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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24