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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24