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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24