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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24