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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24