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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.33 - (show annotations) (download)
Sun Dec 2 05:07:42 2001 UTC (22 years, 5 months ago) by wakaba
Branch: MAIN
Changes since 1.32: +45 -26 lines
2001-12-02  wakaba <wakaba@suika.fam.cx>

	* reimplement uri linking.  add supported fields.
	* newsportal-style.css (.field, .field .name): new.
	* config.inc: add supported field.
	
	* ChangeLog: new.

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24