/[suikacvs]/messaging/newsportal/newsportal.php
Suika

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.34 - (show annotations) (download)
Mon Feb 11 13:27:21 2002 UTC (22 years, 3 months ago) by wakaba
Branch: MAIN
Changes since 1.33: +5 -1 lines
2002-02-11  wakaba <wakaba@suika.fam.cx>

	* newsportal.php (decode_structured_field): Fix unmatched () 
	of regexp.
	(encode_newsgroup): New function.

1 <?
2 /*
3 Newsportal NNTP<->HTTP Gateway
4
5 Version: 0.24pre3
6
7 this Script is licensed under the GNU Public License
8
9 Author: Florian Amrhein
10 eMail: florian.amrhein@gmx.de
11 Homepage: http://floh.gartenhaus.net
12 */
13
14 /*
15 * the name and the description of a newsgroup
16 */
17 class newsgroupType {
18 var $name;
19 var $description;
20 var $count;
21 }
22
23 /*
24 * Stores a complete article:
25 * - The parsed Header as an headerType
26 * - The bodies and attachments as an array of array of lines
27 */
28 class messageType {
29 var $header;
30 var $body;
31 }
32
33
34
35 /*
36 * Stores the Header of an article
37 */
38 class headerType {
39 var $number; // the Number of an article inside a group
40 var $id; // Message-ID
41 var $from; // eMail of the author
42 var $name; // Name of the author
43 var $subject; // the subject
44 var $newsgroups; // the Newsgroups where the article belongs to
45 var $followup;
46 var $date;
47 var $references;
48 var $content_transfer_encoding;
49 var $mime_version;
50 var $content_type; // array, Content-Type of the Body (Index=0) and the
51 // Attachments (Index>0)
52 var $content_type_charset; // like content_type
53 var $content_type_name; // array of the names of the attachments
54 var $content_type_boundary; // The boundary of an multipart-article.
55 var $answers;
56 var $isAnswer;
57 var $username;
58 var $field;
59 var $isReply;
60 }
61
62 /*
63 * opens the connection to the NNTP-Server
64 *
65 * $server: adress of the NNTP-Server
66 * $port: port of the server
67 */
68 function OpenNNTPconnection($nserver=0,$nport=0) {
69 global $text_error,$server_auth_user,$server_auth_pass,$readonly;
70 global $server,$port;
71 if ($nserver==0) $nserver=$server;
72 if ($nport==0) $nport=$port;
73 $ns=fsockopen($nserver,$nport);
74 $weg=lieszeile($ns); // kill the first line
75 if (substr($weg,0,2) != "20") {
76 echo "<p>".$text_error["error:"]."</p>";
77 } else {
78 if ($ns != false) {
79 fputs($ns,"mode reader\r\n");
80 $weg=lieszeile($ns); // and once more
81 if (substr($weg,0,2) != "20") {
82 echo "<p>".$text_error["error:"]."</p>";
83 }
84 }
85 if ((isset($server_auth_user)) && (isset($server_auth_pass)) &&
86 ($server_auth_user != "")) {
87 fputs($ns,"authinfo user $server_auth_user\r\n");
88 $weg=lieszeile($ns);
89 fputs($ns,"authinfo pass $server_auth_pass\r\n");
90 $weg=lieszeile($ns);
91 if (substr($weg,0,3) != "281") {
92 echo "<p>".$text_error["error:"]."</p>";
93 echo "<p>".$text_error["auth_error"]."</p>";
94 }
95 }
96 }
97 if ($ns==false) echo "<p>".$text_error["connection_failed"]."</p>";
98 return $ns;
99 }
100
101 /*
102 * Close a NNTP connection
103 *
104 * $ns: the handle of the connection
105 */
106 function closeNNTPconnection(&$ns) {
107 if ($ns != false) {
108 fputs($ns,"quit\r\n");
109 fclose($ns);
110 }
111 }
112
113 /*
114 * Validates an email adress
115 *
116 * $address: a string containing the email-address to be validated
117 *
118 * returns true if the address passes the tests, false otherwise.
119 */
120 function validate_email($address)
121 {
122 global $validate_email;
123 $return=true;
124 if (($validate_email >= 1) && ($return == true))
125 $return = (ereg('^[-!#$%&\'*+\\./0-9=?A-Z^_A-z{|}~]+'.'@'.
126 '[-!#$%&\'*+\\/0-9=?A-Z^_A-z{|}~]+\.'.
127 '[-!#$%&\'*+\\./0-9=?A-Z^_A-z{|}~]+$',$address));
128 if (($validate_email >= 2) && ($return == true)) {
129 $addressarray=address_decode($address,"garantiertungueltig");
130 $return=checkdnsrr($addressarray[0]["host"],"MX");
131 if (!$return) $return=checkdnsrr($addressarray[0]["host"],"A");
132 }
133 return($return);
134 }
135
136 /*
137 * decodes a block of 7bit-data in uuencoded format to it's original
138 * 8bit format.
139 * The headerline containing filename and permissions doesn't have to
140 * be included.
141 *
142 * $data: The uuencoded data as a string
143 *
144 * returns the 8bit data as a string
145 *
146 * Note: this function is very slow and doesn't recognize incorrect code.
147 */
148 function uudecode_line($line) {
149 $data=substr($line,1);
150 $length=ord($line[0])-32;
151 $decoded="";
152 for ($i=0; $i<(strlen($data)>>2); $i++) {
153 $pack=substr($data,$i<<2,4);
154 $upack="";
155 $bitmaske=0;
156 for ($o=0; $o<4; $o++) {
157 $g=((ord($pack[3-$o])-32));
158 if ($g==64) $g=0;
159 $bitmaske=$bitmaske | ($g << (6*$o));
160 }
161 $schablone=255;
162 for ($o=0; $o<3; $o++) {
163 $c=($bitmaske & $schablone) >> ($o << 3);
164 $schablone=($schablone << 8);
165 $upack=chr($c).$upack;
166 }
167 $decoded.=$upack;
168 }
169 $decoded=substr($decoded,0,$length);
170 return $decoded;
171 }
172 function uudecode($data) {
173 $d=explode("\n",$data);
174 $u="";
175 for ($i=0; $i<count($d)-1; $i++)
176 $u.=uudecode_line($d[$i]);
177 return $u;
178 }
179
180 /*
181 * returns the mimetype of an filename
182 *
183 * $name: the complete filename of a file
184 *
185 * returns a string containing the mimetype
186 */
187 function get_mimetype_by_filename($name) {
188 $ending=strtolower(strrchr($name,"."));
189 switch($ending) {
190 case ".jpg":
191 $type="image/jpeg";
192 break;
193 case ".gif":
194 $type="image/gif";
195 break;
196 default:
197 $type="text/plain";
198 }
199 return $type;
200 }
201
202 function showPageSelectMenu($article_count,$first) {
203 global $articles_per_page,$file_thread,$file_framethread,$name;
204 /* if (isset($file_framethread)) {
205 $thread=$file_framethread;
206 } else {
207 $thread=$file_thread;
208 }
209 */
210 $pages=ceil($article_count / $articles_per_page);
211 if ($article_count > $articles_per_page)
212 for ($i = 0; $i < $pages; $i++) {
213 echo '[';
214 if ($first != $i*$articles_per_page+1)
215 echo '<a href="'.($i*$articles_per_page+1).'_'.
216 ($i+1)*$articles_per_page.'.html">';
217 echo ($i*$articles_per_page+1).'-';
218 if ($i == $pages-1) {
219 echo $article_count;
220 } else {
221 echo ($i+1)*$articles_per_page;
222 }
223 if ($first != $i*$articles_per_page+1)
224 echo '</a>';
225 echo '] ';
226 }
227 }
228
229 function testGroup($groupname) {
230 global $testgroup;
231 if ($testgroup) {
232 $gf=fopen("groups.txt","r");
233 while (!feof($gf)) {
234 $read=trim(lieszeile($gf));
235 $pos=strpos($read," ");
236 if ($pos != false) {
237 if (substr($read,0,$pos)==trim($groupname)) return true;
238 } else {
239 if ($read == trim($groupname)) return true;
240 }
241 }
242 fclose($gf);
243 return false;
244 } else {
245 return true;
246 }
247 }
248
249 function testGroups($newsgroups) {
250 $groups=explode(",",$newsgroups);
251 $count=count($groups);
252 $return="";
253 $o=0;
254 for ($i=0; $i<$count; $i++) {
255 if (testgroup($groups[$i])) {
256 if ($o>0) $return.=",";
257 $o++;
258 $return.=$groups[$i];
259 }
260 }
261 return($return);
262 }
263
264 /*
265 * read one line from the NNTP-server
266 */
267 function lieszeile(&$ns) {
268 if ($ns != false) {
269 $t=str_replace("\n","",str_replace("\r","",fgets($ns,1200)));
270 return $t;
271 }
272 }
273
274 /*
275 * Split an internet-address string into its parts. An address string could
276 * be for example:
277 * - user@host.domain (Realname)
278 * - "Realname" <user@host.domain>
279 * - user@host.domain
280 *
281 * The address will be split into user, host (incl. domain) and realname
282 *
283 * $adrstring: The string containing the address in internet format
284 * $defaulthost: The name of the host which should be returned if the
285 * address-string doesn't contain a hostname.
286 *
287 * returns an hash containing the fields "mailbox", "host" and "personal"
288 */
289 function address_decode($adrstring,$defaulthost) {
290 $parsestring=trim($adrstring);
291 $len=strlen($parsestring);
292 $at_pos=strpos($parsestring,'@'); // find @
293 $ka_pos=strpos($parsestring,"("); // find (
294 $kz_pos=strpos($parsestring,')'); // find )
295 $ha_pos=strpos($parsestring,'<'); // find <
296 $hz_pos=strpos($parsestring,'>'); // find >
297 $space_pos=strpos($parsestring,')'); // find ' '
298 $email="";
299 $mailbox="";
300 $host="";
301 $personal="";
302 if ($space_pos != false) {
303 if (($ka_pos != false) && ($kz_pos != false)) {
304 $personal=substr($parsestring,$ka_pos+1,$kz_pos-$ka_pos-1);
305 $email=trim(substr($parsestring,0,$ka_pos-1));
306 }
307 } else {
308 $email=$adrstring;
309 }
310 if (($ha_pos != false) && ($hz_pos != false)) {
311 $email=trim(substr($parsestring,$ha_pos+1,$hz_pos-$ha_pos-1));
312 $personal=substr($parsestring,0,$ha_pos-1);
313 }
314 if ($at_pos != false) {
315 $mailbox=substr($email,0,strpos($email,'@'));
316 $host=substr($email,strpos($email,'@')+1);
317 } else {
318 $mailbox=$email;
319 $host=$defaulthost;
320 }
321 $personal=trim($personal);
322 if (substr($personal,0,1) == '"') $personal=substr($personal,1);
323 if (substr($personal,strlen($personal)-1,1) == '"')
324 $personal=substr($personal,0,strlen($personal)-1);
325 $result["mailbox"]=trim($mailbox);
326 $result["host"]=trim($host);
327 // $personal = mb_convert_encoding($personal, "EUC-JP", "auto");
328 if ($personal!="") $result["personal"]=$personal;
329 $complete[]=$result;
330 return ($complete);
331 }
332
333
334
335 function readGroups($server,$port) {
336 $ns=OpenNNTPconnection($server,$port);
337 if ($ns == false) return false;
338 $gf=fopen("groups.txt","r");
339 while (!feof($gf)) {
340 $gruppe=new newsgroupType;
341 $tmp=trim(lieszeile($gf));
342 $pos=strpos($tmp," ");
343 if ($pos != false) {
344 $gruppe->name=substr($tmp,0,$pos);
345 $desc=substr($tmp,$pos);
346 } else {
347 $gruppe->name=$tmp;
348 fputs($ns,"xgtitle $gruppe->name\r\n");
349 $response=liesZeile($ns);
350 if (strcmp(substr($response,0,3),"282") == 0) {
351 $neu=liesZeile($ns);
352 do {
353 $response=$neu;
354 if ($neu != ".") $neu=liesZeile($ns);
355 } while ($neu != ".");
356 $desc=strrchr($response,"\t");
357 if (strcmp($response,".") == 0) {
358 $desc="-";
359 }
360 } else {
361 $desc=$response;
362 }
363 if (strcmp(substr($response,0,3),"500") == 0)
364 $desc="-";
365 }
366 if (strcmp($desc,"") == 0) $desc="-";
367 $gruppe->description=$desc;
368 fputs($ns,"group ".$gruppe->name."\r\n");
369 $response=liesZeile($ns);
370 $t=strchr($response," ");
371 $t=substr($t,1,strlen($t)-1);
372 $gruppe->count=substr($t,0,strpos($t," "));
373 if ((strcmp(trim($gruppe->name),"") != 0) &&
374 (substr($gruppe->name,0,1) != "#"))
375 $newsgroups[]=$gruppe;
376 }
377 fclose($gf);
378 closeNNTPconnection($ns);
379 return $newsgroups;
380 }
381
382 /*
383 * print the group names from an array to the webpage
384 */
385 function showgroups($gruppen) {
386 if ($gruppen == false) return;
387 global $file_thread,$text_groups;
388 $c = count($gruppen);
389 echo "<table>\n";
390 echo "<tr><td>#</td><td>".$text_groups["newsgroup"].
391 "</td><td>".$text_groups["description"]."</td></tr>\n";
392 for($i = 0 ; $i < $c ; $i++) {
393 $g = $gruppen[$i];
394 echo "<tr><td>";
395 echo "$g->count</td><td>";
396 echo '<a ';
397 if ((isset($frame_threadframeset)) && ($frame_threadframeset != ""))
398 echo 'target="'.$frame_threadframeset.'" ';
399 echo 'href="'.$file_thread.'/'.encode_newsgroup ($g->name).'/index">'.$g->name."</a></td>\n";
400 echo "<td>$g->description</td></tr>\n";
401 flush();
402 }
403 echo "</table>\n";
404 }
405
406 function encode_newsgroup ($groupname) {
407 return urlencode (str_replace ('.', ':', $groupname));
408 }
409
410 /*
411 * gets a list of aviable articles in the group $groupname
412 */
413 function getArticleList(&$von,$groupname) {
414 fputs($von,"listgroup $groupname \r\n");
415 $zeile=lieszeile($von);
416 $zeile=lieszeile($von);
417 while(strcmp($zeile,".") != 0) {
418 $articleList[] = trim($zeile);
419 $zeile=lieszeile($von);
420 }
421 if (!isset($articleList)) $articleList="-";
422 return $articleList;
423 }
424
425 /*
426 * Decode quoted-printable or base64 encoded headerlines
427 *
428 * $value: The to be decoded line
429 *
430 * returns the decoded line
431 */
432 function headerDecode($value) {
433 if (eregi('=\?.*\?.\?.*\?=',$value)) { // is there anything encoded?
434 if (eregi('=\?.*\?Q\?.*\?=',$value)) { // quoted-printable decoding
435 $result1=eregi_replace('(.*)=\?.*\?Q\?(.*)\?=(.*)','\1',$value);
436 $result2=eregi_replace('(.*)=\?.*\?Q\?(.*)\?=(.*)','\2',$value);
437 $result3=eregi_replace('(.*)=\?.*\?Q\?(.*)\?=(.*)','\3',$value);
438 $result2=str_replace("_"," ",quoted_printable_decode($result2));
439 $newvalue=$result1.$result2.$result3;
440 }
441 if (eregi('=\?.*\?B\?.*\?=',$value)) { // base64 decoding
442 $result1=eregi_replace('(.*)=\?.*\?B\?(.*)\?=(.*)','\1',$value);
443 $result2=eregi_replace('(.*)=\?.*\?B\?(.*)\?=(.*)','\2',$value);
444 $result3=eregi_replace('(.*)=\?.*\?B\?(.*)\?=(.*)','\3',$value);
445 $result2=base64_decode($result2);
446 $newvalue=$result1.$result2.$result3;
447 }
448 if (!isset($newvalue)) // nothig of them, must be an unknown encoding...
449 $newvalue=$value;
450 else
451 $newvalue=headerDecode($newvalue); // maybe there are more encoded
452 return(mb_convert_encoding($newvalue, "EUC-JP", "auto")); // parts
453 } else {
454 return(mb_convert_encoding(decode_structured_body($value), "EUC-JP", "auto"));
455 }
456 }
457
458
459 function parse_header($hdr,$number="") {
460 for ($i=count($hdr)-1; $i>0; $i--)
461 if (preg_match("/^(\x09|\x20)/",$hdr[$i]))
462 $hdr[$i-1]=$hdr[$i-1].ltrim($hdr[$i]);
463 $header = new headerType;
464 $header->isAnswer=false;
465 for ($count=0;$count<count($hdr);$count++) {
466 $variable=substr($hdr[$count],0,strpos($hdr[$count],":"));
467 $value=trim(substr($hdr[$count],strpos($hdr[$count],":")+1));
468 $header->field[strtolower($variable)][] = $value;
469 switch (strtolower($variable)) {
470 case "from":
471 $fromline=address_decode(headerDecode($value),"nirgendwo");
472 if (!isset($fromline[0]["host"])) $fromline[0]["host"]="";
473 $header->from=$fromline[0]["mailbox"]."@".$fromline[0]["host"];
474 $header->username=$fromline[0]["mailbox"];
475 if (!isset($fromline[0]["personal"])) {
476 $header->name="";
477 } else {
478 $header->name=$fromline[0]["personal"];
479 }
480 break;
481 case "message-id":
482 $header->id=$value;
483 break;
484 case "subject":
485 $header->subject = decode_unstructured_body($value);
486 break;
487 case "newsgroups":
488 $header->newsgroups=$value;
489 break;
490 case "content-transfer-encoding":
491 $header->content_transfer_encoding=trim(strtolower($value));
492 break;
493 case "content-type":
494 $header->content_type=array();
495 $subheader=split(";",$value);
496 $header->content_type[0]=strtolower(trim($subheader[0]));
497 for ($i=1; $i<count($subheader); $i++) {
498 $gleichpos=strpos($subheader[$i],"=");
499 if ($gleichpos) {
500 $subvariable=trim(substr($subheader[$i],0,$gleichpos));
501 $subvalue=trim(substr($subheader[$i],$gleichpos+1));
502 if (($subvalue[0]=='"') &&
503 ($subvalue[strlen($subvalue)-1]=='"'))
504 $subvalue=substr($subvalue,1,strlen($subvalue)-2);
505 switch($subvariable) {
506 case "charset":
507 $header->content_type_charset=array(strtolower($subvalue));
508 break;
509 case "name":
510 $header->content_type_name=array($subvalue);
511 break;
512 case "boundary":
513 $header->content_type_boundary=$subvalue;
514 }
515 }
516 }
517 break;
518 case "references":
519 $ref=ereg_replace("> *<", "> <", trim($value));
520 while (strpos($ref,"> <") != false) {
521 $header->references[]=substr($ref,0,strpos($ref," "));
522 $ref=substr($ref,strpos($ref,"> <")+2);
523 }
524 $header->references[]=trim($ref);
525 break;
526 case "date":
527 $header->date = strtotime(trim($value));
528 break;
529 case "followup-to":
530 $header->followup=trim($value);
531 break;
532 /*
533 case "x-newsreader":
534 case "x-mailer":
535 case "user-agent":
536 $header->user_agent= decode_structured_body($value);
537 break;
538 */
539 }
540 }
541 if (!isset($header->content_type[0]))
542 $header->content_type[0]="text/plain";
543 if (!isset($header->content_transfer_encoding))
544 $header->content_transfer_encoding="8bit";
545 if ($number != "") $header->number=$number;
546 return $header;
547 }
548
549 function decode_unstructured_body ($body) {
550 $patterns = array (
551 "/(=\\?[^\\x00-\\x20()<>@,;:\\\"\\/\\[\\]?.=\\x7F]+\\?[BQ]\\?[^\\x00-\\x20\\x3F\\x7F]*\\?=)/ei",
552 );
553 $replace = array (
554 "mb_decode_mimeheader('\\1')",
555 );
556 return preg_replace ($patterns, $replace,
557 mb_convert_encoding(fake_jisx0213($body), "EUC-JP", "auto"));
558 }
559
560 function decode_structured_body ($body) {
561 $patterns = array (
562 "/\"((?:[^\"\\\\]+|\\\\.)*)\"/e",
563 "/\(((?:[^()\\\\]+|\\\\.|(?:\((?:[^()\\\\]+|\\\\.|(?:\((?:[^)\\\\]+|\\\\.\
564 )*\)))*\)))*)\)/e",
565 );
566 $replace = array (
567 "mb_convert_encoding(fake_jisx0213(decode_quoted_pair('\\1')),'EUC-JP','auto')",
568 "'('.mb_convert_encoding(fake_jisx0213(decode_quoted_pair('\\1')),
569 'EUC-JP','auto').')'",
570 );
571 return preg_replace ($patterns, $replace, $body);
572 }
573
574 function decode_quoted_pair($value) {
575 $value = ereg_replace('\\\\(\\\\")', "\\1", $value);
576 return ereg_replace('\\\\(.)', "\\1", $value);
577 }
578
579 function fake_jisx0213 ($value) {
580 $value = preg_replace ("/\\x1B\\\$\\(O/", "\x1B\\\$B", $value);
581 $value = preg_replace ("/\\x1B\\\$\\(P/", "\x1B\\\$(D", $value);
582 return $value;
583 }
584
585 function decode_body($body,$encoding) {
586 $bodyzeile="";
587 switch ($encoding) {
588 case "base64":
589 $body=base64_decode($body);
590 break;
591 case "quoted-printable":
592 $body=Quoted_printable_decode($body);
593 $body=str_replace("=\n","",$body);
594 // default:
595 // $body=str_replace("\n..\n","\n.\n",$body);
596 }
597 return $body;
598 }
599
600 function parse_message($rawmessage) {
601 global $attachment_delete_alternative,$attachment_uudecode;
602 // Read the header of the message:
603 $count_rawmessage=count($rawmessage);
604 $message = new messageType;
605 $rawheader=array();
606 $i=0;
607 while ($rawmessage[$i] != "") {
608 $rawheader[]=$rawmessage[$i];
609 $i++;
610 }
611 // Parse the Header:
612 $message->header=parse_header($rawheader);
613 // Now we know if the message is a mime-multipart message:
614 $content_type=split("/",$message->header->content_type[0]);
615 if ($content_type[0]=="multipart") {
616 $message->header->content_type=array();
617 // We have multible bodies, so we split the message into its parts
618 $boundary="--".$message->header->content_type_boundary;
619 // lets find the first part
620 while($rawmessage[$i] != $boundary)
621 $i++;
622 $i++;
623 $part=array();
624 while($i<=$count_rawmessage) {
625 if (($rawmessage[$i]==$boundary) || ($i==$count_rawmessage-1) ||
626 ($rawmessage[$i]==$boundary.'--')) {
627 $partmessage=parse_message($part);
628 // merge the content-types of the message with those of the part
629 for ($o=0; $o<count($partmessage->header->content_type); $o++) {
630 $message->header->content_type[]=
631 $partmessage->header->content_type[$o];
632 $message->header->content_type_charset[]=
633 $partmessage->header->content_type_charset[$o];
634 $message->header->content_type_name[]=
635 $partmessage->header->content_type_name[$o];
636 $message->body[]=$partmessage->body[$o];
637 }
638 $part=array();
639 } else {
640 if ($i<$count_rawmessage)
641 $part[]=$rawmessage[$i];
642 }
643 if ($rawmessage[$i]==$boundary.'--') break;
644 $i++;
645 }
646 // Is this a multipart/alternative multipart-message? Do we have to
647 // delete all non plain/text parts?
648 if (($attachment_delete_alternative) &&
649 ($content_type[1]=="alternative")) {
650 $plaintext=false;
651 for ($o=0; $o<count($message->header->content_type); $o++) {
652 if ($message->header->content_type[$o]=="text/plain")
653 $plaintext=true; // we found at least one text/plain
654 }
655 if ($plaintext) { // now we can delete the other parts
656 for ($o=0; $o<count($message->header->content_type); $o++) {
657 if ($message->header->content_type[$o]!="text/plain") {
658 unset($message->header->content_type[$o]);
659 unset($message->header->content_type_name[$o]);
660 unset($message->header->content_type_charset[$o]);
661 unset($message->body[$o]);
662 }
663 }
664 }
665 }
666 } else {
667 // No mime-attachments in the message:
668 $body="";
669 $uueatt=0; // as default we have no uuencoded attachments
670 for($i++;$i<$count_rawmessage; $i++) {
671 // do we have an inlay uuencoded file?
672 if ((strtolower(substr($rawmessage[$i],0,5))!="begin") ||
673 ($attachment_uudecode==false)) {
674 $body.=$rawmessage[$i]."\n";
675 // yes, it seems, we have!
676 } else {
677 $old_i=$i;
678 $uue_infoline_raw=$rawmessage[$i];
679 $uue_infoline=explode(" ",$uue_infoline_raw);
680 $uue_data="";
681 $i++;
682 while($rawmessage[$i]!="end") {
683 if (strlen(trim($rawmessage[$i])) > 2)
684 $uue_data.=$rawmessage[$i]."\n";
685 $i++;
686 }
687 // now write the data in an attachment
688 $uueatt++;
689 $message->body[$uueatt]=uudecode($uue_data);
690 $message->header->content_type_name[$uueatt]="";
691 for ($o=2; $o<count($uue_infoline); $o++)
692 $message->header->content_type_name[$uueatt].=$uue_infoline[$o];
693 $message->header->content_type[$uueatt]=
694 get_mimetype_by_filename($message->header->content_type_name[$uueatt]);
695 }
696 }
697 // if ($message->header->content_type[0]=="text/plain") {
698 // $body=trim($body);
699 // if ($body=="") $body=" ";
700 // }
701 $body=decode_body($body,$message->header->content_transfer_encoding);
702 $message->body[0] = mb_convert_encoding($body, "EUC-JP", "auto");
703 }
704 if (!isset($message->header->content_type_charset))
705 $message->header->content_type_charset=array("ISO-8859-1");
706 if (!isset($message->header->content_type_name))
707 $message->header->content_type_name=array("unnamed");
708 for ($o=0; $o<count($message->body); $o++) {
709 if (!isset($message->header->content_type_charset[$o]))
710 $message->header->content_type_charset[$o]="ISO-8859-1";
711 if (!isset($message->header->content_type_name[$o]))
712 $message->header->content_type_name[$o]="unnamed";
713 }
714 return $message;
715 }
716
717 /*
718 * read an article from the newsserver or the spool-directory
719 *
720 * $id: the Message-ID of an article
721 * $bodynum: the number of the attachment:
722 * -1: return only the header without any bodies or attachments.
723 * 0: the body
724 * 1: the first attachment...
725 *
726 * The function returns an article as an messageType or false if the article
727 * doesn't exists on the newsserver or doesn't contain the given
728 * attachment.
729 */
730 function read_message($id,$bodynum=0,$group="") {
731 global $cache_articles,$spooldir,$text_error;
732 $message = new messageType;
733 if ((isset($cache_articles)) && ($cache_articles == true)) {
734 if ((ereg('^[0-9]+$',$id)) && ($group != ''))
735 $filename=$group.'_'.$id;
736 else
737 $filename=base64_encode($id);
738 $cachefilename_header=$spooldir."/".$filename.'.header';
739 $cachefilename_body=$spooldir."/".$filename.'.body';
740 if (file_exists($cachefilename_header)) {
741 $cachefile=fopen($cachefilename_header,"r");
742 $message->header=unserialize(fread($cachefile,filesize($cachefilename_header)));
743 fclose($cachefile);
744 } else {
745 unset($message->header);
746 }
747 // Is a non-existing attachment of an article requested?
748 if ((isset($message->header)) &&
749 ($bodynum!= -1) &&
750 (!isset($message->header->content_type[$bodynum])))
751 return false;
752 if ((file_exists($cachefilename_body.$bodynum)) &&
753 ($bodynum != -1)) {
754 $cachefile=fopen($cachefilename_body.$bodynum,"r");
755 $message->body[$bodynum]=
756 fread($cachefile,filesize($cachefilename_body.$bodynum));
757 fclose($cachefile);
758 }
759 }
760 if ((!isset($message->header)) ||
761 ((!isset($message->body[$bodynum])) &&
762 ($bodynum != -1))) {
763 if (!isset($ns)) $ns=openNNTPconnection();
764 if ($group != "") {
765 fputs($ns,"group ".$group."\r\n");
766 $zeile=lieszeile($ns);
767 }
768 fputs($ns,'article '.$id."\r\n");
769 $zeile=lieszeile($ns);
770 if (substr($zeile,0,3) != "220")
771 return false;
772 $rawmessage=array();
773 $line=lieszeile($ns);
774 #$line=mb_convert_encoding($line, "EUC-JP", "ISO-2022-JP");
775 while(strcmp($line,".") != 0) {
776 $rawmessage[]=$line;
777 $line=lieszeile($ns);
778 #$line=mb_convert_encoding($line, "EUC-JP", "ISO-2022-JP");
779 }
780 $message=parse_message($rawmessage);
781 if (ereg('^[0-9]+$',$id)) $message->header->number=$id;
782 // write header, body and attachments to disk
783 if ((isset($cache_articles)) && ($cache_articles == true)) {
784 $cachefile=fopen($cachefilename_header,"w");
785 if ($cachefile) {
786 fputs($cachefile,serialize($message->header));
787 }
788 fclose($cachefile);
789 for ($i=0; $i<count($message->header->content_type); $i++) {
790 if (isset($message->body[$i])) {
791 $cachefile=fopen($cachefilename_body.$i,"w");
792 fwrite($cachefile,$message->body[$i]);
793 fclose($cachefile);
794 }
795 }
796 }
797 }
798 return $message;
799 }
800
801 function textwrap($text, $wrap=80, $break="\n"){
802 $len = strlen($text);
803 if ($len > $wrap) {
804 $h = ''; // massaged text
805 $lastWhite = 0; // position of last whitespace char
806 $lastChar = 0; // position of last char
807 $lastBreak = 0; // position of last break
808 // while there is text to process
809 while ($lastChar < $len) {
810 $char = substr($text, $lastChar, 1); // get the next character
811 // if we are beyond the wrap boundry and there is a place to break
812 if (($lastChar - $lastBreak > $wrap) && ($lastWhite > $lastBreak)) {
813 $h .= substr($text, $lastBreak, ($lastWhite - $lastBreak)) . $break;
814 $lastChar = $lastWhite + 1;
815 $lastBreak = $lastChar;
816 }
817 // You may wish to include other characters as valid whitespace...
818 if ($char == ' ' || $char == chr(13) || $char == chr(10)) {
819 $lastWhite = $lastChar; // note the position of the last whitespace
820 }
821 $lastChar = $lastChar + 1; // advance the last character position by one
822 }
823 $h .= substr($text, $lastBreak); // build line
824 } else {
825 $h = $text; // in this case everything can fit on one line
826 }
827 return $h;
828 }
829
830 /*
831 * makes URLs clickable
832 *
833 * $comment: A text-line probably containing links.
834 *
835 * the function returns the text-line with HTML-Links to the links or
836 * email-adresses.
837 */
838 function html_parse($comment, $group = "", $msgidregex = "") {
839 global $frame_externallink;
840 global $file_article;
841 if ((isset($frame_externallink)) && ($frame_externallink != "")) {
842 $target=' TARGET="'.$frame_externallink.'" ';
843 } else {
844 $target=' ';
845 }
846 $ncomment = eregi_replace( 'http://([-a-z0-9_./~@?=%#&;]+)', '<a'.$target.'href="http://\1">http://\1</a>', $comment);
847 if ($ncomment == $comment)
848 $ncomment = eregi_replace( '(www\.[-a-z]+\.(de|int|eu|dk|org|net|at|ch|com|jp))','<a'.$target.'href="http://\1">\1</a>',$comment);
849 $comment=$ncomment;
850 $comment = eregi_replace( 'https://([-a-z0-9_./~@?=%#&;\n]+)', '<a'.$target.'href="https://\1">https://\1</a>', $comment);
851 $comment = eregi_replace( 'gopher://([-a-z0-9_./~@?=%\n]+)','<a'.$target.'href="gopher://\1">gopher://\1</a>', $comment);
852 $comment = eregi_replace( 'news://([-a-z0-9_./~@?=%\n]+)','<a'.$target.'href="news://\1">news://\1</a>', $comment);
853 $comment = eregi_replace( 'ftp://([-a-z0-9_./~@?=%\n]+)', '<a'.$target.'href="ftp://\1">ftp://\1</a>', $comment);
854 if(!empty($msgidregex) && ereg($msgidregex, $comment)){
855 //$comment = ereg_replace( $msgidregex, '<a'.$target.'href="http://'.$SERVER_NAME.'/\1">&lt;\1&gt;</a>', $comment);
856 $comment = preg_replace( '/'.$msgidregex.'/e', "'<a$target'.'href=\"../../'.addslashes('$file_article').'/'.urlencode('$group').'/'.urlencode('<\\2>').'.html\">\\1\\2\\3</a>'", $comment);
857 } else{
858 $comment = eregi_replace( '([-a-z0-9_./n]+)@([-a-z0-9_.]+)','<a href="mailto:\1@\2">\1@\2</a>', $comment);
859 }
860 return($comment);
861 }
862
863 function uri_to_link($comment, $group = "", $msgidregex = "") {
864 global $frame_externallink;
865 global $file_article;
866 $comment = preg_replace (
867 '"((?:https?|mailto|urn|news|ftp|irc|mid|data|nntp|gother)):((?:[-_.!~*\'()A-Z0-9:;@=+$,%?/]+|&amp;)+)(#(?:[-_.!~*\'()A-Z0-9;/?:@&=+$,%]+|&amp;)+)?"ie',
868 'uri_to_link_uri("\1", "\2", "\3")',
869 $comment);
870 return($comment);
871 }
872
873 function uri_to_link_uri ($scheme, $body, $fragment) {
874 global $file_article;
875 switch (strtolower($scheme)) {
876 case "urn":
877 case "data":
878 $uri = '/uri-res/N2L?'.urlencode($scheme.':'.$body);
879 break;
880 case "news":
881 if (!preg_match('"^//"', $body)) {
882 $uri = "../../".addslashes($file_article).'/junk/%3C'.$nbody.'%3E';
883 } else {
884 $uri = $scheme.':'.$body;
885 }
886 break;
887 case "mid":
888 $nbody = preg_replace('"/.*$"', "", $body);
889 $uri = "../../".addslashes($file_article).'/junk/%3C'.$nbody.'%3E';
890 break;
891 default:
892 $uri = $scheme.':'.$body;
893 break;
894 }
895 $uri = $uri . $fragment;
896 if (!empty($uri)) {
897 $uri = '<a href="'.$uri.'">'.$scheme.':'.$body.$fragment.'</a>';
898 }
899 return $uri;
900 }
901
902
903
904 /*
905 * read the header of an article in plaintext into an array
906 * $articleNumber can be the number of an article or its message-id.
907 */
908 function readPlainHeader(&$von,$group,$articleNumber) {
909 fputs($von,"group $group\r\n");
910 $zeile=lieszeile($von);
911 fputs($von,"head $articleNumber\r\n");
912 $zeile=lieszeile($von);
913 if (substr($zeile,0,3) != "221") {
914 echo $text_error["article_not_found"];
915 $header=false;
916 } else {
917 $zeile=lieszeile($von);
918 $body="";
919 while(strcmp(trim($zeile),".") != 0) {
920 $body .= $zeile."\n";
921 $zeile=lieszeile($von);
922 }
923 return split("\n",str_replace("\r\n","\n",$body));
924 }
925 }
926
927 function readArticles(&$von,$groupname,$articleList) {
928 for($i = 0; $i <= count($articleList)-1 ; $i++) {
929 $temp=read_header($von,$articleList[$i]);
930 $articles[$temp->id] = $temp;
931 }
932 return $articles;
933 }
934
935 /*
936 * Remove re: aw: etc. from a subject.
937 *
938 * $subject: a string containing the complete Subject
939 *
940 * The function removes the re:, aw: etc. from $subject end returns true
941 * if it removed anything, and false if not.
942 */
943 function splitSubject(&$subject) {
944 $s=eregi_replace('^(aw:|re:|re\[2\]:| )+','',$subject);
945 $return=($s != $subject);
946 $subject=$s;
947 return $return;
948 }
949
950 function interpretOverviewLine($zeile,$overviewformat,$groupname) {
951 $return="";
952 $overviewfmt=explode("\t",$overviewformat);
953 echo " "; // keep the connection to the webbrowser alive
954 flush(); // while generating the message-tree
955 $over=split("\t",$zeile,count($overviewfmt)-1);
956 $article=new headerType;
957 for ($i=0; $i<count($overviewfmt)-1; $i++) {
958 if ($overviewfmt[$i]=="Subject:") {
959 $subject=headerDecode($over[$i+1]);
960 $article->isReply=splitSubject($subject);
961 $article->subject=$subject;
962 }
963 if ($overviewfmt[$i]=="Date:") {
964 $article->date = strtotime($over[$i+1]);
965 }
966 if ($overviewfmt[$i]=="From:") {
967 $fromline=address_decode(headerDecode($over[$i+1]),"nirgendwo");
968 $article->from=$fromline[0]["mailbox"]."@".$fromline[0]["host"];
969 $article->username=$fromline[0]["mailbox"];
970 if (!isset($fromline[0]["personal"])) {
971 $article->name=$fromline[0]["mailbox"];
972 if (strpos($article->name,'%')) {
973 $article->name=substr($article->name,0,strpos($article->name,'%'));
974 }
975 $article->name=strtr($article->name,'_',' ');
976 } else {
977 $article->name=$fromline[0]["personal"];
978 }
979 }
980 if ($overviewfmt[$i]=="Message-ID:") $article->id=$over[$i+1];
981 if (($overviewfmt[$i]=="References:") && ($over[$i+1] != ""))
982 $article->references=explode(" ",$over[$i+1]);
983 }
984 $article->number=$over[0];
985 $article->isAnswer=false;
986 return($article);
987 }
988
989 /*
990 * Rebuild the Overview-File
991 */
992 function rebuildOverview(&$von,$groupname,$poll) {
993 global $spooldir,$maxarticles,$maxfetch,$initialfetch,$maxarticles_extra;
994 global $text_error,$text_thread,$compress_spoolfiles,$server;
995 $idstring="0.22,".$server.",".$compress_spoolfiles.",".$maxarticles.",".
996 $maxarticles_extra.",".$maxfetch.",".$initialfetch;
997 fputs($von,"list overview.fmt\r\n"); // find out the format of the
998 $tmp=liesZeile($von); // xover-command
999 $zeile=liesZeile($von);
1000 while (strcmp($zeile,".") != 0) {
1001 $overviewfmt[]=$zeile;
1002 $zeile=liesZeile($von);
1003 }
1004 $overviewformat=implode("\t",$overviewfmt);
1005 $spoolfilename=$spooldir."/".$groupname."-data.dat";
1006 fputs($von,"group $groupname\r\n"); // select a group
1007 $groupinfo=explode(" ",liesZeile($von));
1008 if (substr($groupinfo[0],0,1) != 2) {
1009 echo "<p>".$text_error["error:"]."</p>";
1010 echo "<p>".$text_thread["no_such_group"]."</p>";
1011 flush();
1012 } else {
1013 $infofilename=$spooldir."/".$groupname."-info.txt";
1014 $spoolopenmodus="n";
1015 if (!((file_exists($infofilename)) && (file_exists($spoolfilename)))) {
1016 $spoolopenmodus="w";
1017 } else {
1018 $infofile=fopen($infofilename,"r");
1019 $oldid=fgets($infofile,100);
1020 if (trim($oldid) != $idstring) {
1021 echo "<!-- Database Error, rebuilding Database...-->\n";
1022 $spoolopenmodus="w";
1023 }
1024 $oldgroupinfo=explode(" ",trim(fgets($infofile,200)));
1025 fclose($infofile);
1026 if ($groupinfo[3] < $oldgroupinfo[1]) {
1027 $spoolopenmodus="w";
1028 }
1029 if ($maxarticles == 0) {
1030 if ($groupinfo[2] != $oldgroupinfo[0]) $spoolopenmodus="w";
1031 } else {
1032 if ($groupinfo[2] > $oldgroupinfo[0]) $spoolopenmodus="w";
1033 }
1034 if (($spoolopenmodus == "n") && ($groupinfo[3] > $oldgroupinfo[1]))
1035 $spoolopenmodus="a";
1036 }
1037 if ($spoolopenmodus=="a") {
1038 $firstarticle=$oldgroupinfo[1]+1;
1039 $lastarticle=$groupinfo[3];
1040 }
1041 if ($spoolopenmodus=="w") {
1042 $firstarticle=$groupinfo[2];
1043 $lastarticle=$groupinfo[3];
1044 }
1045 if ($spoolopenmodus != "n") {
1046 if ($maxarticles != 0) {
1047 if ($spoolopenmodus == "w") {
1048 $firstarticle=$lastarticle-$maxarticles+1;
1049 if ($firstarticle < $groupinfo[2])
1050 $firstarticle=$groupinfo[2];
1051 } else {
1052 if ($lastarticle-$oldgroupinfo[0]+1 > $maxarticles + $maxarticles_extra) {
1053 $firstarticle=$lastarticle-$maxarticles+1;
1054 $spoolopenmodus="w";
1055 }
1056 }
1057 }
1058 if (($maxfetch!=0) && (($lastarticle-$firstarticle+1) > $maxfetch)) {
1059 if ($spoolopenmodus=="w") {
1060 $tofetch=($initialfetch != 0) ? $initialfetch : $maxfetch;
1061 $lastarticle=$firstarticle+$tofetch-1;
1062 } else {
1063 $lastarticle=$firstarticle+$maxfetch-1;
1064 }
1065 }
1066 }
1067 echo "<!--openmodus: ".$spoolopenmodus."-->\n";
1068 if ($spoolopenmodus != "w") $headers=loadThreadData($groupname);
1069 if ($spoolopenmodus != "n") {
1070 fputs($von,"xover ".$firstarticle."-".$lastarticle."\r\n"); // and read the overview
1071 $tmp=liesZeile($von);
1072 if (substr($tmp,0,3) == "224") {
1073 $zeile=liesZeile($von);
1074 while ($zeile != ".") {
1075 $article=interpretOverviewLine($zeile,$overviewformat,$groupname);
1076 $headers[$article->id]=$article;
1077 if($poll) {
1078 echo $article->number.", "; flush();
1079 read_message($article->number,0,$groupname);
1080 }
1081 $zeile=lieszeile($von);
1082 }
1083 }
1084 if (file_exists($spoolfilename)) unlink($spoolfilename);
1085 if (count($headers)>0) {
1086 $infofile=fopen($infofilename,"w");
1087 if ($spoolopenmodus=="a") $firstarticle=$oldgroupinfo[0];
1088 fputs($infofile,$idstring."\n");
1089 fputs($infofile,$firstarticle." ".$lastarticle."\r\n");
1090 fclose($infofile);
1091 reset($headers);
1092 $c=current($headers); // read one article
1093 for ($i=0 ; $i<=count($headers)-1 ; $i++) {
1094 if (($c->isAnswer == false) &&
1095 (isset($c->references[0]))) { // is the article an answer to an
1096 // other article?
1097 $o=count($c->references)-1;
1098 $ref=$c->references[$o];
1099 while (($o >= 0) && (!isset($headers[$ref]))) { // try to find a
1100 $ref=$c->references[$o]; // matching article
1101 $o--; // to the reference
1102 }
1103 if ($o >= 0) { // found a matching article?
1104 $c->isAnswer=true; // so the Article is an answer
1105 $headers[$c->id]=$c;
1106 $headers[$ref]->answers[]=$c->id; // the referenced article gets
1107 // the ID of the article
1108 }
1109 }
1110 $c=next($headers);
1111 }
1112 reset($headers);
1113 saveThreadData($headers,$groupname);
1114 }
1115 }
1116 return((isset($headers)) ? $headers : false);
1117 }
1118 }
1119
1120
1121 /*
1122 * Read the Overview.
1123 * Format of the overview-file:
1124 * message-id
1125 * date
1126 * subject
1127 * author
1128 * email
1129 * references
1130 */
1131 function mycompare($a,$b) {
1132 global $thread_sorting;
1133 if ($a->date==$b->date) $r=0;
1134 $r=($a->date<$b->date) ? -1 : 1;
1135 return $r*$thread_sorting;
1136 }
1137 function readOverview(&$von,$groupname,$readmode = 1,$poll=false) {
1138 global $text_error, $maxarticles;
1139 global $spooldir,$thread_sorting;
1140 if (!testGroup($groupname)) {
1141 echo $text_error["read_access_denied"];
1142 return;
1143 }
1144 if ($von == false) return false;
1145 if (($von!=false) && ($readmode > 0))
1146 $articles=rebuildOverview($von,$groupname,$poll);
1147 if ((isset($articles)) && ($articles)) {
1148 if (($thread_sorting != 0) && (count($articles)>0))
1149 uasort($articles,'mycompare');
1150 return $articles;
1151 } else {
1152 return false;
1153 }
1154 }
1155
1156 function str_change($str,$pos,$char) {
1157 return(substr($str,0,$pos).$char.substr($str,$pos+1,strlen($str)-$pos));
1158 }
1159
1160 function formatDate($c) {
1161 global $age_count,$age_time,$age_color,$date_format;
1162 $return="";
1163 $currentTime=time();
1164 $color="";
1165 if ($age_count > 0)
1166 for($t = $age_count; $t >= 1; $t--)
1167 if ($currentTime - $c->date < $age_time[$t]) $color = $age_color[$t];
1168 if ($color != "") $return .= '<font color="'.$color.'">';
1169 if (!isset($date_format)) $date_format = "d.m.";
1170 $return .= date($date_format,$c->date); // format the date
1171 if ($color != "") $return .= '</font>';
1172 return($return);
1173 }
1174
1175 function calculateTree($newtree,$depth,$num,$liste,$c) {
1176 if ((isset($c->answers[0])) && (count($c->answers)>0)) {
1177 $newtree.="*";
1178 } else {
1179 if ($depth == 1) {
1180 $newtree.="o";
1181 } else {
1182 $newtree.="-";
1183 }
1184 }
1185 if (($num == count($liste)-1) && ($depth>1)) {
1186 $newtree=str_change($newtree,$depth-2,"`");
1187 }
1188 return($newtree);
1189 }
1190
1191
1192 /*
1193 * Format the message-tree
1194 * Zeichen im Baum:
1195 * o : leerer Kasten k1.gif
1196 * * : Kasten mit Zeichen drin k2.gif
1197 * i : vertikale Linie I.gif
1198 * - : horizontale Linie s.gif
1199 * + : T-Stueck T.gif
1200 * ` : Winkel L.gif
1201 */
1202 function formatTreeGraphic($newtree) {
1203 global $imgdir;
1204 $return="";
1205 for ($o=0 ; $o<strlen($newtree) ; $o++) {
1206 $return .= '<img src="../../'.$imgdir.'/';
1207 $k=substr($newtree,$o,1);
1208 $alt=$k;
1209 switch ($k) {
1210 case "o":
1211 $return .= 'k1.gif';
1212 break;
1213 case "*":
1214 $return .= 'k2.gif';
1215 break;
1216 case "i":
1217 $return .= 'I.gif';
1218 $alt='|';
1219 break;
1220 case "-":
1221 $return .= 's.gif';
1222 break;
1223 case "+":
1224 $return .= 'T.gif';
1225 break;
1226 case "`":
1227 $return .= 'L.gif';
1228 break;
1229 case ".":
1230 $return .= 'e.gif';
1231 $alt='&nbsp;';
1232 break;
1233 }
1234 $return .= '" alt="'.$alt.'"';
1235 if (strcmp($k,".") == 0) $return .=(' style="width: 12px; height: 9px"');
1236 $return .= '>';
1237 }
1238 return($return);
1239 }
1240
1241 function formatTreeText($tree) {
1242 $tree=str_replace("i","|",$tree);
1243 $tree=str_replace(".","&nbsp;",$tree);
1244 return($tree);
1245 }
1246
1247 function formatSubject($c,$group) {
1248 if ($c->isReply) {
1249 $re="Re: ";
1250 } else {
1251 $re="";
1252 }
1253 global $file_article, $thread_maxSubject, $frame_article;
1254 $return='<a ';
1255 if ((isset($frame_article)) && ($frame_article != ""))
1256 $return .= 'target="'.$frame_article.'" ';
1257 $return .= 'href="../../'.$file_article.
1258 // '?id='.urlencode($c->id).'&amp;group='.urlencode($group).'">'.
1259 '/'.urlencode($group).'/'.urlencode($c->number).'.html">'.
1260 $re.htmlspecialchars(substr(trim($c->subject),0,$thread_maxSubject))."</a>";
1261 return($return);
1262 }
1263
1264 function formatAuthor($c) {
1265 $return = '<a href="mailto:'.trim($c->from).'">';
1266 if (trim($c->name)!="") {
1267 // $return .= htmlspecialchars(trim(mb_convert_encoding($c->name, "EUC-JP", "auto")));
1268 $return .= htmlspecialchars(trim($c->name));
1269 } else {
1270 if (isset($c->username)) {
1271 $s = strpos($c->username,"%");
1272 if ($s != false) {
1273 $return .= htmlspecialchars(substr($c->username,0,$s));
1274 } else {
1275 $return .= htmlspecialchars($c->username);
1276 }
1277 }
1278 }
1279 $return .= "</a>";
1280 return($return);
1281 }
1282
1283 function showThread(&$headers,&$liste,$depth,$tree,$group,$article_first=0,$article_last=0,&$article_count) {
1284 global $thread_treestyle;
1285 global $thread_showDate,$thread_showSubject;
1286 global $thread_showAuthor,$imgdir;
1287 global $file_article,$thread_maxSubject;
1288 global $age_count,$age_time,$age_color;
1289 global $frame_article,$thread_fontPre,$thread_fontPost;
1290 if ($thread_treestyle==3) echo "\n<UL>\n";
1291 for ($i = 0 ; $i<count($liste) ; $i++) {
1292 $c=$headers[$liste[$i]]; // read the first article
1293 $article_count++;
1294 switch ($thread_treestyle) {
1295 case 4: // thread
1296 case 5: // thread, graphic
1297 case 6: // thread, table
1298 case 7: // thread, table, graphic
1299 $newtree=calculateTree($tree,$depth,$i,$liste,$c);
1300 }
1301 if (($article_first == 0) ||
1302 (($article_count >= $article_first) &&
1303 ($article_count <= $article_last))) {
1304 switch ($thread_treestyle) {
1305 case 0: // simple list
1306 echo $thread_fontPre;
1307 if ($thread_showDate) echo formatDate($c)." ";
1308 if ($thread_showSubject) echo formatSubject($c,$group)." ";
1309 if ($thread_showAuthor) echo "(".formatAuthor($c).")";
1310 echo $thread_fontPost;
1311 echo "<br>\n";
1312 break;
1313 case 1: // html-auflistung, kein baum
1314 echo "<li>".$thread_fontPre;
1315 if ($thread_showDate)
1316 echo formatDate($c)." ";
1317 if ($thread_showSubject)
1318 echo formatSubject($c,$group)." ";
1319 if ($thread_showAuthor)
1320 echo "<em>(".formatAuthor($c).")</em>";
1321 echo $thread_fontPost."</li>";
1322 break;
1323 case 2: // table
1324 echo "<tr>";
1325 if ($thread_showDate)
1326 echo "<td>".$thread_fontPre.formatDate($c)." ".$thread_fontPost."</td>";
1327 if ($thread_showSubject) {
1328 echo '<td nowrap="nowrap">'.$thread_fontPre.formatSubject($c,$group);
1329 echo $thread_fontPost."</td>";
1330 }
1331 if ($thread_showAuthor) {
1332 echo "<td></td>";
1333 echo '<td>'.$thread_fontPre.formatAuthor($c);
1334 echo $thread_fontPost."</td>";
1335 }
1336 echo "</tr>\n";
1337 break;
1338 case 3: // html-tree
1339 echo "<li>".$thread_fontPre;
1340 if ($thread_showDate)
1341 echo formatDate($c)." ";
1342 if ($thread_showSubject)
1343 echo formatSubject($c,$group)." ";
1344 if ($thread_showAuthor)
1345 echo "<em>(".formatAuthor($c).")</em>";
1346 echo $thread_fontPost."\n";
1347 break;
1348 case 4: // thread
1349 echo "".$thread_fontPre;
1350 if ($thread_showDate)
1351 echo formatDate($c)." ";
1352 echo formatTreeText($newtree)." ";
1353 if ($thread_showSubject)
1354 echo formatSubject($c,$group)." ";
1355 if ($thread_showAuthor)
1356 echo "<em>(".formatAuthor($c).")</em>";
1357 echo $thread_fontPost."<br>";
1358 break;
1359 case 5: // thread, graphic
1360 echo "<table><tr>\n";
1361 if ($thread_showDate)
1362 echo '<td>'.$thread_fontPre.formatDate($c)." ".$thread_fontPost."</td>";
1363 echo "<td>".$thread_fontPre.formatTreeGraphic($newtree).$thread_fontPost."</td>";
1364 if ($thread_showSubject)
1365 echo '<td>'.$thread_fontPre."&nbsp;".formatSubject($c,$group)." ";
1366 if ($thread_showAuthor)
1367 echo "(".formatAuthor($c).")".$thread_fontPost."</td>";
1368 echo "</tr></table>";
1369 break;
1370 case 6: // thread, table
1371 echo "<tr>";
1372 if ($thread_showDate)
1373 echo '<td>'.$thread_fontPre.formatDate($c)." ".$thread_fontPost."</td>";
1374 echo '<td>'.$thread_fontPre.formatTreeText($newtree)." ";
1375 if ($thread_showSubject) {
1376 echo formatSubject($c,$group).$thread_fontPost."</td>";
1377 echo "<td></td>";
1378 }
1379 if ($thread_showAuthor)
1380 echo '<td>'.$thread_fontPre.formatAuthor($c).$thread_fontPost."</td>";
1381 echo "</tr>";
1382 break;
1383 case 7: // thread, table, graphic
1384 echo "<tr>";
1385 if ($thread_showDate)
1386 echo '<td>'.$thread_fontPre.formatDate($c)." ".$thread_fontPost."</td>";
1387 echo "<td><table>\n";
1388 echo "<td>".formatTreeGraphic($newtree)."</td>";
1389 if ($thread_showSubject)
1390 echo '<td>'.$thread_fontPre."&nbsp;".formatSubject($c,$group).$thread_fontPost."</td>";
1391 echo "</table></td>";
1392 if ($thread_showSubject) echo "<td></td>";
1393 if ($thread_showAuthor)
1394 echo '<td>'.$thread_fontPre.formatAuthor($c).$thread_fontPost."</td>";
1395 echo "</tr>";
1396 break;
1397 }
1398 }
1399 if ((isset($c->answers[0])) && (count($c->answers)>0) &&
1400 ($article_count<=$article_last)) {
1401 if ($thread_treestyle >= 4) {
1402 if (substr($newtree,$depth-2,1) == "+")
1403 $newtree=str_change($newtree,$depth-2,"i");
1404 $newtree=str_change($newtree,$depth-1,"+");
1405 $newtree=strtr($newtree,"`",".");
1406 }
1407 if (!isset($newtree)) $newtree="";
1408 showThread($headers,$c->answers,$depth+1,$newtree."",$group,
1409 $article_first,$article_last,$article_count);
1410 }
1411 flush();
1412 }
1413 if ($thread_treestyle==3) echo "</UL>";
1414 }
1415
1416
1417 /*
1418 * Load a thread from disk
1419 *
1420 * $group: name of the newsgroup, is needed to create the filename
1421 *
1422 * the function returns an array of headerType containing the
1423 * overview-data of the thread.
1424 */
1425 function loadThreadData($group) {
1426 global $spooldir,$compress_spoolfiles;
1427 $filename=$spooldir."/".$group."-data.dat";
1428 if ($compress_spoolfiles) {
1429 $file=gzopen("$spooldir/$group-data.dat","r");
1430 $headers=unserialize(gzread($file,1000000));
1431 gzclose($file);
1432 } else {
1433 $file=fopen($filename,"r");
1434 $headers=unserialize(fread($file,filesize($filename)));
1435 fclose($file);
1436 }
1437 return($headers);
1438 }
1439
1440
1441 /*
1442 * Save the thread to disk
1443 *
1444 * $header: is an array of headerType containing all overview-information
1445 * of a newsgroup
1446 * $group: name of the newsgroup, is needed to create the filename
1447 */
1448 function saveThreadData($headers,$group) {
1449 global $spooldir,$compress_spoolfiles;
1450 if ($compress_spoolfiles) {
1451 $file=gzopen("$spooldir/$group-data.dat","w");
1452 gzputs($file,serialize($headers));
1453 gzclose($file);
1454 } else {
1455 $file=fopen("$spooldir/$group-data.dat","w");
1456 fputs($file,serialize($headers));
1457 fclose($file);
1458 }
1459 }
1460
1461
1462 function showHeaders(&$headers,$group,$article_first=0,$article_last=0) {
1463 global $thread_showDate, $thread_showTable;
1464 global $thread_showAuthor,$thread_showSubject;
1465 global $text_thread,$thread_treestyle;
1466 $article_count=0;
1467 if ($headers == false) {
1468 echo $text_thread["no_articles"];
1469 } else {
1470 reset($headers);
1471 $c=current($headers);
1472 for ($i=0; $i<=count($headers)-1; $i++) { // create the array $liste
1473 if ($c->isAnswer == false) { // where are all the articles
1474 $liste[]=$c->id; // in that don't have
1475 } // references
1476 $c=next($headers);
1477 }
1478 reset($liste);
1479 if (count($liste)>0) {
1480 if (($thread_treestyle==2) || ($thread_treestyle==6) ||
1481 ($thread_treestyle==7)) {
1482 echo "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n";
1483 echo "<tr>\n";
1484 if ($thread_showDate) echo "<td>".$text_thread["date"]."&nbsp;</td>";
1485 if ($thread_showSubject) echo "<td>".$text_thread["subject"]."</td>";
1486 if ($thread_showAuthor) {
1487 echo "<td>&nbsp;&nbsp;</td>";
1488 echo "<td>".$text_thread["author"]."</td>\n";
1489 }
1490 echo "</tr>\n";
1491 showThread($headers,$liste,1,"",$group,$article_first,$article_last,
1492 $article_count);
1493 echo "</table>\n";
1494 } else {
1495 if ($thread_treestyle==1) echo "<ul>\n";
1496 showThread($headers,$liste,1,"",$group,$article_first,$article_last,
1497 $article_count);
1498 if ($thread_treestyle==1) echo "</ul>\n";
1499 }
1500 }
1501 }
1502 }
1503
1504 function MessageIdToUrl($id) {
1505 $id = ereg_replace("^<","",$id);
1506 $id = ereg_replace(">$","",$id);
1507 return urlencode($id);
1508 }
1509
1510 /*
1511 * Print the header of a message to the webpage
1512 *
1513 * $head: the header of the message as an headerType
1514 * $group: the name of the newsgroup, is needed for the links to post.php3
1515 * and the header.
1516 */
1517 function show_header($head,$group) {
1518 global $article_show,$text_header,$file_article,$attachment_show;
1519 global $file_attachment, $file_article, $server;
1520 if ($article_show["Subject"]) echo $text_header["subject"].htmlspecialchars($head->subject)."<br>";
1521 if ($article_show["From"]) {
1522 echo $text_header["from"].'<a href="mailto:'.htmlspecialchars($head->from).'">'.$head->from.'</a> ';
1523 if ($head->name != "") echo '('.htmlspecialchars($head->name).')';
1524 echo "<br>";
1525 }
1526 if ($article_show["Newsgroups"])
1527 echo $text_header["newsgroups"].htmlspecialchars(str_replace(',',', ',$head->newsgroups))."<br>\n";
1528 if (isset($head->followup) && ($article_show["Followup"]) && ($head->followup != ""))
1529 echo $text_header["followup"].htmlspecialchars($head->followup)."<br>\n";
1530 if ($article_show["Date"])
1531 echo $text_header["date"].date($text_header["date_format"],$head->date)."<br>\n";
1532 if ($article_show["Message-ID"])
1533 $a = MessageIdToUrl($head->id);
1534 echo $text_header["message-id"].htmlspecialchars($head->id)."[".'<a href="http://'.$server.'/'.$a.'">'."HTTP"."</a>][".'<a href="news://'.$server.'/'.$a.'">'."NNTP"."</a>]<br>\n";
1535 if (($article_show["References"]) && (isset($head->references[0]))) {
1536 echo $text_header["references"];
1537 for ($i=0; $i<=count($head->references)-1; $i++) {
1538 $ref=$head->references[$i];
1539 echo ' '.'<a href="../../'.$file_article.'/'.urlencode($group).'/'.
1540 urlencode($ref).'.html">'.($i+1).'</a>';
1541 }
1542 echo "<br>";
1543 }
1544 $fields = array ("x-moe", "x-brother", "x-syster", "x-wife",
1545 "x-daughter", "x-respect",
1546 "user-agent", "x-mailer", "x-newsreader",
1547 "list-id", "x-uri", "x-mail-count", "keywords");
1548 for ($i = 0; $i < count($fields); $i++) {
1549 if (count($head->field[$fields[$i]])) {
1550 if ((isset($article_show[$fields[$i]])) && ($article_show[$fields[$i]])) {
1551 echo "<div class=\"field ".$fields[$i]."\"><span class=\"name\">"
1552 .$text_header[$fields[$i]]."</span> <span class=\"body\">"
1553 .uri_to_link(htmlspecialchars(decode_structured_body(
1554 join(', ', $head->field[$fields[$i]]))))
1555 ."</span></div>\n";
1556 }
1557 }
1558 }
1559 $fields = array ("x-weather", "x-copyright", "comments", "organization");
1560 for ($i = 0; $i < count($fields); $i++) {
1561 if (count($head->field[$fields[$i]])) {
1562 if ((isset($article_show[$fields[$i]])) && ($article_show[$fields[$i]])) {
1563 for ($j = 0; $j > count($head->field[$fields[$i]]); $j++) {
1564 echo "<div class=\"field ".$fields[$i]."\"><span class=\"name\">"
1565 .$text_header[$fields[$i]]."</span> <span class=\"body\">"
1566 .uri_to_link(htmlspecialchars(decode_unstructured_body(
1567 $head->field[$fields[$i]][$j])))
1568 ."</span></div>\n";
1569 }
1570 }
1571 }
1572 }
1573 if ((isset($attachment_show)) && ($attachment_show==true) &&
1574 (isset($head->content_type[1]))) {
1575 echo $text_header["attachments"];
1576 for ($i=1; $i<count($head->content_type); $i++) {
1577 echo '<a href="../../'.$file_attachment.'/'.urlencode($group).'/'.
1578 urlencode($head->number).'/'.
1579 $i.'/'.
1580 urlencode($head->content_type_name[$i]).'">'.
1581 $head->content_type_name[$i].'</a> ('.
1582 $head->content_type[$i].')';
1583 if ($i<count($head->content_type)-1) echo ', ';
1584 }
1585 }
1586 }
1587
1588
1589 /*
1590 function showAntwortKnopf($group,$id) {
1591 global $file_post;
1592 echo "<form action=\"$file_post\" method=post>\n";
1593 echo "<input type=submit value=\"Antworten\"\n>";
1594 echo "<input type=hidden name=\"type\" value=\"reply\">\n";
1595 echo "<input type=hidden name=\"id\" value=\"$id\">\n";
1596 echo "<input type=hidden name=\"group\" value=\"$group\">\n";
1597 echo "</form>\n";
1598 }
1599 */
1600
1601 /*
1602 * print an article to the webpage
1603 *
1604 * $group: The name of the newsgroup
1605 * $id: the ID of the article inside the group or the message-id
1606 * $attachment: The number of the attachment of the article.
1607 * 0 means the normal textbody.
1608 */
1609 function show_article($group,$id,$attachment=0,$article_data=false) {
1610 global $file_article;
1611 global $text_header,$article_showthread;
1612 if ($article_data == false)
1613 $article_data=read_message($id,$attachment,$group);
1614 $head=$article_data->header;
1615 $body=$article_data->body[$attachment];
1616 if ($head!=false) {
1617 if (($head->content_type[$attachment]=="text/plain") &&
1618 ($attachment==0)){
1619 show_header($head,$group);
1620 echo "<pre>\n";
1621 if(count($head->references)){
1622 $refs = $head->references;
1623 array_walk($refs, 'escape_regex');
1624 $msgidregex = "(&lt;|news:)(".join("|", $refs).")(&gt;)?";
1625 $msgidregex = str_replace("><", "|", $msgidregex);
1626 }
1627 $body=split("\n",$body);
1628 for ($i=0; $i<=count($body)-1; $i++) {
1629 // $b=textwrap($body[$i],80,"\n");
1630 // if ((strpos(substr($b,0,strpos($b," ")),'>') != false ) ||
1631 // (strcmp(substr($b,0,1),'>') == 0) ||
1632 // (strcmp(substr($b,0,1),':') == 0)) {
1633 // echo "<i>".html_parse(htmlspecialchars($b))."</i>\n";
1634 // } else {
1635 // echo html_parse(htmlspecialchars($b)."\n");
1636 // }
1637 // echo $body[$i]."\n";
1638 $b=$body[$i];
1639 echo uri_to_link(htmlspecialchars($b)."\n", $group, $msgidregex);
1640 }
1641 echo "\n</pre>\n";
1642 } else {
1643 echo $body;
1644 }
1645 }
1646 if ($article_showthread > 0) {
1647 }
1648 }
1649
1650 function escape_regex(&$value, $key){
1651 $value = QuoteMeta(substr($value, 1, -1));
1652 }
1653
1654 /*
1655 * Encode lines with 8bit-characters to quote-printable
1656 *
1657 * $line: the to be encoded line
1658 *
1659 * the function returns a sting containing the quoted-printable encoded
1660 * $line
1661 */
1662 function quoted_printable_encode($line) {
1663 $qp_table=array(
1664 '=00', '=01', '=02', '=03', '=04', '=05',
1665 '=06', '=07', '=08', '=09', '=0A', '=0B',
1666 '=0C', '=0D', '=0E', '=0F', '=10', '=11',
1667 '=12', '=13', '=14', '=15', '=16', '=17',
1668 '=18', '=19', '=1A', '=1B', '=1C', '=1D',
1669 '=1E', '=1F', '_', '!', '"', '#',
1670 '$', '%', '&', "'", '(', ')',
1671 '*', '+', ',', '-', '.', '/',
1672 '0', '1', '2', '3', '4', '5',
1673 '6', '7', '8', '9', ':', ';',
1674 '<', '=3D', '>', '=3F', '@', 'A',
1675 'B', 'C', 'D', 'E', 'F', 'G',
1676 'H', 'I', 'J', 'K', 'L', 'M',
1677 'N', 'O', 'P', 'Q', 'R', 'S',
1678 'T', 'U', 'V', 'W', 'X', 'Y',
1679 'Z', '[', '\\', ']', '^', '=5F',
1680 '', 'a', 'b', 'c', 'd', 'e',
1681 'f', 'g', 'h', 'i', 'j', 'k',
1682 'l', 'm', 'n', 'o', 'p', 'q',
1683 'r', 's', 't', 'u', 'v', 'w',
1684 'x', 'y', 'z', '{', '|', '}',
1685 '~', '=7F', '=80', '=81', '=82', '=83',
1686 '=84', '=85', '=86', '=87', '=88', '=89',
1687 '=8A', '=8B', '=8C', '=8D', '=8E', '=8F',
1688 '=90', '=91', '=92', '=93', '=94', '=95',
1689 '=96', '=97', '=98', '=99', '=9A', '=9B',
1690 '=9C', '=9D', '=9E', '=9F', '=A0', '=A1',
1691 '=A2', '=A3', '=A4', '=A5', '=A6', '=A7',
1692 '=A8', '=A9', '=AA', '=AB', '=AC', '=AD',
1693 '=AE', '=AF', '=B0', '=B1', '=B2', '=B3',
1694 '=B4', '=B5', '=B6', '=B7', '=B8', '=B9',
1695 '=BA', '=BB', '=BC', '=BD', '=BE', '=BF',
1696 '=C0', '=C1', '=C2', '=C3', '=C4', '=C5',
1697 '=C6', '=C7', '=C8', '=C9', '=CA', '=CB',
1698 '=CC', '=CD', '=CE', '=CF', '=D0', '=D1',
1699 '=D2', '=D3', '=D4', '=D5', '=D6', '=D7',
1700 '=D8', '=D9', '=DA', '=DB', '=DC', '=DD',
1701 '=DE', '=DF', '=E0', '=E1', '=E2', '=E3',
1702 '=E4', '=E5', '=E6', '=E7', '=E8', '=E9',
1703 '=EA', '=EB', '=EC', '=ED', '=EE', '=EF',
1704 '=F0', '=F1', '=F2', '=F3', '=F4', '=F5',
1705 '=F6', '=F7', '=F8', '=F9', '=FA', '=FB',
1706 '=FC', '=FD', '=FE', '=FF');
1707 // are there "forbidden" characters in the string?
1708 for($i=0; $i<strlen($line) && ord($line[$i])<=127 ; $i++);
1709 if ($i<strlen($line)) { // yes, there are. So lets encode them!
1710 $from=$i;
1711 for($to=strlen($line)-1; ord($line[$to])<=127; $to--);
1712 // lets scan for the start and the end of the to be encoded _words_
1713 for(;$from>0 && $line[$from] != ' '; $from--);
1714 if($from>0) $from++;
1715 for(;$to<strlen($line) && $line[$to] != ' '; $to++);
1716 // split the string into the to be encoded middle and the rest
1717 $begin=substr($line,0,$from);
1718 $middle=substr($line,$from,$to-$from);
1719 $end=substr($line,$to);
1720 // ok, now lets encode $middle...
1721 $newmiddle="";
1722 for($i=0; $i<strlen($middle); $i++)
1723 $newmiddle .= $qp_table[ord($middle[$i])];
1724 // now we glue the parts together...
1725 $line=$begin.'=?ISO-8859-1?Q?'.$newmiddle.'?='.$end;
1726 }
1727 return $line;
1728 }
1729
1730
1731
1732 /*
1733 * Post an article to a newsgroup
1734 *
1735 * $subject: The Subject of the article
1736 * $from: The authors name and email of the article
1737 * $newsgroups: The groups to post to
1738 * $ref: The references of the article
1739 * $body: The article itself
1740 */
1741 function verschicken($subject,$from,$newsgroups,$ref,$body) {
1742 global $server,$port,$send_poster_host,$organization,$text_error,$text_ua;
1743 global $file_footer;
1744 flush();
1745 $ns=OpenNNTPconnection($server,$port);
1746 if ($ns != false) {
1747 fputs($ns,"post\r\n");
1748 $weg=lieszeile($ns);
1749 // fputs($ns,'Subject: '.quoted_printable_encode($subject)."\r\n");
1750 fputs($ns,'Subject: '.mb_convert_encoding($subject, "ISO-2022-JP", "EUC-JP")."\r\n");
1751 // fputs($ns,'Subject: '.mb_encode_mimeheader($subject)."\r\n");
1752 fputs($ns,'From: '.$from."\r\n");
1753 fputs($ns,'Newsgroups: '.$newsgroups."\r\n");
1754 // fputs($ns,"Mime-Version: 1.0\r\n");
1755 // fputs($ns,"Content-Type: text/plain; charset=ISO-8859-1\r\n");
1756 // fputs($ns,"Content-Transfer-Encoding: 8bit\r\n");
1757 fputs($ns,"User-Agent: ".$text_ua["user_agent"]."\r\n");
1758 if ($send_poster_host)
1759 fputs($ns,'X-HTTP-Posting-Host: '.gethostbyaddr(getenv("REMOTE_ADDR"))."\r\n");
1760 if ($ref!=false) fputs($ns,'References: '.$ref."\r\n");
1761 if (isset($organization))
1762 fputs($ns,'Organization: '.mb_encode_mimeheader($organization)."\r\n");
1763 if ((isset($file_footer)) && ($file_footer!="")) {
1764 $footerfile=fopen($file_footer,"r");
1765 $body.="\n".fread($footerfile,filesize($file_footer));
1766 fclose($footerfile);
1767 }
1768 $body=str_replace("\n.\r","\n..\r",$body);
1769 $body=str_replace("\r",'',$body);
1770 $b=split("\n",$body);
1771 $body="";
1772 for ($i=0; $i<count($b); $i++) {
1773 if ((strpos(substr($b[$i],0,strpos($b[$i]," ")),">") != false ) | (strcmp(substr($b[$i],0,1),">") == 0)) {
1774 $body .= textwrap(stripSlashes($b[$i]),78,"\r\n")."\r\n";
1775 } else {
1776 $body .= textwrap(stripSlashes($b[$i]),74,"\r\n")."\r\n";
1777 }
1778 }
1779 $body = mb_convert_encoding($body, "ISO-2022-JP", "EUC-JP");
1780 fputs($ns,"\r\n".$body."\r\n.\r\n");
1781 $message=lieszeile($ns);
1782 closeNNTPconnection($ns);
1783 } else {
1784 $message=$text_error["post_failed"];
1785 }
1786 return $message . mb_encode_mimeheader($subject) . mb_encode_mimeheader($from);
1787 }
1788
1789 ?>

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24