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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.23 - (show annotations) (download)
Sat Dec 1 14:02:09 2001 UTC (22 years, 5 months ago) by wakaba
Branch: MAIN
Changes since 1.22: +8 -3 lines
*** empty log message ***

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24