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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24