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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.24 - (hide annotations) (download)
Sat Dec 1 15:15:08 2001 UTC (22 years, 5 months ago) by wakaba
Branch: MAIN
Changes since 1.23: +8 -6 lines
*** empty log message ***

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24