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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.28 - (show annotations) (download)
Sun Dec 2 01:34:45 2001 UTC (22 years, 5 months ago) by wakaba
Branch: MAIN
Changes since 1.27: +10 -3 lines
*** empty log message ***

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24