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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24