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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24