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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.35 - (show annotations) (download)
Mon Feb 11 13:35:52 2002 UTC (22 years, 3 months ago) by wakaba
Branch: MAIN
Changes since 1.34: +5 -11 lines
2002-02-11  wakaba <wakaba@suika.fam.cx>

	* newsportal.php (decode_structured_field): Fix unmatched () 
	of regexp.
	(encode_newsgroup): New function.
	* thread.php: Change PATH_INFO syntax.

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24