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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24