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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24