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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.24 - (show annotations) (download)
Sat Dec 1 15:15:08 2001 UTC (22 years, 5 months ago) by wakaba
Branch: MAIN
Changes since 1.23: +8 -6 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 if (eregi('".*"',$value)) { // quoted-pair
452 ereg('([^"]*)"(([^"]+|\\\\.)*)"(.*)',$value,$vals);
453 $newvalue = $vals[1].decode_quoted_pair($vals[2]).$vals[4];
454 return(mb_convert_encoding($newvalue, "EUC-JP", "auto"));
455 } else { // there wasn't anything encoded, return the original string
456 return(mb_convert_encoding($value, "EUC-JP", "auto"));
457 }
458 }
459 }
460
461 function getTimestamp($value) {
462 $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);
463 $value=str_replace(" "," ",$value);
464 $d=split(" ",$value,5);
465 if (strcmp(substr($d[0],strlen($d[0])-1,1),",") == 0) {
466 $date[0]=$d[1]; // day
467 $date[1]=$d[2]; // month
468 $date[2]=$d[3]; // year
469 $date[3]=$d[4]; // hours:minutes:seconds
470 } else {
471 $date[0]=$d[0]; // day
472 $date[1]=$d[1]; // month
473 $date[2]=$d[2]; // year
474 $date[3]=$d[3]; // hours:minutes:seconds
475 }
476 $time=split(":",$date[3]);
477 $timestamp=mktime($time[0],$time[1],$time[2],$months[$date[1]],$date[0],$date[2]);
478 return $timestamp;
479 }
480
481 function parse_header($hdr,$number="") {
482 for ($i=count($hdr)-1; $i>0; $i--)
483 if (preg_match("/^(\x09|\x20)/",$hdr[$i]))
484 $hdr[$i-1]=$hdr[$i-1].ltrim($hdr[$i]);
485 $header = new headerType;
486 $header->isAnswer=false;
487 for ($count=0;$count<count($hdr);$count++) {
488 $variable=substr($hdr[$count],0,strpos($hdr[$count]," "));
489 $value=trim(substr($hdr[$count],strpos($hdr[$count]," ")+1));
490 switch (strtolower($variable)) {
491 case "from:":
492 $fromline=address_decode(headerDecode($value),"nirgendwo");
493 if (!isset($fromline[0]["host"])) $fromline[0]["host"]="";
494 $header->from=$fromline[0]["mailbox"]."@".$fromline[0]["host"];
495 $header->username=$fromline[0]["mailbox"];
496 if (!isset($fromline[0]["personal"])) {
497 $header->name="";
498 } else {
499 $header->name=$fromline[0]["personal"];
500 }
501 break;
502 case "message-id:":
503 $header->id=$value;
504 break;
505 case "subject:":
506 $header->subject=headerDecode($value);
507 break;
508 case "newsgroups:":
509 $header->newsgroups=$value;
510 break;
511 case "organization:":
512 $header->organization=$value;
513 break;
514 case "content-transfer-encoding:":
515 $header->content_transfer_encoding=trim(strtolower($value));
516 break;
517 case "content-type:":
518 $header->content_type=array();
519 $subheader=split(";",$value);
520 $header->content_type[0]=strtolower(trim($subheader[0]));
521 for ($i=1; $i<count($subheader); $i++) {
522 $gleichpos=strpos($subheader[$i],"=");
523 if ($gleichpos) {
524 $subvariable=trim(substr($subheader[$i],0,$gleichpos));
525 $subvalue=trim(substr($subheader[$i],$gleichpos+1));
526 if (($subvalue[0]=='"') &&
527 ($subvalue[strlen($subvalue)-1]=='"'))
528 $subvalue=substr($subvalue,1,strlen($subvalue)-2);
529 switch($subvariable) {
530 case "charset":
531 $header->content_type_charset=array(strtolower($subvalue));
532 break;
533 case "name":
534 $header->content_type_name=array($subvalue);
535 break;
536 case "boundary":
537 $header->content_type_boundary=$subvalue;
538 }
539 }
540 }
541 break;
542 case "references:":
543 $ref=ereg_replace("> *<", "> <", trim($value));
544 while (strpos($ref,"> <") != false) {
545 $header->references[]=substr($ref,0,strpos($ref," "));
546 $ref=substr($ref,strpos($ref,"> <")+2);
547 }
548 $header->references[]=trim($ref);
549 break;
550 case "date:":
551 $header->date=getTimestamp(trim($value));
552 break;
553 case "followup-to:":
554 $header->followup=trim($value);
555 break;
556 case "x-newsreader:":
557 case "x-mailer:":
558 case "user-agent:":
559 $header->user_agent=trim(decode_structured_body($value));
560 break;
561 case "x-face:":
562 // echo "<p>-".base64_decode($value)."-</p>";
563 break;
564 }
565 }
566 if (!isset($header->content_type[0]))
567 $header->content_type[0]="text/plain";
568 if (!isset($header->content_transfer_encoding))
569 $header->content_transfer_encoding="8bit";
570 if ($number != "") $header->number=$number;
571 return $header;
572 }
573
574 function decode_structured_body ($body) {
575 $patterns = array ("/\"((?:[^\"\\\\]+|\\\\.)*)\"/e");
576 $replace = array ("mb_convert_encoding(decode_quoted_pair('\\1'), 'EUC-JP', 'auto')");
577 return preg_replace ($patterns, $replace, $body);
578 }
579
580 function decode_quoted_pair($value) {
581 $value = ereg_replace('\\\\(\\\\")', "\\1", $value);
582 return ereg_replace('\\\\(.)', "\\1", $value);
583 }
584
585 function decode_body($body,$encoding) {
586 $bodyzeile="";
587 switch ($encoding) {
588 case "base64":
589 $body=base64_decode($body);
590 break;
591 case "quoted-printable":
592 $body=Quoted_printable_decode($body);
593 $body=str_replace("=\n","",$body);
594 // default:
595 // $body=str_replace("\n..\n","\n.\n",$body);
596 }
597 return $body;
598 }
599
600 function parse_message($rawmessage) {
601 global $attachment_delete_alternative,$attachment_uudecode;
602 // Read the header of the message:
603 $count_rawmessage=count($rawmessage);
604 $message = new messageType;
605 $rawheader=array();
606 $i=0;
607 while ($rawmessage[$i] != "") {
608 $rawheader[]=$rawmessage[$i];
609 $i++;
610 }
611 // Parse the Header:
612 $message->header=parse_header($rawheader);
613 // Now we know if the message is a mime-multipart message:
614 $content_type=split("/",$message->header->content_type[0]);
615 if ($content_type[0]=="multipart") {
616 $message->header->content_type=array();
617 // We have multible bodies, so we split the message into its parts
618 $boundary="--".$message->header->content_type_boundary;
619 // lets find the first part
620 while($rawmessage[$i] != $boundary)
621 $i++;
622 $i++;
623 $part=array();
624 while($i<=$count_rawmessage) {
625 if (($rawmessage[$i]==$boundary) || ($i==$count_rawmessage-1) ||
626 ($rawmessage[$i]==$boundary.'--')) {
627 $partmessage=parse_message($part);
628 // merge the content-types of the message with those of the part
629 for ($o=0; $o<count($partmessage->header->content_type); $o++) {
630 $message->header->content_type[]=
631 $partmessage->header->content_type[$o];
632 $message->header->content_type_charset[]=
633 $partmessage->header->content_type_charset[$o];
634 $message->header->content_type_name[]=
635 $partmessage->header->content_type_name[$o];
636 $message->body[]=$partmessage->body[$o];
637 }
638 $part=array();
639 } else {
640 if ($i<$count_rawmessage)
641 $part[]=$rawmessage[$i];
642 }
643 if ($rawmessage[$i]==$boundary.'--') break;
644 $i++;
645 }
646 // Is this a multipart/alternative multipart-message? Do we have to
647 // delete all non plain/text parts?
648 if (($attachment_delete_alternative) &&
649 ($content_type[1]=="alternative")) {
650 $plaintext=false;
651 for ($o=0; $o<count($message->header->content_type); $o++) {
652 if ($message->header->content_type[$o]=="text/plain")
653 $plaintext=true; // we found at least one text/plain
654 }
655 if ($plaintext) { // now we can delete the other parts
656 for ($o=0; $o<count($message->header->content_type); $o++) {
657 if ($message->header->content_type[$o]!="text/plain") {
658 unset($message->header->content_type[$o]);
659 unset($message->header->content_type_name[$o]);
660 unset($message->header->content_type_charset[$o]);
661 unset($message->body[$o]);
662 }
663 }
664 }
665 }
666 } else {
667 // No mime-attachments in the message:
668 $body="";
669 $uueatt=0; // as default we have no uuencoded attachments
670 for($i++;$i<$count_rawmessage; $i++) {
671 // do we have an inlay uuencoded file?
672 if ((strtolower(substr($rawmessage[$i],0,5))!="begin") ||
673 ($attachment_uudecode==false)) {
674 $body.=$rawmessage[$i]."\n";
675 // yes, it seems, we have!
676 } else {
677 $old_i=$i;
678 $uue_infoline_raw=$rawmessage[$i];
679 $uue_infoline=explode(" ",$uue_infoline_raw);
680 $uue_data="";
681 $i++;
682 while($rawmessage[$i]!="end") {
683 if (strlen(trim($rawmessage[$i])) > 2)
684 $uue_data.=$rawmessage[$i]."\n";
685 $i++;
686 }
687 // now write the data in an attachment
688 $uueatt++;
689 $message->body[$uueatt]=uudecode($uue_data);
690 $message->header->content_type_name[$uueatt]="";
691 for ($o=2; $o<count($uue_infoline); $o++)
692 $message->header->content_type_name[$uueatt].=$uue_infoline[$o];
693 $message->header->content_type[$uueatt]=
694 get_mimetype_by_filename($message->header->content_type_name[$uueatt]);
695 }
696 }
697 // if ($message->header->content_type[0]=="text/plain") {
698 // $body=trim($body);
699 // if ($body=="") $body=" ";
700 // }
701 $body=decode_body($body,$message->header->content_transfer_encoding);
702 $message->body[0]=$body;
703 }
704 if (!isset($message->header->content_type_charset))
705 $message->header->content_type_charset=array("ISO-8859-1");
706 if (!isset($message->header->content_type_name))
707 $message->header->content_type_name=array("unnamed");
708 for ($o=0; $o<count($message->body); $o++) {
709 if (!isset($message->header->content_type_charset[$o]))
710 $message->header->content_type_charset[$o]="ISO-8859-1";
711 if (!isset($message->header->content_type_name[$o]))
712 $message->header->content_type_name[$o]="unnamed";
713 }
714 return $message;
715 }
716
717 /*
718 * read an article from the newsserver or the spool-directory
719 *
720 * $id: the Message-ID of an article
721 * $bodynum: the number of the attachment:
722 * -1: return only the header without any bodies or attachments.
723 * 0: the body
724 * 1: the first attachment...
725 *
726 * The function returns an article as an messageType or false if the article
727 * doesn't exists on the newsserver or doesn't contain the given
728 * attachment.
729 */
730 function read_message($id,$bodynum=0,$group="") {
731 global $cache_articles,$spooldir,$text_error;
732 $message = new messageType;
733 if ((isset($cache_articles)) && ($cache_articles == true)) {
734 if ((ereg('^[0-9]+$',$id)) && ($group != ''))
735 $filename=$group.'_'.$id;
736 else
737 $filename=base64_encode($id);
738 $cachefilename_header=$spooldir."/".$filename.'.header';
739 $cachefilename_body=$spooldir."/".$filename.'.body';
740 if (file_exists($cachefilename_header)) {
741 $cachefile=fopen($cachefilename_header,"r");
742 $message->header=unserialize(fread($cachefile,filesize($cachefilename_header)));
743 fclose($cachefile);
744 } else {
745 unset($message->header);
746 }
747 // Is a non-existing attachment of an article requested?
748 if ((isset($message->header)) &&
749 ($bodynum!= -1) &&
750 (!isset($message->header->content_type[$bodynum])))
751 return false;
752 if ((file_exists($cachefilename_body.$bodynum)) &&
753 ($bodynum != -1)) {
754 $cachefile=fopen($cachefilename_body.$bodynum,"r");
755 $message->body[$bodynum]=
756 fread($cachefile,filesize($cachefilename_body.$bodynum));
757 fclose($cachefile);
758 }
759 }
760 if ((!isset($message->header)) ||
761 ((!isset($message->body[$bodynum])) &&
762 ($bodynum != -1))) {
763 if (!isset($ns)) $ns=openNNTPconnection();
764 if ($group != "") {
765 fputs($ns,"group ".$group."\r\n");
766 $zeile=lieszeile($ns);
767 }
768 fputs($ns,'article '.$id."\r\n");
769 $zeile=lieszeile($ns);
770 if (substr($zeile,0,3) != "220")
771 return false;
772 $rawmessage=array();
773 $line=lieszeile($ns);
774 #$line=mb_convert_encoding($line, "EUC-JP", "ISO-2022-JP");
775 while(strcmp($line,".") != 0) {
776 $rawmessage[]=$line;
777 $line=lieszeile($ns);
778 #$line=mb_convert_encoding($line, "EUC-JP", "ISO-2022-JP");
779 }
780 $message=parse_message($rawmessage);
781 if (ereg('^[0-9]+$',$id)) $message->header->number=$id;
782 // write header, body and attachments to disk
783 if ((isset($cache_articles)) && ($cache_articles == true)) {
784 $cachefile=fopen($cachefilename_header,"w");
785 if ($cachefile) {
786 fputs($cachefile,serialize($message->header));
787 }
788 fclose($cachefile);
789 for ($i=0; $i<count($message->header->content_type); $i++) {
790 if (isset($message->body[$i])) {
791 $cachefile=fopen($cachefilename_body.$i,"w");
792 fwrite($cachefile,$message->body[$i]);
793 fclose($cachefile);
794 }
795 }
796 }
797 }
798 return $message;
799 }
800
801 function textwrap($text, $wrap=80, $break="\n"){
802 $len = strlen($text);
803 if ($len > $wrap) {
804 $h = ''; // massaged text
805 $lastWhite = 0; // position of last whitespace char
806 $lastChar = 0; // position of last char
807 $lastBreak = 0; // position of last break
808 // while there is text to process
809 while ($lastChar < $len) {
810 $char = substr($text, $lastChar, 1); // get the next character
811 // if we are beyond the wrap boundry and there is a place to break
812 if (($lastChar - $lastBreak > $wrap) && ($lastWhite > $lastBreak)) {
813 $h .= substr($text, $lastBreak, ($lastWhite - $lastBreak)) . $break;
814 $lastChar = $lastWhite + 1;
815 $lastBreak = $lastChar;
816 }
817 // You may wish to include other characters as valid whitespace...
818 if ($char == ' ' || $char == chr(13) || $char == chr(10)) {
819 $lastWhite = $lastChar; // note the position of the last whitespace
820 }
821 $lastChar = $lastChar + 1; // advance the last character position by one
822 }
823 $h .= substr($text, $lastBreak); // build line
824 } else {
825 $h = $text; // in this case everything can fit on one line
826 }
827 return $h;
828 }
829
830 /*
831 * makes URLs clickable
832 *
833 * $comment: A text-line probably containing links.
834 *
835 * the function returns the text-line with HTML-Links to the links or
836 * email-adresses.
837 */
838 function html_parse($comment, $group = "", $msgidregex = "") {
839 global $frame_externallink;
840 global $file_article;
841 if ((isset($frame_externallink)) && ($frame_externallink != "")) {
842 $target=' TARGET="'.$frame_externallink.'" ';
843 } else {
844 $target=' ';
845 }
846 $ncomment = eregi_replace( 'http://([-a-z0-9_./~@?=%#&;]+)', '<a'.$target.'href="http://\1">http://\1</a>', $comment);
847 if ($ncomment == $comment)
848 $ncomment = eregi_replace( '(www\.[-a-z]+\.(de|int|eu|dk|org|net|at|ch|com|jp))','<a'.$target.'href="http://\1">\1</a>',$comment);
849 $comment=$ncomment;
850 $comment = eregi_replace( 'https://([-a-z0-9_./~@?=%#&;\n]+)', '<a'.$target.'href="https://\1">https://\1</a>', $comment);
851 $comment = eregi_replace( 'gopher://([-a-z0-9_./~@?=%\n]+)','<a'.$target.'href="gopher://\1">gopher://\1</a>', $comment);
852 $comment = eregi_replace( 'news://([-a-z0-9_./~@?=%\n]+)','<a'.$target.'href="news://\1">news://\1</a>', $comment);
853 $comment = eregi_replace( 'ftp://([-a-z0-9_./~@?=%\n]+)', '<a'.$target.'href="ftp://\1">ftp://\1</a>', $comment);
854 if(!empty($msgidregex) && ereg($msgidregex, $comment)){
855 //$comment = ereg_replace( $msgidregex, '<a'.$target.'href="http://'.$SERVER_NAME.'/\1">&lt;\1&gt;</a>', $comment);
856 $comment = preg_replace( '/'.$msgidregex.'/e', "'<a$target'.'href=\"../../'.addslashes('$file_article').'/'.urlencode('$group').'/'.urlencode('<\\2>').'.html\">\\1\\2\\3</a>'", $comment);
857 } else{
858 $comment = eregi_replace( '([-a-z0-9_./n]+)@([-a-z0-9_.]+)','<a href="mailto:\1@\2">\1@\2</a>', $comment);
859 }
860 return($comment);
861 }
862
863
864
865
866 /*
867 * read the header of an article in plaintext into an array
868 * $articleNumber can be the number of an article or its message-id.
869 */
870 function readPlainHeader(&$von,$group,$articleNumber) {
871 fputs($von,"group $group\r\n");
872 $zeile=lieszeile($von);
873 fputs($von,"head $articleNumber\r\n");
874 $zeile=lieszeile($von);
875 if (substr($zeile,0,3) != "221") {
876 echo $text_error["article_not_found"];
877 $header=false;
878 } else {
879 $zeile=lieszeile($von);
880 $body="";
881 while(strcmp(trim($zeile),".") != 0) {
882 $body .= $zeile."\n";
883 $zeile=lieszeile($von);
884 }
885 return split("\n",str_replace("\r\n","\n",$body));
886 }
887 }
888
889 function readArticles(&$von,$groupname,$articleList) {
890 for($i = 0; $i <= count($articleList)-1 ; $i++) {
891 $temp=read_header($von,$articleList[$i]);
892 $articles[$temp->id] = $temp;
893 }
894 return $articles;
895 }
896
897 /*
898 * Remove re: aw: etc. from a subject.
899 *
900 * $subject: a string containing the complete Subject
901 *
902 * The function removes the re:, aw: etc. from $subject end returns true
903 * if it removed anything, and false if not.
904 */
905 function splitSubject(&$subject) {
906 $s=eregi_replace('^(aw:|re:|re\[2\]:| )+','',$subject);
907 $return=($s != $subject);
908 $subject=$s;
909 return $return;
910 }
911
912 function interpretOverviewLine($zeile,$overviewformat,$groupname) {
913 $return="";
914 $overviewfmt=explode("\t",$overviewformat);
915 echo " "; // keep the connection to the webbrowser alive
916 flush(); // while generating the message-tree
917 $over=split("\t",$zeile,count($overviewfmt)-1);
918 $article=new headerType;
919 for ($i=0; $i<count($overviewfmt)-1; $i++) {
920 if ($overviewfmt[$i]=="Subject:") {
921 $subject=headerDecode($over[$i+1]);
922 $article->isReply=splitSubject($subject);
923 $article->subject=$subject;
924 }
925 if ($overviewfmt[$i]=="Date:") {
926 $article->date=getTimestamp($over[$i+1]);
927 }
928 if ($overviewfmt[$i]=="From:") {
929 $fromline=address_decode(headerDecode($over[$i+1]),"nirgendwo");
930 $article->from=$fromline[0]["mailbox"]."@".$fromline[0]["host"];
931 $article->username=$fromline[0]["mailbox"];
932 if (!isset($fromline[0]["personal"])) {
933 $article->name=$fromline[0]["mailbox"];
934 if (strpos($article->name,'%')) {
935 $article->name=substr($article->name,0,strpos($article->name,'%'));
936 }
937 $article->name=strtr($article->name,'_',' ');
938 } else {
939 $article->name=$fromline[0]["personal"];
940 }
941 }
942 if ($overviewfmt[$i]=="Message-ID:") $article->id=$over[$i+1];
943 if (($overviewfmt[$i]=="References:") && ($over[$i+1] != ""))
944 $article->references=explode(" ",$over[$i+1]);
945 }
946 $article->number=$over[0];
947 $article->isAnswer=false;
948 return($article);
949 }
950
951 /*
952 * Rebuild the Overview-File
953 */
954 function rebuildOverview(&$von,$groupname,$poll) {
955 global $spooldir,$maxarticles,$maxfetch,$initialfetch,$maxarticles_extra;
956 global $text_error,$text_thread,$compress_spoolfiles,$server;
957 $idstring="0.22,".$server.",".$compress_spoolfiles.",".$maxarticles.",".
958 $maxarticles_extra.",".$maxfetch.",".$initialfetch;
959 fputs($von,"list overview.fmt\r\n"); // find out the format of the
960 $tmp=liesZeile($von); // xover-command
961 $zeile=liesZeile($von);
962 while (strcmp($zeile,".") != 0) {
963 $overviewfmt[]=$zeile;
964 $zeile=liesZeile($von);
965 }
966 $overviewformat=implode("\t",$overviewfmt);
967 $spoolfilename=$spooldir."/".$groupname."-data.dat";
968 fputs($von,"group $groupname\r\n"); // select a group
969 $groupinfo=explode(" ",liesZeile($von));
970 if (substr($groupinfo[0],0,1) != 2) {
971 echo "<p>".$text_error["error:"]."</p>";
972 echo "<p>".$text_thread["no_such_group"]."</p>";
973 flush();
974 } else {
975 $infofilename=$spooldir."/".$groupname."-info.txt";
976 $spoolopenmodus="n";
977 if (!((file_exists($infofilename)) && (file_exists($spoolfilename)))) {
978 $spoolopenmodus="w";
979 } else {
980 $infofile=fopen($infofilename,"r");
981 $oldid=fgets($infofile,100);
982 if (trim($oldid) != $idstring) {
983 echo "<!-- Database Error, rebuilding Database...-->\n";
984 $spoolopenmodus="w";
985 }
986 $oldgroupinfo=explode(" ",trim(fgets($infofile,200)));
987 fclose($infofile);
988 if ($groupinfo[3] < $oldgroupinfo[1]) {
989 $spoolopenmodus="w";
990 }
991 if ($maxarticles == 0) {
992 if ($groupinfo[2] != $oldgroupinfo[0]) $spoolopenmodus="w";
993 } else {
994 if ($groupinfo[2] > $oldgroupinfo[0]) $spoolopenmodus="w";
995 }
996 if (($spoolopenmodus == "n") && ($groupinfo[3] > $oldgroupinfo[1]))
997 $spoolopenmodus="a";
998 }
999 if ($spoolopenmodus=="a") {
1000 $firstarticle=$oldgroupinfo[1]+1;
1001 $lastarticle=$groupinfo[3];
1002 }
1003 if ($spoolopenmodus=="w") {
1004 $firstarticle=$groupinfo[2];
1005 $lastarticle=$groupinfo[3];
1006 }
1007 if ($spoolopenmodus != "n") {
1008 if ($maxarticles != 0) {
1009 if ($spoolopenmodus == "w") {
1010 $firstarticle=$lastarticle-$maxarticles+1;
1011 if ($firstarticle < $groupinfo[2])
1012 $firstarticle=$groupinfo[2];
1013 } else {
1014 if ($lastarticle-$oldgroupinfo[0]+1 > $maxarticles + $maxarticles_extra) {
1015 $firstarticle=$lastarticle-$maxarticles+1;
1016 $spoolopenmodus="w";
1017 }
1018 }
1019 }
1020 if (($maxfetch!=0) && (($lastarticle-$firstarticle+1) > $maxfetch)) {
1021 if ($spoolopenmodus=="w") {
1022 $tofetch=($initialfetch != 0) ? $initialfetch : $maxfetch;
1023 $lastarticle=$firstarticle+$tofetch-1;
1024 } else {
1025 $lastarticle=$firstarticle+$maxfetch-1;
1026 }
1027 }
1028 }
1029 echo "<!--openmodus: ".$spoolopenmodus."-->\n";
1030 if ($spoolopenmodus != "w") $headers=loadThreadData($groupname);
1031 if ($spoolopenmodus != "n") {
1032 fputs($von,"xover ".$firstarticle."-".$lastarticle."\r\n"); // and read the overview
1033 $tmp=liesZeile($von);
1034 if (substr($tmp,0,3) == "224") {
1035 $zeile=liesZeile($von);
1036 while ($zeile != ".") {
1037 $article=interpretOverviewLine($zeile,$overviewformat,$groupname);
1038 $headers[$article->id]=$article;
1039 if($poll) {
1040 echo $article->number.", "; flush();
1041 read_message($article->number,0,$groupname);
1042 }
1043 $zeile=lieszeile($von);
1044 }
1045 }
1046 if (file_exists($spoolfilename)) unlink($spoolfilename);
1047 if (count($headers)>0) {
1048 $infofile=fopen($infofilename,"w");
1049 if ($spoolopenmodus=="a") $firstarticle=$oldgroupinfo[0];
1050 fputs($infofile,$idstring."\n");
1051 fputs($infofile,$firstarticle." ".$lastarticle."\r\n");
1052 fclose($infofile);
1053 reset($headers);
1054 $c=current($headers); // read one article
1055 for ($i=0 ; $i<=count($headers)-1 ; $i++) {
1056 if (($c->isAnswer == false) &&
1057 (isset($c->references[0]))) { // is the article an answer to an
1058 // other article?
1059 $o=count($c->references)-1;
1060 $ref=$c->references[$o];
1061 while (($o >= 0) && (!isset($headers[$ref]))) { // try to find a
1062 $ref=$c->references[$o]; // matching article
1063 $o--; // to the reference
1064 }
1065 if ($o >= 0) { // found a matching article?
1066 $c->isAnswer=true; // so the Article is an answer
1067 $headers[$c->id]=$c;
1068 $headers[$ref]->answers[]=$c->id; // the referenced article gets
1069 // the ID of the article
1070 }
1071 }
1072 $c=next($headers);
1073 }
1074 reset($headers);
1075 saveThreadData($headers,$groupname);
1076 }
1077 }
1078 return((isset($headers)) ? $headers : false);
1079 }
1080 }
1081
1082
1083 /*
1084 * Read the Overview.
1085 * Format of the overview-file:
1086 * message-id
1087 * date
1088 * subject
1089 * author
1090 * email
1091 * references
1092 */
1093 function mycompare($a,$b) {
1094 global $thread_sorting;
1095 if ($a->date==$b->date) $r=0;
1096 $r=($a->date<$b->date) ? -1 : 1;
1097 return $r*$thread_sorting;
1098 }
1099 function readOverview(&$von,$groupname,$readmode = 1,$poll=false) {
1100 global $text_error, $maxarticles;
1101 global $spooldir,$thread_sorting;
1102 if (!testGroup($groupname)) {
1103 echo $text_error["read_access_denied"];
1104 return;
1105 }
1106 if ($von == false) return false;
1107 if (($von!=false) && ($readmode > 0))
1108 $articles=rebuildOverview($von,$groupname,$poll);
1109 if ((isset($articles)) && ($articles)) {
1110 if (($thread_sorting != 0) && (count($articles)>0))
1111 uasort($articles,'mycompare');
1112 return $articles;
1113 } else {
1114 return false;
1115 }
1116 }
1117
1118 function str_change($str,$pos,$char) {
1119 return(substr($str,0,$pos).$char.substr($str,$pos+1,strlen($str)-$pos));
1120 }
1121
1122 function formatDate($c) {
1123 global $age_count,$age_time,$age_color,$date_format;
1124 $return="";
1125 $currentTime=time();
1126 $color="";
1127 if ($age_count > 0)
1128 for($t = $age_count; $t >= 1; $t--)
1129 if ($currentTime - $c->date < $age_time[$t]) $color = $age_color[$t];
1130 if ($color != "") $return .= '<font color="'.$color.'">';
1131 if (!isset($date_format)) $date_format = "d.m.";
1132 $return .= date($date_format,$c->date); // format the date
1133 if ($color != "") $return .= '</font>';
1134 return($return);
1135 }
1136
1137 function calculateTree($newtree,$depth,$num,$liste,$c) {
1138 if ((isset($c->answers[0])) && (count($c->answers)>0)) {
1139 $newtree.="*";
1140 } else {
1141 if ($depth == 1) {
1142 $newtree.="o";
1143 } else {
1144 $newtree.="-";
1145 }
1146 }
1147 if (($num == count($liste)-1) && ($depth>1)) {
1148 $newtree=str_change($newtree,$depth-2,"`");
1149 }
1150 return($newtree);
1151 }
1152
1153
1154 /*
1155 * Format the message-tree
1156 * Zeichen im Baum:
1157 * o : leerer Kasten k1.gif
1158 * * : Kasten mit Zeichen drin k2.gif
1159 * i : vertikale Linie I.gif
1160 * - : horizontale Linie s.gif
1161 * + : T-Stueck T.gif
1162 * ` : Winkel L.gif
1163 */
1164 function formatTreeGraphic($newtree) {
1165 global $imgdir;
1166 $return="";
1167 for ($o=0 ; $o<strlen($newtree) ; $o++) {
1168 $return .= '<img src="../../'.$imgdir.'/';
1169 $k=substr($newtree,$o,1);
1170 $alt=$k;
1171 switch ($k) {
1172 case "o":
1173 $return .= 'k1.gif';
1174 break;
1175 case "*":
1176 $return .= 'k2.gif';
1177 break;
1178 case "i":
1179 $return .= 'I.gif';
1180 $alt='|';
1181 break;
1182 case "-":
1183 $return .= 's.gif';
1184 break;
1185 case "+":
1186 $return .= 'T.gif';
1187 break;
1188 case "`":
1189 $return .= 'L.gif';
1190 break;
1191 case ".":
1192 $return .= 'e.gif';
1193 $alt='&nbsp;';
1194 break;
1195 }
1196 $return .= '" alt="'.$alt.'"';
1197 if (strcmp($k,".") == 0) $return .=(' style="width: 12px; height: 9px"');
1198 $return .= '>';
1199 }
1200 return($return);
1201 }
1202
1203 function formatTreeText($tree) {
1204 $tree=str_replace("i","|",$tree);
1205 $tree=str_replace(".","&nbsp;",$tree);
1206 return($tree);
1207 }
1208
1209 function formatSubject($c,$group) {
1210 if ($c->isReply) {
1211 $re="Re: ";
1212 } else {
1213 $re="";
1214 }
1215 global $file_article, $thread_maxSubject, $frame_article;
1216 $return='<a ';
1217 if ((isset($frame_article)) && ($frame_article != ""))
1218 $return .= 'target="'.$frame_article.'" ';
1219 $return .= 'href="../../'.$file_article.
1220 // '?id='.urlencode($c->id).'&amp;group='.urlencode($group).'">'.
1221 '/'.urlencode($group).'/'.urlencode($c->number).'.html">'.
1222 $re.htmlspecialchars(substr(trim($c->subject),0,$thread_maxSubject))."</a>";
1223 return($return);
1224 }
1225
1226 function formatAuthor($c) {
1227 $return = '<a href="mailto:'.trim($c->from).'">';
1228 if (trim($c->name)!="") {
1229 // $return .= htmlspecialchars(trim(mb_convert_encoding($c->name, "EUC-JP", "auto")));
1230 $return .= htmlspecialchars(trim($c->name));
1231 } else {
1232 if (isset($c->username)) {
1233 $s = strpos($c->username,"%");
1234 if ($s != false) {
1235 $return .= htmlspecialchars(substr($c->username,0,$s));
1236 } else {
1237 $return .= htmlspecialchars($c->username);
1238 }
1239 }
1240 }
1241 $return .= "</a>";
1242 return($return);
1243 }
1244
1245 function showThread(&$headers,&$liste,$depth,$tree,$group,$article_first=0,$article_last=0,&$article_count) {
1246 global $thread_treestyle;
1247 global $thread_showDate,$thread_showSubject;
1248 global $thread_showAuthor,$imgdir;
1249 global $file_article,$thread_maxSubject;
1250 global $age_count,$age_time,$age_color;
1251 global $frame_article,$thread_fontPre,$thread_fontPost;
1252 if ($thread_treestyle==3) echo "\n<UL>\n";
1253 for ($i = 0 ; $i<count($liste) ; $i++) {
1254 $c=$headers[$liste[$i]]; // read the first article
1255 $article_count++;
1256 switch ($thread_treestyle) {
1257 case 4: // thread
1258 case 5: // thread, graphic
1259 case 6: // thread, table
1260 case 7: // thread, table, graphic
1261 $newtree=calculateTree($tree,$depth,$i,$liste,$c);
1262 }
1263 if (($article_first == 0) ||
1264 (($article_count >= $article_first) &&
1265 ($article_count <= $article_last))) {
1266 switch ($thread_treestyle) {
1267 case 0: // simple list
1268 echo $thread_fontPre;
1269 if ($thread_showDate) echo formatDate($c)." ";
1270 if ($thread_showSubject) echo formatSubject($c,$group)." ";
1271 if ($thread_showAuthor) echo "(".formatAuthor($c).")";
1272 echo $thread_fontPost;
1273 echo "<br>\n";
1274 break;
1275 case 1: // html-auflistung, kein baum
1276 echo "<li>".$thread_fontPre;
1277 if ($thread_showDate)
1278 echo formatDate($c)." ";
1279 if ($thread_showSubject)
1280 echo formatSubject($c,$group)." ";
1281 if ($thread_showAuthor)
1282 echo "<em>(".formatAuthor($c).")</em>";
1283 echo $thread_fontPost."</li>";
1284 break;
1285 case 2: // table
1286 echo "<tr>";
1287 if ($thread_showDate)
1288 echo "<td>".$thread_fontPre.formatDate($c)." ".$thread_fontPost."</td>";
1289 if ($thread_showSubject) {
1290 echo '<td nowrap="nowrap">'.$thread_fontPre.formatSubject($c,$group);
1291 echo $thread_fontPost."</td>";
1292 }
1293 if ($thread_showAuthor) {
1294 echo "<td></td>";
1295 echo '<td>'.$thread_fontPre.formatAuthor($c);
1296 echo $thread_fontPost."</td>";
1297 }
1298 echo "</tr>\n";
1299 break;
1300 case 3: // html-tree
1301 echo "<li>".$thread_fontPre;
1302 if ($thread_showDate)
1303 echo formatDate($c)." ";
1304 if ($thread_showSubject)
1305 echo formatSubject($c,$group)." ";
1306 if ($thread_showAuthor)
1307 echo "<em>(".formatAuthor($c).")</em>";
1308 echo $thread_fontPost."\n";
1309 break;
1310 case 4: // thread
1311 echo "".$thread_fontPre;
1312 if ($thread_showDate)
1313 echo formatDate($c)." ";
1314 echo formatTreeText($newtree)." ";
1315 if ($thread_showSubject)
1316 echo formatSubject($c,$group)." ";
1317 if ($thread_showAuthor)
1318 echo "<em>(".formatAuthor($c).")</em>";
1319 echo $thread_fontPost."<br>";
1320 break;
1321 case 5: // thread, graphic
1322 echo "<table><tr>\n";
1323 if ($thread_showDate)
1324 echo '<td>'.$thread_fontPre.formatDate($c)." ".$thread_fontPost."</td>";
1325 echo "<td>".$thread_fontPre.formatTreeGraphic($newtree).$thread_fontPost."</td>";
1326 if ($thread_showSubject)
1327 echo '<td>'.$thread_fontPre."&nbsp;".formatSubject($c,$group)." ";
1328 if ($thread_showAuthor)
1329 echo "(".formatAuthor($c).")".$thread_fontPost."</td>";
1330 echo "</tr></table>";
1331 break;
1332 case 6: // thread, table
1333 echo "<tr>";
1334 if ($thread_showDate)
1335 echo '<td>'.$thread_fontPre.formatDate($c)." ".$thread_fontPost."</td>";
1336 echo '<td>'.$thread_fontPre.formatTreeText($newtree)." ";
1337 if ($thread_showSubject) {
1338 echo formatSubject($c,$group).$thread_fontPost."</td>";
1339 echo "<td></td>";
1340 }
1341 if ($thread_showAuthor)
1342 echo '<td>'.$thread_fontPre.formatAuthor($c).$thread_fontPost."</td>";
1343 echo "</tr>";
1344 break;
1345 case 7: // thread, table, graphic
1346 echo "<tr>";
1347 if ($thread_showDate)
1348 echo '<td>'.$thread_fontPre.formatDate($c)." ".$thread_fontPost."</td>";
1349 echo "<td><table>\n";
1350 echo "<td>".formatTreeGraphic($newtree)."</td>";
1351 if ($thread_showSubject)
1352 echo '<td>'.$thread_fontPre."&nbsp;".formatSubject($c,$group).$thread_fontPost."</td>";
1353 echo "</table></td>";
1354 if ($thread_showSubject) echo "<td></td>";
1355 if ($thread_showAuthor)
1356 echo '<td>'.$thread_fontPre.formatAuthor($c).$thread_fontPost."</td>";
1357 echo "</tr>";
1358 break;
1359 }
1360 }
1361 if ((isset($c->answers[0])) && (count($c->answers)>0) &&
1362 ($article_count<=$article_last)) {
1363 if ($thread_treestyle >= 4) {
1364 if (substr($newtree,$depth-2,1) == "+")
1365 $newtree=str_change($newtree,$depth-2,"i");
1366 $newtree=str_change($newtree,$depth-1,"+");
1367 $newtree=strtr($newtree,"`",".");
1368 }
1369 if (!isset($newtree)) $newtree="";
1370 showThread($headers,$c->answers,$depth+1,$newtree."",$group,
1371 $article_first,$article_last,$article_count);
1372 }
1373 flush();
1374 }
1375 if ($thread_treestyle==3) echo "</UL>";
1376 }
1377
1378
1379 /*
1380 * Load a thread from disk
1381 *
1382 * $group: name of the newsgroup, is needed to create the filename
1383 *
1384 * the function returns an array of headerType containing the
1385 * overview-data of the thread.
1386 */
1387 function loadThreadData($group) {
1388 global $spooldir,$compress_spoolfiles;
1389 $filename=$spooldir."/".$group."-data.dat";
1390 if ($compress_spoolfiles) {
1391 $file=gzopen("$spooldir/$group-data.dat","r");
1392 $headers=unserialize(gzread($file,1000000));
1393 gzclose($file);
1394 } else {
1395 $file=fopen($filename,"r");
1396 $headers=unserialize(fread($file,filesize($filename)));
1397 fclose($file);
1398 }
1399 return($headers);
1400 }
1401
1402
1403 /*
1404 * Save the thread to disk
1405 *
1406 * $header: is an array of headerType containing all overview-information
1407 * of a newsgroup
1408 * $group: name of the newsgroup, is needed to create the filename
1409 */
1410 function saveThreadData($headers,$group) {
1411 global $spooldir,$compress_spoolfiles;
1412 if ($compress_spoolfiles) {
1413 $file=gzopen("$spooldir/$group-data.dat","w");
1414 gzputs($file,serialize($headers));
1415 gzclose($file);
1416 } else {
1417 $file=fopen("$spooldir/$group-data.dat","w");
1418 fputs($file,serialize($headers));
1419 fclose($file);
1420 }
1421 }
1422
1423
1424 function showHeaders(&$headers,$group,$article_first=0,$article_last=0) {
1425 global $thread_showDate, $thread_showTable;
1426 global $thread_showAuthor,$thread_showSubject;
1427 global $text_thread,$thread_treestyle;
1428 $article_count=0;
1429 if ($headers == false) {
1430 echo $text_thread["no_articles"];
1431 } else {
1432 reset($headers);
1433 $c=current($headers);
1434 for ($i=0; $i<=count($headers)-1; $i++) { // create the array $liste
1435 if ($c->isAnswer == false) { // where are all the articles
1436 $liste[]=$c->id; // in that don't have
1437 } // references
1438 $c=next($headers);
1439 }
1440 reset($liste);
1441 if (count($liste)>0) {
1442 if (($thread_treestyle==2) || ($thread_treestyle==6) ||
1443 ($thread_treestyle==7)) {
1444 echo "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n";
1445 echo "<tr>\n";
1446 if ($thread_showDate) echo "<td>".$text_thread["date"]."&nbsp;</td>";
1447 if ($thread_showSubject) echo "<td>".$text_thread["subject"]."</td>";
1448 if ($thread_showAuthor) {
1449 echo "<td>&nbsp;&nbsp;</td>";
1450 echo "<td>".$text_thread["author"]."</td>\n";
1451 }
1452 echo "</tr>\n";
1453 showThread($headers,$liste,1,"",$group,$article_first,$article_last,
1454 $article_count);
1455 echo "</table>\n";
1456 } else {
1457 if ($thread_treestyle==1) echo "<ul>\n";
1458 showThread($headers,$liste,1,"",$group,$article_first,$article_last,
1459 $article_count);
1460 if ($thread_treestyle==1) echo "</ul>\n";
1461 }
1462 }
1463 }
1464 }
1465
1466 function MessageIdToUrl($id) {
1467 $id = ereg_replace("^<","",$id);
1468 $id = ereg_replace(">$","",$id);
1469 return urlencode($id);
1470 }
1471
1472 /*
1473 * Print the header of a message to the webpage
1474 *
1475 * $head: the header of the message as an headerType
1476 * $group: the name of the newsgroup, is needed for the links to post.php3
1477 * and the header.
1478 */
1479 function show_header($head,$group) {
1480 global $article_show,$text_header,$file_article,$attachment_show;
1481 global $file_attachment, $file_article, $server;
1482 if ($article_show["Subject"]) echo $text_header["subject"].htmlspecialchars($head->subject)."<br>";
1483 if ($article_show["From"]) {
1484 echo $text_header["from"].'<a href="mailto:'.htmlspecialchars($head->from).'">'.$head->from.'</a> ';
1485 if ($head->name != "") echo '('.htmlspecialchars($head->name).')';
1486 echo "<br>";
1487 }
1488 if ($article_show["Newsgroups"])
1489 echo $text_header["newsgroups"].htmlspecialchars(str_replace(',',', ',$head->newsgroups))."<br>\n";
1490 if (isset($head->followup) && ($article_show["Followup"]) && ($head->followup != ""))
1491 echo $text_header["followup"].htmlspecialchars($head->followup)."<br>\n";
1492 if ((isset($head->organization)) && ($article_show["Organization"]) &&
1493 ($head->organization != ""))
1494 echo $text_header["organization"].
1495 html_parse(htmlspecialchars($head->organization))."<br>\n";
1496 if ($article_show["Date"])
1497 echo $text_header["date"].date($text_header["date_format"],$head->date)."<br>\n";
1498 if ($article_show["Message-ID"])
1499 $a = MessageIdToUrl($head->id);
1500 echo $text_header["message-id"].htmlspecialchars($head->id)."[".'<a href="http://'.$server.'/'.$a.'">'."HTTP"."</a>][".'<a href="news://'.$server.'/'.$a.'">'."NNTP"."</a>]<br>\n";
1501 if (($article_show["References"]) && (isset($head->references[0]))) {
1502 echo $text_header["references"];
1503 for ($i=0; $i<=count($head->references)-1; $i++) {
1504 $ref=$head->references[$i];
1505 echo ' '.'<a href="../../'.$file_article.'/'.urlencode($group).'/'.
1506 urlencode($ref).'.html">'.($i+1).'</a>';
1507 }
1508 echo "<br>";
1509 }
1510 if (isset($head->user_agent)) {
1511 if ((isset($article_show["User-Agent"])) &&
1512 ($article_show["User-Agent"])) {
1513 echo $text_header["user-agent"].htmlspecialchars($head->user_agent)."<br>\n";
1514 } else {
1515 echo "<!-- User-Agent: ".htmlspecialchars($head->user_agent)." -->\n";
1516 }
1517 }
1518 if ((isset($attachment_show)) && ($attachment_show==true) &&
1519 (isset($head->content_type[1]))) {
1520 echo $text_header["attachments"];
1521 for ($i=1; $i<count($head->content_type); $i++) {
1522 echo '<a href="../../'.$file_attachment.'/'.urlencode($group).'/'.
1523 urlencode($head->number).'/'.
1524 $i.'/'.
1525 urlencode($head->content_type_name[$i]).'">'.
1526 $head->content_type_name[$i].'</a> ('.
1527 $head->content_type[$i].')';
1528 if ($i<count($head->content_type)-1) echo ', ';
1529 }
1530 }
1531 }
1532
1533
1534 /*
1535 function showAntwortKnopf($group,$id) {
1536 global $file_post;
1537 echo "<form action=\"$file_post\" method=post>\n";
1538 echo "<input type=submit value=\"Antworten\"\n>";
1539 echo "<input type=hidden name=\"type\" value=\"reply\">\n";
1540 echo "<input type=hidden name=\"id\" value=\"$id\">\n";
1541 echo "<input type=hidden name=\"group\" value=\"$group\">\n";
1542 echo "</form>\n";
1543 }
1544 */
1545
1546 /*
1547 * print an article to the webpage
1548 *
1549 * $group: The name of the newsgroup
1550 * $id: the ID of the article inside the group or the message-id
1551 * $attachment: The number of the attachment of the article.
1552 * 0 means the normal textbody.
1553 */
1554 function show_article($group,$id,$attachment=0,$article_data=false) {
1555 global $file_article;
1556 global $text_header,$article_showthread;
1557 if ($article_data == false)
1558 $article_data=read_message($id,$attachment,$group);
1559 $head=$article_data->header;
1560 $body=$article_data->body[$attachment];
1561 if ($head!=false) {
1562 if (($head->content_type[$attachment]=="text/plain") &&
1563 ($attachment==0)){
1564 show_header($head,$group);
1565 echo "<pre>\n";
1566 if(count($head->references)){
1567 $refs = $head->references;
1568 array_walk($refs, 'escape_regex');
1569 $msgidregex = "(&lt;|news:)(".join("|", $refs).")(&gt;)?";
1570 $msgidregex = str_replace("><", "|", $msgidregex);
1571 }
1572 $body=split("\n",$body);
1573 for ($i=0; $i<=count($body)-1; $i++) {
1574 // $b=textwrap($body[$i],80,"\n");
1575 // if ((strpos(substr($b,0,strpos($b," ")),'>') != false ) ||
1576 // (strcmp(substr($b,0,1),'>') == 0) ||
1577 // (strcmp(substr($b,0,1),':') == 0)) {
1578 // echo "<i>".html_parse(htmlspecialchars($b))."</i>\n";
1579 // } else {
1580 // echo html_parse(htmlspecialchars($b)."\n");
1581 // }
1582 // echo $body[$i]."\n";
1583 $b=$body[$i];
1584 echo html_parse(htmlspecialchars($b)."\n", $group, $msgidregex);
1585 }
1586 echo "\n</pre>\n";
1587 } else {
1588 echo $body;
1589 }
1590 }
1591 if ($article_showthread > 0) {
1592 }
1593 }
1594
1595 function escape_regex(&$value, $key){
1596 $value = QuoteMeta(substr($value, 1, -1));
1597 }
1598
1599 /*
1600 * Encode lines with 8bit-characters to quote-printable
1601 *
1602 * $line: the to be encoded line
1603 *
1604 * the function returns a sting containing the quoted-printable encoded
1605 * $line
1606 */
1607 function quoted_printable_encode($line) {
1608 $qp_table=array(
1609 '=00', '=01', '=02', '=03', '=04', '=05',
1610 '=06', '=07', '=08', '=09', '=0A', '=0B',
1611 '=0C', '=0D', '=0E', '=0F', '=10', '=11',
1612 '=12', '=13', '=14', '=15', '=16', '=17',
1613 '=18', '=19', '=1A', '=1B', '=1C', '=1D',
1614 '=1E', '=1F', '_', '!', '"', '#',
1615 '$', '%', '&', "'", '(', ')',
1616 '*', '+', ',', '-', '.', '/',
1617 '0', '1', '2', '3', '4', '5',
1618 '6', '7', '8', '9', ':', ';',
1619 '<', '=3D', '>', '=3F', '@', 'A',
1620 'B', 'C', 'D', 'E', 'F', 'G',
1621 'H', 'I', 'J', 'K', 'L', 'M',
1622 'N', 'O', 'P', 'Q', 'R', 'S',
1623 'T', 'U', 'V', 'W', 'X', 'Y',
1624 'Z', '[', '\\', ']', '^', '=5F',
1625 '', 'a', 'b', 'c', 'd', 'e',
1626 'f', 'g', 'h', 'i', 'j', 'k',
1627 'l', 'm', 'n', 'o', 'p', 'q',
1628 'r', 's', 't', 'u', 'v', 'w',
1629 'x', 'y', 'z', '{', '|', '}',
1630 '~', '=7F', '=80', '=81', '=82', '=83',
1631 '=84', '=85', '=86', '=87', '=88', '=89',
1632 '=8A', '=8B', '=8C', '=8D', '=8E', '=8F',
1633 '=90', '=91', '=92', '=93', '=94', '=95',
1634 '=96', '=97', '=98', '=99', '=9A', '=9B',
1635 '=9C', '=9D', '=9E', '=9F', '=A0', '=A1',
1636 '=A2', '=A3', '=A4', '=A5', '=A6', '=A7',
1637 '=A8', '=A9', '=AA', '=AB', '=AC', '=AD',
1638 '=AE', '=AF', '=B0', '=B1', '=B2', '=B3',
1639 '=B4', '=B5', '=B6', '=B7', '=B8', '=B9',
1640 '=BA', '=BB', '=BC', '=BD', '=BE', '=BF',
1641 '=C0', '=C1', '=C2', '=C3', '=C4', '=C5',
1642 '=C6', '=C7', '=C8', '=C9', '=CA', '=CB',
1643 '=CC', '=CD', '=CE', '=CF', '=D0', '=D1',
1644 '=D2', '=D3', '=D4', '=D5', '=D6', '=D7',
1645 '=D8', '=D9', '=DA', '=DB', '=DC', '=DD',
1646 '=DE', '=DF', '=E0', '=E1', '=E2', '=E3',
1647 '=E4', '=E5', '=E6', '=E7', '=E8', '=E9',
1648 '=EA', '=EB', '=EC', '=ED', '=EE', '=EF',
1649 '=F0', '=F1', '=F2', '=F3', '=F4', '=F5',
1650 '=F6', '=F7', '=F8', '=F9', '=FA', '=FB',
1651 '=FC', '=FD', '=FE', '=FF');
1652 // are there "forbidden" characters in the string?
1653 for($i=0; $i<strlen($line) && ord($line[$i])<=127 ; $i++);
1654 if ($i<strlen($line)) { // yes, there are. So lets encode them!
1655 $from=$i;
1656 for($to=strlen($line)-1; ord($line[$to])<=127; $to--);
1657 // lets scan for the start and the end of the to be encoded _words_
1658 for(;$from>0 && $line[$from] != ' '; $from--);
1659 if($from>0) $from++;
1660 for(;$to<strlen($line) && $line[$to] != ' '; $to++);
1661 // split the string into the to be encoded middle and the rest
1662 $begin=substr($line,0,$from);
1663 $middle=substr($line,$from,$to-$from);
1664 $end=substr($line,$to);
1665 // ok, now lets encode $middle...
1666 $newmiddle="";
1667 for($i=0; $i<strlen($middle); $i++)
1668 $newmiddle .= $qp_table[ord($middle[$i])];
1669 // now we glue the parts together...
1670 $line=$begin.'=?ISO-8859-1?Q?'.$newmiddle.'?='.$end;
1671 }
1672 return $line;
1673 }
1674
1675
1676
1677 /*
1678 * Post an article to a newsgroup
1679 *
1680 * $subject: The Subject of the article
1681 * $from: The authors name and email of the article
1682 * $newsgroups: The groups to post to
1683 * $ref: The references of the article
1684 * $body: The article itself
1685 */
1686 function verschicken($subject,$from,$newsgroups,$ref,$body) {
1687 global $server,$port,$send_poster_host,$organization,$text_error;
1688 global $file_footer;
1689 flush();
1690 $ns=OpenNNTPconnection($server,$port);
1691 if ($ns != false) {
1692 fputs($ns,"post\r\n");
1693 $weg=lieszeile($ns);
1694 // fputs($ns,'Subject: '.quoted_printable_encode($subject)."\r\n");
1695 fputs($ns,'Subject: '.mb_convert_encoding($subject, "ISO-2022-JP", "EUC-JP")."\r\n");
1696 // fputs($ns,'Subject: '.mb_encode_mimeheader($subject)."\r\n");
1697 fputs($ns,'From: '.$from."\r\n");
1698 fputs($ns,'Newsgroups: '.$newsgroups."\r\n");
1699 // fputs($ns,"Mime-Version: 1.0\r\n");
1700 // fputs($ns,"Content-Type: text/plain; charset=ISO-8859-1\r\n");
1701 // fputs($ns,"Content-Transfer-Encoding: 8bit\r\n");
1702 fputs($ns,"User-Agent: ".$text_ua["user_agent"]."\r\n");
1703 if ($send_poster_host)
1704 fputs($ns,'X-HTTP-Posting-Host: '.gethostbyaddr(getenv("REMOTE_ADDR"))."\r\n");
1705 if ($ref!=false) fputs($ns,'References: '.$ref."\r\n");
1706 if (isset($organization))
1707 fputs($ns,'Organization: '.mb_encode_mimeheader($organization)."\r\n");
1708 if ((isset($file_footer)) && ($file_footer!="")) {
1709 $footerfile=fopen($file_footer,"r");
1710 $body.="\n".fread($footerfile,filesize($file_footer));
1711 fclose($footerfile);
1712 }
1713 $body=str_replace("\n.\r","\n..\r",$body);
1714 $body=str_replace("\r",'',$body);
1715 $b=split("\n",$body);
1716 $body="";
1717 for ($i=0; $i<count($b); $i++) {
1718 if ((strpos(substr($b[$i],0,strpos($b[$i]," ")),">") != false ) | (strcmp(substr($b[$i],0,1),">") == 0)) {
1719 $body .= textwrap(stripSlashes($b[$i]),78,"\r\n")."\r\n";
1720 } else {
1721 $body .= textwrap(stripSlashes($b[$i]),74,"\r\n")."\r\n";
1722 }
1723 }
1724 $body = mb_convert_encoding($body, "ISO-2022-JP", "EUC-JP");
1725 fputs($ns,"\r\n".$body."\r\n.\r\n");
1726 $message=lieszeile($ns);
1727 closeNNTPconnection($ns);
1728 } else {
1729 $message=$text_error["post_failed"];
1730 }
1731 return $message . mb_encode_mimeheader($subject) . mb_encode_mimeheader($from);
1732 }
1733
1734 ?>

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24