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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (show annotations) (download) (vendor branch)
Sat Dec 1 11:17:31 2001 UTC (22 years, 5 months ago) by wakaba
Branch: suika
CVS Tags: initial
Changes since 1.1: +0 -0 lines

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24