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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (show annotations) (download)
Sat Dec 1 12:07:26 2001 UTC (22 years, 5 months ago) by wakaba
Branch: MAIN
Changes since 1.3: +1 -1 lines
*** empty log message ***

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24