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

Contents of /messaging/newsportal/newsportal.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.28 - (hide annotations) (download)
Sun Dec 2 01:34:45 2001 UTC (22 years, 5 months ago) by wakaba
Branch: MAIN
Changes since 1.27: +10 -3 lines
*** empty log message ***

1 wakaba 1.1 <?
2     /*
3     Newsportal NNTP<->HTTP Gateway
4    
5     Version: 0.24pre3
6    
7     this Script is licensed under the GNU Public License
8    
9     Author: Florian Amrhein
10     eMail: florian.amrhein@gmx.de
11     Homepage: http://floh.gartenhaus.net
12     */
13    
14     /*
15     * the name and the description of a newsgroup
16     */
17     class newsgroupType {
18     var $name;
19     var $description;
20     var $count;
21     }
22    
23     /*
24     * Stores a complete article:
25     * - The parsed Header as an headerType
26     * - The bodies and attachments as an array of array of lines
27     */
28     class messageType {
29     var $header;
30     var $body;
31     }
32    
33    
34    
35     /*
36     * Stores the Header of an article
37     */
38     class headerType {
39     var $number; // the Number of an article inside a group
40     var $id; // Message-ID
41     var $from; // eMail of the author
42     var $name; // Name of the author
43     var $subject; // the subject
44     var $newsgroups; // the Newsgroups where the article belongs to
45     var $followup;
46     var $date;
47     var $organization;
48     var $references;
49     var $content_transfer_encoding;
50     var $mime_version;
51     var $content_type; // array, Content-Type of the Body (Index=0) and the
52     // Attachments (Index>0)
53     var $content_type_charset; // like content_type
54     var $content_type_name; // array of the names of the attachments
55     var $content_type_boundary; // The boundary of an multipart-article.
56     var $answers;
57     var $isAnswer;
58     var $username;
59     var $user_agent;
60     var $isReply;
61     }
62    
63     /*
64     * opens the connection to the NNTP-Server
65     *
66     * $server: adress of the NNTP-Server
67     * $port: port of the server
68     */
69     function OpenNNTPconnection($nserver=0,$nport=0) {
70     global $text_error,$server_auth_user,$server_auth_pass,$readonly;
71     global $server,$port;
72     if ($nserver==0) $nserver=$server;
73     if ($nport==0) $nport=$port;
74     $ns=fsockopen($nserver,$nport);
75     $weg=lieszeile($ns); // kill the first line
76     if (substr($weg,0,2) != "20") {
77     echo "<p>".$text_error["error:"]."</p>";
78     } else {
79     if ($ns != false) {
80     fputs($ns,"mode reader\r\n");
81     $weg=lieszeile($ns); // and once more
82     if (substr($weg,0,2) != "20") {
83     echo "<p>".$text_error["error:"]."</p>";
84     }
85     }
86     if ((isset($server_auth_user)) && (isset($server_auth_pass)) &&
87     ($server_auth_user != "")) {
88     fputs($ns,"authinfo user $server_auth_user\r\n");
89     $weg=lieszeile($ns);
90     fputs($ns,"authinfo pass $server_auth_pass\r\n");
91     $weg=lieszeile($ns);
92     if (substr($weg,0,3) != "281") {
93     echo "<p>".$text_error["error:"]."</p>";
94     echo "<p>".$text_error["auth_error"]."</p>";
95     }
96     }
97     }
98     if ($ns==false) echo "<p>".$text_error["connection_failed"]."</p>";
99     return $ns;
100     }
101    
102     /*
103     * Close a NNTP connection
104     *
105     * $ns: the handle of the connection
106     */
107     function closeNNTPconnection(&$ns) {
108     if ($ns != false) {
109     fputs($ns,"quit\r\n");
110     fclose($ns);
111     }
112     }
113    
114     /*
115     * Validates an email adress
116     *
117     * $address: a string containing the email-address to be validated
118     *
119     * returns true if the address passes the tests, false otherwise.
120     */
121     function validate_email($address)
122     {
123     global $validate_email;
124     $return=true;
125     if (($validate_email >= 1) && ($return == true))
126     $return = (ereg('^[-!#$%&\'*+\\./0-9=?A-Z^_A-z{|}~]+'.'@'.
127     '[-!#$%&\'*+\\/0-9=?A-Z^_A-z{|}~]+\.'.
128     '[-!#$%&\'*+\\./0-9=?A-Z^_A-z{|}~]+$',$address));
129     if (($validate_email >= 2) && ($return == true)) {
130     $addressarray=address_decode($address,"garantiertungueltig");
131     $return=checkdnsrr($addressarray[0]["host"],"MX");
132     if (!$return) $return=checkdnsrr($addressarray[0]["host"],"A");
133     }
134     return($return);
135     }
136    
137     /*
138     * decodes a block of 7bit-data in uuencoded format to it's original
139     * 8bit format.
140     * The headerline containing filename and permissions doesn't have to
141     * be included.
142     *
143     * $data: The uuencoded data as a string
144     *
145     * returns the 8bit data as a string
146     *
147     * Note: this function is very slow and doesn't recognize incorrect code.
148     */
149     function uudecode_line($line) {
150     $data=substr($line,1);
151     $length=ord($line[0])-32;
152     $decoded="";
153     for ($i=0; $i<(strlen($data)>>2); $i++) {
154     $pack=substr($data,$i<<2,4);
155     $upack="";
156     $bitmaske=0;
157     for ($o=0; $o<4; $o++) {
158     $g=((ord($pack[3-$o])-32));
159     if ($g==64) $g=0;
160     $bitmaske=$bitmaske | ($g << (6*$o));
161     }
162     $schablone=255;
163     for ($o=0; $o<3; $o++) {
164     $c=($bitmaske & $schablone) >> ($o << 3);
165     $schablone=($schablone << 8);
166     $upack=chr($c).$upack;
167     }
168     $decoded.=$upack;
169     }
170     $decoded=substr($decoded,0,$length);
171     return $decoded;
172     }
173     function uudecode($data) {
174     $d=explode("\n",$data);
175     $u="";
176     for ($i=0; $i<count($d)-1; $i++)
177     $u.=uudecode_line($d[$i]);
178     return $u;
179     }
180    
181     /*
182     * returns the mimetype of an filename
183     *
184     * $name: the complete filename of a file
185     *
186     * returns a string containing the mimetype
187     */
188     function get_mimetype_by_filename($name) {
189     $ending=strtolower(strrchr($name,"."));
190     switch($ending) {
191     case ".jpg":
192     $type="image/jpeg";
193     break;
194     case ".gif":
195     $type="image/gif";
196     break;
197     default:
198     $type="text/plain";
199     }
200     return $type;
201     }
202    
203     function showPageSelectMenu($article_count,$first) {
204     global $articles_per_page,$file_thread,$file_framethread,$name;
205     /* if (isset($file_framethread)) {
206     $thread=$file_framethread;
207     } else {
208     $thread=$file_thread;
209     }
210     */
211     $pages=ceil($article_count / $articles_per_page);
212     if ($article_count > $articles_per_page)
213     for ($i = 0; $i < $pages; $i++) {
214     echo '[';
215     if ($first != $i*$articles_per_page+1)
216     echo '<a href="'.($i*$articles_per_page+1).'_'.
217     ($i+1)*$articles_per_page.'.html">';
218     echo ($i*$articles_per_page+1).'-';
219     if ($i == $pages-1) {
220     echo $article_count;
221     } else {
222     echo ($i+1)*$articles_per_page;
223     }
224     if ($first != $i*$articles_per_page+1)
225     echo '</a>';
226     echo '] ';
227     }
228     }
229    
230     function testGroup($groupname) {
231     global $testgroup;
232     if ($testgroup) {
233     $gf=fopen("groups.txt","r");
234     while (!feof($gf)) {
235     $read=trim(lieszeile($gf));
236     $pos=strpos($read," ");
237     if ($pos != false) {
238     if (substr($read,0,$pos)==trim($groupname)) return true;
239     } else {
240     if ($read == trim($groupname)) return true;
241     }
242     }
243     fclose($gf);
244     return false;
245     } else {
246     return true;
247     }
248     }
249    
250     function testGroups($newsgroups) {
251     $groups=explode(",",$newsgroups);
252     $count=count($groups);
253     $return="";
254     $o=0;
255     for ($i=0; $i<$count; $i++) {
256     if (testgroup($groups[$i])) {
257     if ($o>0) $return.=",";
258     $o++;
259     $return.=$groups[$i];
260     }
261     }
262     return($return);
263     }
264    
265     /*
266     * read one line from the NNTP-server
267     */
268     function lieszeile(&$ns) {
269     if ($ns != false) {
270     $t=str_replace("\n","",str_replace("\r","",fgets($ns,1200)));
271     return $t;
272     }
273     }
274    
275     /*
276     * Split an internet-address string into its parts. An address string could
277     * be for example:
278     * - user@host.domain (Realname)
279     * - "Realname" <user@host.domain>
280     * - user@host.domain
281     *
282     * The address will be split into user, host (incl. domain) and realname
283     *
284     * $adrstring: The string containing the address in internet format
285     * $defaulthost: The name of the host which should be returned if the
286     * address-string doesn't contain a hostname.
287     *
288     * returns an hash containing the fields "mailbox", "host" and "personal"
289     */
290     function address_decode($adrstring,$defaulthost) {
291     $parsestring=trim($adrstring);
292     $len=strlen($parsestring);
293     $at_pos=strpos($parsestring,'@'); // find @
294     $ka_pos=strpos($parsestring,"("); // find (
295     $kz_pos=strpos($parsestring,')'); // find )
296     $ha_pos=strpos($parsestring,'<'); // find <
297     $hz_pos=strpos($parsestring,'>'); // find >
298     $space_pos=strpos($parsestring,')'); // find ' '
299     $email="";
300     $mailbox="";
301     $host="";
302     $personal="";
303     if ($space_pos != false) {
304     if (($ka_pos != false) && ($kz_pos != false)) {
305     $personal=substr($parsestring,$ka_pos+1,$kz_pos-$ka_pos-1);
306     $email=trim(substr($parsestring,0,$ka_pos-1));
307     }
308     } else {
309     $email=$adrstring;
310     }
311     if (($ha_pos != false) && ($hz_pos != false)) {
312     $email=trim(substr($parsestring,$ha_pos+1,$hz_pos-$ha_pos-1));
313     $personal=substr($parsestring,0,$ha_pos-1);
314     }
315     if ($at_pos != false) {
316     $mailbox=substr($email,0,strpos($email,'@'));
317     $host=substr($email,strpos($email,'@')+1);
318     } else {
319     $mailbox=$email;
320     $host=$defaulthost;
321     }
322     $personal=trim($personal);
323     if (substr($personal,0,1) == '"') $personal=substr($personal,1);
324     if (substr($personal,strlen($personal)-1,1) == '"')
325     $personal=substr($personal,0,strlen($personal)-1);
326     $result["mailbox"]=trim($mailbox);
327     $result["host"]=trim($host);
328     // $personal = mb_convert_encoding($personal, "EUC-JP", "auto");
329     if ($personal!="") $result["personal"]=$personal;
330     $complete[]=$result;
331     return ($complete);
332     }
333    
334    
335    
336     function readGroups($server,$port) {
337     $ns=OpenNNTPconnection($server,$port);
338     if ($ns == false) return false;
339     $gf=fopen("groups.txt","r");
340     while (!feof($gf)) {
341     $gruppe=new newsgroupType;
342     $tmp=trim(lieszeile($gf));
343     $pos=strpos($tmp," ");
344     if ($pos != false) {
345     $gruppe->name=substr($tmp,0,$pos);
346     $desc=substr($tmp,$pos);
347     } else {
348     $gruppe->name=$tmp;
349     fputs($ns,"xgtitle $gruppe->name\r\n");
350     $response=liesZeile($ns);
351     if (strcmp(substr($response,0,3),"282") == 0) {
352     $neu=liesZeile($ns);
353     do {
354     $response=$neu;
355     if ($neu != ".") $neu=liesZeile($ns);
356     } while ($neu != ".");
357     $desc=strrchr($response,"\t");
358     if (strcmp($response,".") == 0) {
359     $desc="-";
360     }
361     } else {
362     $desc=$response;
363     }
364     if (strcmp(substr($response,0,3),"500") == 0)
365     $desc="-";
366     }
367     if (strcmp($desc,"") == 0) $desc="-";
368     $gruppe->description=$desc;
369     fputs($ns,"group ".$gruppe->name."\r\n");
370     $response=liesZeile($ns);
371     $t=strchr($response," ");
372     $t=substr($t,1,strlen($t)-1);
373     $gruppe->count=substr($t,0,strpos($t," "));
374     if ((strcmp(trim($gruppe->name),"") != 0) &&
375     (substr($gruppe->name,0,1) != "#"))
376     $newsgroups[]=$gruppe;
377     }
378     fclose($gf);
379     closeNNTPconnection($ns);
380     return $newsgroups;
381     }
382    
383     /*
384     * print the group names from an array to the webpage
385     */
386     function showgroups($gruppen) {
387     if ($gruppen == false) return;
388     global $file_thread,$text_groups;
389     $c = count($gruppen);
390     echo "<table>\n";
391     echo "<tr><td>#</td><td>".$text_groups["newsgroup"].
392     "</td><td>".$text_groups["description"]."</td></tr>\n";
393     for($i = 0 ; $i < $c ; $i++) {
394     $g = $gruppen[$i];
395     echo "<tr><td>";
396     echo "$g->count</td><td>";
397     echo '<a ';
398     if ((isset($frame_threadframeset)) && ($frame_threadframeset != ""))
399     echo 'target="'.$frame_threadframeset.'" ';
400     echo 'href="'.$file_thread.'/'.urlencode($g->name).'/index.html">'.$g->name."</a></td>\n";
401     echo "<td>$g->description</td></tr>\n";
402     flush();
403     }
404     echo "</table>\n";
405     }
406    
407     /*
408     * gets a list of aviable articles in the group $groupname
409     */
410     function getArticleList(&$von,$groupname) {
411     fputs($von,"listgroup $groupname \r\n");
412     $zeile=lieszeile($von);
413     $zeile=lieszeile($von);
414     while(strcmp($zeile,".") != 0) {
415     $articleList[] = trim($zeile);
416     $zeile=lieszeile($von);
417     }
418     if (!isset($articleList)) $articleList="-";
419     return $articleList;
420     }
421    
422     /*
423     * Decode quoted-printable or base64 encoded headerlines
424     *
425     * $value: The to be decoded line
426     *
427     * returns the decoded line
428     */
429     function headerDecode($value) {
430     if (eregi('=\?.*\?.\?.*\?=',$value)) { // is there anything encoded?
431     if (eregi('=\?.*\?Q\?.*\?=',$value)) { // quoted-printable decoding
432     $result1=eregi_replace('(.*)=\?.*\?Q\?(.*)\?=(.*)','\1',$value);
433     $result2=eregi_replace('(.*)=\?.*\?Q\?(.*)\?=(.*)','\2',$value);
434     $result3=eregi_replace('(.*)=\?.*\?Q\?(.*)\?=(.*)','\3',$value);
435     $result2=str_replace("_"," ",quoted_printable_decode($result2));
436     $newvalue=$result1.$result2.$result3;
437     }
438     if (eregi('=\?.*\?B\?.*\?=',$value)) { // base64 decoding
439     $result1=eregi_replace('(.*)=\?.*\?B\?(.*)\?=(.*)','\1',$value);
440     $result2=eregi_replace('(.*)=\?.*\?B\?(.*)\?=(.*)','\2',$value);
441     $result3=eregi_replace('(.*)=\?.*\?B\?(.*)\?=(.*)','\3',$value);
442     $result2=base64_decode($result2);
443     $newvalue=$result1.$result2.$result3;
444     }
445     if (!isset($newvalue)) // nothig of them, must be an unknown encoding...
446     $newvalue=$value;
447     else
448     $newvalue=headerDecode($newvalue); // maybe there are more encoded
449     return(mb_convert_encoding($newvalue, "EUC-JP", "auto")); // parts
450 wakaba 1.5 } else {
451 wakaba 1.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 wakaba 1.28 mb_convert_encoding(fake_jisx0213($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 wakaba 1.28 "mb_convert_encoding(fake_jisx0213(decode_quoted_pair('\\1')),'EUC-JP','auto')",
590     "'('.mb_convert_encoding(fake_jisx0213(decode_quoted_pair('\\1')),
591     'EUC-JP','auto').')'",
592 wakaba 1.25 );
593 wakaba 1.24 return preg_replace ($patterns, $replace, $body);
594     }
595    
596     function decode_quoted_pair($value) {
597     $value = ereg_replace('\\\\(\\\\")', "\\1", $value);
598     return ereg_replace('\\\\(.)', "\\1", $value);
599 wakaba 1.28 }
600    
601     function fake_jisx0213 ($value) {
602     $value = preg_replace ("/\\x1B\\\$\\(O/", "\x1B\\\$B", $value);
603     $value = preg_replace ("/\\x1B\\\$\\(P/", "\x1B\\\$(D", $value);
604     return $value;
605 wakaba 1.1 }
606    
607     function decode_body($body,$encoding) {
608     $bodyzeile="";
609     switch ($encoding) {
610     case "base64":
611     $body=base64_decode($body);
612     break;
613     case "quoted-printable":
614     $body=Quoted_printable_decode($body);
615     $body=str_replace("=\n","",$body);
616     // default:
617     // $body=str_replace("\n..\n","\n.\n",$body);
618     }
619     return $body;
620     }
621    
622     function parse_message($rawmessage) {
623     global $attachment_delete_alternative,$attachment_uudecode;
624     // Read the header of the message:
625     $count_rawmessage=count($rawmessage);
626     $message = new messageType;
627     $rawheader=array();
628     $i=0;
629     while ($rawmessage[$i] != "") {
630     $rawheader[]=$rawmessage[$i];
631     $i++;
632     }
633     // Parse the Header:
634     $message->header=parse_header($rawheader);
635     // Now we know if the message is a mime-multipart message:
636     $content_type=split("/",$message->header->content_type[0]);
637     if ($content_type[0]=="multipart") {
638     $message->header->content_type=array();
639     // We have multible bodies, so we split the message into its parts
640     $boundary="--".$message->header->content_type_boundary;
641     // lets find the first part
642     while($rawmessage[$i] != $boundary)
643     $i++;
644     $i++;
645     $part=array();
646     while($i<=$count_rawmessage) {
647     if (($rawmessage[$i]==$boundary) || ($i==$count_rawmessage-1) ||
648     ($rawmessage[$i]==$boundary.'--')) {
649     $partmessage=parse_message($part);
650     // merge the content-types of the message with those of the part
651     for ($o=0; $o<count($partmessage->header->content_type); $o++) {
652     $message->header->content_type[]=
653     $partmessage->header->content_type[$o];
654     $message->header->content_type_charset[]=
655     $partmessage->header->content_type_charset[$o];
656     $message->header->content_type_name[]=
657     $partmessage->header->content_type_name[$o];
658     $message->body[]=$partmessage->body[$o];
659     }
660     $part=array();
661     } else {
662     if ($i<$count_rawmessage)
663     $part[]=$rawmessage[$i];
664     }
665     if ($rawmessage[$i]==$boundary.'--') break;
666     $i++;
667     }
668     // Is this a multipart/alternative multipart-message? Do we have to
669     // delete all non plain/text parts?
670     if (($attachment_delete_alternative) &&
671     ($content_type[1]=="alternative")) {
672     $plaintext=false;
673     for ($o=0; $o<count($message->header->content_type); $o++) {
674     if ($message->header->content_type[$o]=="text/plain")
675     $plaintext=true; // we found at least one text/plain
676     }
677     if ($plaintext) { // now we can delete the other parts
678     for ($o=0; $o<count($message->header->content_type); $o++) {
679     if ($message->header->content_type[$o]!="text/plain") {
680     unset($message->header->content_type[$o]);
681     unset($message->header->content_type_name[$o]);
682     unset($message->header->content_type_charset[$o]);
683     unset($message->body[$o]);
684     }
685     }
686     }
687     }
688     } else {
689     // No mime-attachments in the message:
690     $body="";
691     $uueatt=0; // as default we have no uuencoded attachments
692     for($i++;$i<$count_rawmessage; $i++) {
693     // do we have an inlay uuencoded file?
694     if ((strtolower(substr($rawmessage[$i],0,5))!="begin") ||
695     ($attachment_uudecode==false)) {
696     $body.=$rawmessage[$i]."\n";
697     // yes, it seems, we have!
698     } else {
699     $old_i=$i;
700     $uue_infoline_raw=$rawmessage[$i];
701     $uue_infoline=explode(" ",$uue_infoline_raw);
702     $uue_data="";
703     $i++;
704     while($rawmessage[$i]!="end") {
705     if (strlen(trim($rawmessage[$i])) > 2)
706     $uue_data.=$rawmessage[$i]."\n";
707     $i++;
708     }
709     // now write the data in an attachment
710     $uueatt++;
711     $message->body[$uueatt]=uudecode($uue_data);
712     $message->header->content_type_name[$uueatt]="";
713     for ($o=2; $o<count($uue_infoline); $o++)
714     $message->header->content_type_name[$uueatt].=$uue_infoline[$o];
715     $message->header->content_type[$uueatt]=
716     get_mimetype_by_filename($message->header->content_type_name[$uueatt]);
717     }
718     }
719     // if ($message->header->content_type[0]=="text/plain") {
720     // $body=trim($body);
721     // if ($body=="") $body=" ";
722     // }
723     $body=decode_body($body,$message->header->content_transfer_encoding);
724 wakaba 1.25 $message->body[0] = mb_convert_encoding($body, "EUC-JP", "auto");
725 wakaba 1.1 }
726     if (!isset($message->header->content_type_charset))
727     $message->header->content_type_charset=array("ISO-8859-1");
728     if (!isset($message->header->content_type_name))
729     $message->header->content_type_name=array("unnamed");
730     for ($o=0; $o<count($message->body); $o++) {
731     if (!isset($message->header->content_type_charset[$o]))
732     $message->header->content_type_charset[$o]="ISO-8859-1";
733     if (!isset($message->header->content_type_name[$o]))
734     $message->header->content_type_name[$o]="unnamed";
735     }
736     return $message;
737     }
738    
739     /*
740     * read an article from the newsserver or the spool-directory
741     *
742     * $id: the Message-ID of an article
743     * $bodynum: the number of the attachment:
744     * -1: return only the header without any bodies or attachments.
745     * 0: the body
746     * 1: the first attachment...
747     *
748     * The function returns an article as an messageType or false if the article
749     * doesn't exists on the newsserver or doesn't contain the given
750     * attachment.
751     */
752     function read_message($id,$bodynum=0,$group="") {
753     global $cache_articles,$spooldir,$text_error;
754     $message = new messageType;
755     if ((isset($cache_articles)) && ($cache_articles == true)) {
756     if ((ereg('^[0-9]+$',$id)) && ($group != ''))
757     $filename=$group.'_'.$id;
758     else
759     $filename=base64_encode($id);
760     $cachefilename_header=$spooldir."/".$filename.'.header';
761     $cachefilename_body=$spooldir."/".$filename.'.body';
762     if (file_exists($cachefilename_header)) {
763     $cachefile=fopen($cachefilename_header,"r");
764     $message->header=unserialize(fread($cachefile,filesize($cachefilename_header)));
765     fclose($cachefile);
766     } else {
767     unset($message->header);
768     }
769     // Is a non-existing attachment of an article requested?
770     if ((isset($message->header)) &&
771     ($bodynum!= -1) &&
772     (!isset($message->header->content_type[$bodynum])))
773     return false;
774     if ((file_exists($cachefilename_body.$bodynum)) &&
775     ($bodynum != -1)) {
776     $cachefile=fopen($cachefilename_body.$bodynum,"r");
777     $message->body[$bodynum]=
778     fread($cachefile,filesize($cachefilename_body.$bodynum));
779     fclose($cachefile);
780     }
781     }
782     if ((!isset($message->header)) ||
783     ((!isset($message->body[$bodynum])) &&
784     ($bodynum != -1))) {
785     if (!isset($ns)) $ns=openNNTPconnection();
786     if ($group != "") {
787     fputs($ns,"group ".$group."\r\n");
788     $zeile=lieszeile($ns);
789     }
790     fputs($ns,'article '.$id."\r\n");
791     $zeile=lieszeile($ns);
792     if (substr($zeile,0,3) != "220")
793     return false;
794     $rawmessage=array();
795     $line=lieszeile($ns);
796 wakaba 1.10 #$line=mb_convert_encoding($line, "EUC-JP", "ISO-2022-JP");
797 wakaba 1.1 while(strcmp($line,".") != 0) {
798     $rawmessage[]=$line;
799     $line=lieszeile($ns);
800 wakaba 1.10 #$line=mb_convert_encoding($line, "EUC-JP", "ISO-2022-JP");
801 wakaba 1.1 }
802     $message=parse_message($rawmessage);
803     if (ereg('^[0-9]+$',$id)) $message->header->number=$id;
804     // write header, body and attachments to disk
805     if ((isset($cache_articles)) && ($cache_articles == true)) {
806     $cachefile=fopen($cachefilename_header,"w");
807     if ($cachefile) {
808     fputs($cachefile,serialize($message->header));
809     }
810     fclose($cachefile);
811     for ($i=0; $i<count($message->header->content_type); $i++) {
812     if (isset($message->body[$i])) {
813     $cachefile=fopen($cachefilename_body.$i,"w");
814     fwrite($cachefile,$message->body[$i]);
815     fclose($cachefile);
816     }
817     }
818     }
819     }
820     return $message;
821     }
822    
823     function textwrap($text, $wrap=80, $break="\n"){
824     $len = strlen($text);
825     if ($len > $wrap) {
826     $h = ''; // massaged text
827     $lastWhite = 0; // position of last whitespace char
828     $lastChar = 0; // position of last char
829     $lastBreak = 0; // position of last break
830     // while there is text to process
831     while ($lastChar < $len) {
832     $char = substr($text, $lastChar, 1); // get the next character
833     // if we are beyond the wrap boundry and there is a place to break
834     if (($lastChar - $lastBreak > $wrap) && ($lastWhite > $lastBreak)) {
835     $h .= substr($text, $lastBreak, ($lastWhite - $lastBreak)) . $break;
836     $lastChar = $lastWhite + 1;
837     $lastBreak = $lastChar;
838     }
839     // You may wish to include other characters as valid whitespace...
840     if ($char == ' ' || $char == chr(13) || $char == chr(10)) {
841     $lastWhite = $lastChar; // note the position of the last whitespace
842     }
843     $lastChar = $lastChar + 1; // advance the last character position by one
844     }
845     $h .= substr($text, $lastBreak); // build line
846     } else {
847     $h = $text; // in this case everything can fit on one line
848     }
849     return $h;
850     }
851    
852     /*
853     * makes URLs clickable
854     *
855     * $comment: A text-line probably containing links.
856     *
857     * the function returns the text-line with HTML-Links to the links or
858     * email-adresses.
859     */
860     function html_parse($comment, $group = "", $msgidregex = "") {
861     global $frame_externallink;
862     global $file_article;
863     if ((isset($frame_externallink)) && ($frame_externallink != "")) {
864     $target=' TARGET="'.$frame_externallink.'" ';
865     } else {
866     $target=' ';
867     }
868     $ncomment = eregi_replace( 'http://([-a-z0-9_./~@?=%#&;]+)', '<a'.$target.'href="http://\1">http://\1</a>', $comment);
869     if ($ncomment == $comment)
870     $ncomment = eregi_replace( '(www\.[-a-z]+\.(de|int|eu|dk|org|net|at|ch|com|jp))','<a'.$target.'href="http://\1">\1</a>',$comment);
871     $comment=$ncomment;
872     $comment = eregi_replace( 'https://([-a-z0-9_./~@?=%#&;\n]+)', '<a'.$target.'href="https://\1">https://\1</a>', $comment);
873     $comment = eregi_replace( 'gopher://([-a-z0-9_./~@?=%\n]+)','<a'.$target.'href="gopher://\1">gopher://\1</a>', $comment);
874     $comment = eregi_replace( 'news://([-a-z0-9_./~@?=%\n]+)','<a'.$target.'href="news://\1">news://\1</a>', $comment);
875     $comment = eregi_replace( 'ftp://([-a-z0-9_./~@?=%\n]+)', '<a'.$target.'href="ftp://\1">ftp://\1</a>', $comment);
876     if(!empty($msgidregex) && ereg($msgidregex, $comment)){
877     //$comment = ereg_replace( $msgidregex, '<a'.$target.'href="http://'.$SERVER_NAME.'/\1">&lt;\1&gt;</a>', $comment);
878     $comment = preg_replace( '/'.$msgidregex.'/e', "'<a$target'.'href=\"../../'.addslashes('$file_article').'/'.urlencode('$group').'/'.urlencode('<\\2>').'.html\">\\1\\2\\3</a>'", $comment);
879     } else{
880     $comment = eregi_replace( '([-a-z0-9_./n]+)@([-a-z0-9_.]+)','<a href="mailto:\1@\2">\1@\2</a>', $comment);
881     }
882     return($comment);
883     }
884    
885    
886    
887    
888     /*
889     * read the header of an article in plaintext into an array
890     * $articleNumber can be the number of an article or its message-id.
891     */
892     function readPlainHeader(&$von,$group,$articleNumber) {
893     fputs($von,"group $group\r\n");
894     $zeile=lieszeile($von);
895     fputs($von,"head $articleNumber\r\n");
896     $zeile=lieszeile($von);
897     if (substr($zeile,0,3) != "221") {
898     echo $text_error["article_not_found"];
899     $header=false;
900     } else {
901     $zeile=lieszeile($von);
902     $body="";
903     while(strcmp(trim($zeile),".") != 0) {
904     $body .= $zeile."\n";
905     $zeile=lieszeile($von);
906     }
907     return split("\n",str_replace("\r\n","\n",$body));
908     }
909     }
910    
911     function readArticles(&$von,$groupname,$articleList) {
912     for($i = 0; $i <= count($articleList)-1 ; $i++) {
913     $temp=read_header($von,$articleList[$i]);
914     $articles[$temp->id] = $temp;
915     }
916     return $articles;
917     }
918    
919     /*
920     * Remove re: aw: etc. from a subject.
921     *
922     * $subject: a string containing the complete Subject
923     *
924     * The function removes the re:, aw: etc. from $subject end returns true
925     * if it removed anything, and false if not.
926     */
927     function splitSubject(&$subject) {
928     $s=eregi_replace('^(aw:|re:|re\[2\]:| )+','',$subject);
929     $return=($s != $subject);
930     $subject=$s;
931     return $return;
932     }
933    
934     function interpretOverviewLine($zeile,$overviewformat,$groupname) {
935     $return="";
936     $overviewfmt=explode("\t",$overviewformat);
937     echo " "; // keep the connection to the webbrowser alive
938     flush(); // while generating the message-tree
939     $over=split("\t",$zeile,count($overviewfmt)-1);
940     $article=new headerType;
941     for ($i=0; $i<count($overviewfmt)-1; $i++) {
942     if ($overviewfmt[$i]=="Subject:") {
943     $subject=headerDecode($over[$i+1]);
944     $article->isReply=splitSubject($subject);
945     $article->subject=$subject;
946     }
947     if ($overviewfmt[$i]=="Date:") {
948     $article->date=getTimestamp($over[$i+1]);
949     }
950     if ($overviewfmt[$i]=="From:") {
951     $fromline=address_decode(headerDecode($over[$i+1]),"nirgendwo");
952     $article->from=$fromline[0]["mailbox"]."@".$fromline[0]["host"];
953     $article->username=$fromline[0]["mailbox"];
954     if (!isset($fromline[0]["personal"])) {
955     $article->name=$fromline[0]["mailbox"];
956     if (strpos($article->name,'%')) {
957     $article->name=substr($article->name,0,strpos($article->name,'%'));
958     }
959     $article->name=strtr($article->name,'_',' ');
960     } else {
961     $article->name=$fromline[0]["personal"];
962     }
963     }
964     if ($overviewfmt[$i]=="Message-ID:") $article->id=$over[$i+1];
965     if (($overviewfmt[$i]=="References:") && ($over[$i+1] != ""))
966     $article->references=explode(" ",$over[$i+1]);
967     }
968     $article->number=$over[0];
969     $article->isAnswer=false;
970     return($article);
971     }
972    
973     /*
974     * Rebuild the Overview-File
975     */
976     function rebuildOverview(&$von,$groupname,$poll) {
977     global $spooldir,$maxarticles,$maxfetch,$initialfetch,$maxarticles_extra;
978     global $text_error,$text_thread,$compress_spoolfiles,$server;
979     $idstring="0.22,".$server.",".$compress_spoolfiles.",".$maxarticles.",".
980     $maxarticles_extra.",".$maxfetch.",".$initialfetch;
981     fputs($von,"list overview.fmt\r\n"); // find out the format of the
982     $tmp=liesZeile($von); // xover-command
983     $zeile=liesZeile($von);
984     while (strcmp($zeile,".") != 0) {
985     $overviewfmt[]=$zeile;
986     $zeile=liesZeile($von);
987     }
988     $overviewformat=implode("\t",$overviewfmt);
989     $spoolfilename=$spooldir."/".$groupname."-data.dat";
990     fputs($von,"group $groupname\r\n"); // select a group
991     $groupinfo=explode(" ",liesZeile($von));
992     if (substr($groupinfo[0],0,1) != 2) {
993     echo "<p>".$text_error["error:"]."</p>";
994     echo "<p>".$text_thread["no_such_group"]."</p>";
995     flush();
996     } else {
997     $infofilename=$spooldir."/".$groupname."-info.txt";
998     $spoolopenmodus="n";
999     if (!((file_exists($infofilename)) && (file_exists($spoolfilename)))) {
1000     $spoolopenmodus="w";
1001     } else {
1002     $infofile=fopen($infofilename,"r");
1003     $oldid=fgets($infofile,100);
1004     if (trim($oldid) != $idstring) {
1005     echo "<!-- Database Error, rebuilding Database...-->\n";
1006     $spoolopenmodus="w";
1007     }
1008     $oldgroupinfo=explode(" ",trim(fgets($infofile,200)));
1009     fclose($infofile);
1010     if ($groupinfo[3] < $oldgroupinfo[1]) {
1011     $spoolopenmodus="w";
1012     }
1013     if ($maxarticles == 0) {
1014     if ($groupinfo[2] != $oldgroupinfo[0]) $spoolopenmodus="w";
1015     } else {
1016     if ($groupinfo[2] > $oldgroupinfo[0]) $spoolopenmodus="w";
1017     }
1018     if (($spoolopenmodus == "n") && ($groupinfo[3] > $oldgroupinfo[1]))
1019     $spoolopenmodus="a";
1020     }
1021     if ($spoolopenmodus=="a") {
1022     $firstarticle=$oldgroupinfo[1]+1;
1023     $lastarticle=$groupinfo[3];
1024     }
1025     if ($spoolopenmodus=="w") {
1026     $firstarticle=$groupinfo[2];
1027     $lastarticle=$groupinfo[3];
1028     }
1029     if ($spoolopenmodus != "n") {
1030     if ($maxarticles != 0) {
1031     if ($spoolopenmodus == "w") {
1032     $firstarticle=$lastarticle-$maxarticles+1;
1033     if ($firstarticle < $groupinfo[2])
1034     $firstarticle=$groupinfo[2];
1035     } else {
1036     if ($lastarticle-$oldgroupinfo[0]+1 > $maxarticles + $maxarticles_extra) {
1037     $firstarticle=$lastarticle-$maxarticles+1;
1038     $spoolopenmodus="w";
1039     }
1040     }
1041     }
1042     if (($maxfetch!=0) && (($lastarticle-$firstarticle+1) > $maxfetch)) {
1043     if ($spoolopenmodus=="w") {
1044     $tofetch=($initialfetch != 0) ? $initialfetch : $maxfetch;
1045     $lastarticle=$firstarticle+$tofetch-1;
1046     } else {
1047     $lastarticle=$firstarticle+$maxfetch-1;
1048     }
1049     }
1050     }
1051     echo "<!--openmodus: ".$spoolopenmodus."-->\n";
1052     if ($spoolopenmodus != "w") $headers=loadThreadData($groupname);
1053     if ($spoolopenmodus != "n") {
1054     fputs($von,"xover ".$firstarticle."-".$lastarticle."\r\n"); // and read the overview
1055     $tmp=liesZeile($von);
1056     if (substr($tmp,0,3) == "224") {
1057     $zeile=liesZeile($von);
1058     while ($zeile != ".") {
1059     $article=interpretOverviewLine($zeile,$overviewformat,$groupname);
1060     $headers[$article->id]=$article;
1061     if($poll) {
1062     echo $article->number.", "; flush();
1063     read_message($article->number,0,$groupname);
1064     }
1065     $zeile=lieszeile($von);
1066     }
1067     }
1068     if (file_exists($spoolfilename)) unlink($spoolfilename);
1069     if (count($headers)>0) {
1070     $infofile=fopen($infofilename,"w");
1071     if ($spoolopenmodus=="a") $firstarticle=$oldgroupinfo[0];
1072     fputs($infofile,$idstring."\n");
1073     fputs($infofile,$firstarticle." ".$lastarticle."\r\n");
1074     fclose($infofile);
1075     reset($headers);
1076     $c=current($headers); // read one article
1077     for ($i=0 ; $i<=count($headers)-1 ; $i++) {
1078     if (($c->isAnswer == false) &&
1079     (isset($c->references[0]))) { // is the article an answer to an
1080     // other article?
1081     $o=count($c->references)-1;
1082     $ref=$c->references[$o];
1083     while (($o >= 0) && (!isset($headers[$ref]))) { // try to find a
1084     $ref=$c->references[$o]; // matching article
1085     $o--; // to the reference
1086     }
1087     if ($o >= 0) { // found a matching article?
1088     $c->isAnswer=true; // so the Article is an answer
1089     $headers[$c->id]=$c;
1090     $headers[$ref]->answers[]=$c->id; // the referenced article gets
1091     // the ID of the article
1092     }
1093     }
1094     $c=next($headers);
1095     }
1096     reset($headers);
1097     saveThreadData($headers,$groupname);
1098     }
1099     }
1100     return((isset($headers)) ? $headers : false);
1101     }
1102     }
1103    
1104    
1105     /*
1106     * Read the Overview.
1107     * Format of the overview-file:
1108     * message-id
1109     * date
1110     * subject
1111     * author
1112     * email
1113     * references
1114     */
1115     function mycompare($a,$b) {
1116     global $thread_sorting;
1117     if ($a->date==$b->date) $r=0;
1118     $r=($a->date<$b->date) ? -1 : 1;
1119     return $r*$thread_sorting;
1120     }
1121     function readOverview(&$von,$groupname,$readmode = 1,$poll=false) {
1122     global $text_error, $maxarticles;
1123     global $spooldir,$thread_sorting;
1124     if (!testGroup($groupname)) {
1125     echo $text_error["read_access_denied"];
1126     return;
1127     }
1128     if ($von == false) return false;
1129     if (($von!=false) && ($readmode > 0))
1130     $articles=rebuildOverview($von,$groupname,$poll);
1131     if ((isset($articles)) && ($articles)) {
1132     if (($thread_sorting != 0) && (count($articles)>0))
1133     uasort($articles,'mycompare');
1134     return $articles;
1135     } else {
1136     return false;
1137     }
1138     }
1139    
1140     function str_change($str,$pos,$char) {
1141     return(substr($str,0,$pos).$char.substr($str,$pos+1,strlen($str)-$pos));
1142     }
1143    
1144     function formatDate($c) {
1145     global $age_count,$age_time,$age_color,$date_format;
1146     $return="";
1147     $currentTime=time();
1148     $color="";
1149     if ($age_count > 0)
1150     for($t = $age_count; $t >= 1; $t--)
1151     if ($currentTime - $c->date < $age_time[$t]) $color = $age_color[$t];
1152     if ($color != "") $return .= '<font color="'.$color.'">';
1153     if (!isset($date_format)) $date_format = "d.m.";
1154     $return .= date($date_format,$c->date); // format the date
1155     if ($color != "") $return .= '</font>';
1156     return($return);
1157     }
1158    
1159     function calculateTree($newtree,$depth,$num,$liste,$c) {
1160     if ((isset($c->answers[0])) && (count($c->answers)>0)) {
1161     $newtree.="*";
1162     } else {
1163     if ($depth == 1) {
1164     $newtree.="o";
1165     } else {
1166     $newtree.="-";
1167     }
1168     }
1169     if (($num == count($liste)-1) && ($depth>1)) {
1170     $newtree=str_change($newtree,$depth-2,"`");
1171     }
1172     return($newtree);
1173     }
1174    
1175    
1176     /*
1177     * Format the message-tree
1178     * Zeichen im Baum:
1179     * o : leerer Kasten k1.gif
1180     * * : Kasten mit Zeichen drin k2.gif
1181     * i : vertikale Linie I.gif
1182     * - : horizontale Linie s.gif
1183     * + : T-Stueck T.gif
1184     * ` : Winkel L.gif
1185     */
1186     function formatTreeGraphic($newtree) {
1187     global $imgdir;
1188     $return="";
1189     for ($o=0 ; $o<strlen($newtree) ; $o++) {
1190     $return .= '<img src="../../'.$imgdir.'/';
1191     $k=substr($newtree,$o,1);
1192     $alt=$k;
1193     switch ($k) {
1194     case "o":
1195     $return .= 'k1.gif';
1196     break;
1197     case "*":
1198     $return .= 'k2.gif';
1199     break;
1200     case "i":
1201     $return .= 'I.gif';
1202     $alt='|';
1203     break;
1204     case "-":
1205     $return .= 's.gif';
1206     break;
1207     case "+":
1208     $return .= 'T.gif';
1209     break;
1210     case "`":
1211     $return .= 'L.gif';
1212     break;
1213     case ".":
1214     $return .= 'e.gif';
1215     $alt='&nbsp;';
1216     break;
1217     }
1218     $return .= '" alt="'.$alt.'"';
1219 wakaba 1.3 if (strcmp($k,".") == 0) $return .=(' style="width: 12px; height: 9px"');
1220     $return .= '>';
1221 wakaba 1.1 }
1222     return($return);
1223     }
1224    
1225     function formatTreeText($tree) {
1226     $tree=str_replace("i","|",$tree);
1227     $tree=str_replace(".","&nbsp;",$tree);
1228     return($tree);
1229     }
1230    
1231     function formatSubject($c,$group) {
1232     if ($c->isReply) {
1233     $re="Re: ";
1234     } else {
1235     $re="";
1236     }
1237     global $file_article, $thread_maxSubject, $frame_article;
1238     $return='<a ';
1239     if ((isset($frame_article)) && ($frame_article != ""))
1240     $return .= 'target="'.$frame_article.'" ';
1241     $return .= 'href="../../'.$file_article.
1242     // '?id='.urlencode($c->id).'&amp;group='.urlencode($group).'">'.
1243     '/'.urlencode($group).'/'.urlencode($c->number).'.html">'.
1244     $re.htmlspecialchars(substr(trim($c->subject),0,$thread_maxSubject))."</a>";
1245     return($return);
1246     }
1247    
1248     function formatAuthor($c) {
1249     $return = '<a href="mailto:'.trim($c->from).'">';
1250     if (trim($c->name)!="") {
1251     // $return .= htmlspecialchars(trim(mb_convert_encoding($c->name, "EUC-JP", "auto")));
1252     $return .= htmlspecialchars(trim($c->name));
1253     } else {
1254     if (isset($c->username)) {
1255     $s = strpos($c->username,"%");
1256     if ($s != false) {
1257     $return .= htmlspecialchars(substr($c->username,0,$s));
1258     } else {
1259     $return .= htmlspecialchars($c->username);
1260     }
1261     }
1262     }
1263     $return .= "</a>";
1264     return($return);
1265     }
1266    
1267     function showThread(&$headers,&$liste,$depth,$tree,$group,$article_first=0,$article_last=0,&$article_count) {
1268     global $thread_treestyle;
1269     global $thread_showDate,$thread_showSubject;
1270     global $thread_showAuthor,$imgdir;
1271     global $file_article,$thread_maxSubject;
1272     global $age_count,$age_time,$age_color;
1273     global $frame_article,$thread_fontPre,$thread_fontPost;
1274     if ($thread_treestyle==3) echo "\n<UL>\n";
1275     for ($i = 0 ; $i<count($liste) ; $i++) {
1276     $c=$headers[$liste[$i]]; // read the first article
1277     $article_count++;
1278     switch ($thread_treestyle) {
1279     case 4: // thread
1280     case 5: // thread, graphic
1281     case 6: // thread, table
1282     case 7: // thread, table, graphic
1283     $newtree=calculateTree($tree,$depth,$i,$liste,$c);
1284     }
1285     if (($article_first == 0) ||
1286     (($article_count >= $article_first) &&
1287     ($article_count <= $article_last))) {
1288     switch ($thread_treestyle) {
1289     case 0: // simple list
1290     echo $thread_fontPre;
1291     if ($thread_showDate) echo formatDate($c)." ";
1292     if ($thread_showSubject) echo formatSubject($c,$group)." ";
1293     if ($thread_showAuthor) echo "(".formatAuthor($c).")";
1294     echo $thread_fontPost;
1295     echo "<br>\n";
1296     break;
1297     case 1: // html-auflistung, kein baum
1298 wakaba 1.3 echo "<li>".$thread_fontPre;
1299 wakaba 1.1 if ($thread_showDate)
1300     echo formatDate($c)." ";
1301     if ($thread_showSubject)
1302     echo formatSubject($c,$group)." ";
1303     if ($thread_showAuthor)
1304 wakaba 1.3 echo "<em>(".formatAuthor($c).")</em>";
1305     echo $thread_fontPost."</li>";
1306 wakaba 1.1 break;
1307     case 2: // table
1308     echo "<tr>";
1309     if ($thread_showDate)
1310     echo "<td>".$thread_fontPre.formatDate($c)." ".$thread_fontPost."</td>";
1311     if ($thread_showSubject) {
1312     echo '<td nowrap="nowrap">'.$thread_fontPre.formatSubject($c,$group);
1313     echo $thread_fontPost."</td>";
1314     }
1315     if ($thread_showAuthor) {
1316     echo "<td></td>";
1317 wakaba 1.3 echo '<td>'.$thread_fontPre.formatAuthor($c);
1318 wakaba 1.1 echo $thread_fontPost."</td>";
1319     }
1320     echo "</tr>\n";
1321     break;
1322     case 3: // html-tree
1323 wakaba 1.3 echo "<li>".$thread_fontPre;
1324 wakaba 1.1 if ($thread_showDate)
1325     echo formatDate($c)." ";
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."\n";
1331 wakaba 1.1 break;
1332     case 4: // thread
1333 wakaba 1.3 echo "".$thread_fontPre;
1334 wakaba 1.1 if ($thread_showDate)
1335     echo formatDate($c)." ";
1336     echo formatTreeText($newtree)." ";
1337     if ($thread_showSubject)
1338     echo formatSubject($c,$group)." ";
1339     if ($thread_showAuthor)
1340 wakaba 1.3 echo "<em>(".formatAuthor($c).")</em>";
1341     echo $thread_fontPost."<br>";
1342 wakaba 1.1 break;
1343     case 5: // thread, graphic
1344 wakaba 1.3 echo "<table><tr>\n";
1345 wakaba 1.1 if ($thread_showDate)
1346 wakaba 1.3 echo '<td>'.$thread_fontPre.formatDate($c)." ".$thread_fontPost."</td>";
1347 wakaba 1.1 echo "<td>".$thread_fontPre.formatTreeGraphic($newtree).$thread_fontPost."</td>";
1348     if ($thread_showSubject)
1349 wakaba 1.3 echo '<td>'.$thread_fontPre."&nbsp;".formatSubject($c,$group)." ";
1350 wakaba 1.1 if ($thread_showAuthor)
1351     echo "(".formatAuthor($c).")".$thread_fontPost."</td>";
1352     echo "</tr></table>";
1353     break;
1354     case 6: // thread, table
1355     echo "<tr>";
1356     if ($thread_showDate)
1357 wakaba 1.3 echo '<td>'.$thread_fontPre.formatDate($c)." ".$thread_fontPost."</td>";
1358     echo '<td>'.$thread_fontPre.formatTreeText($newtree)." ";
1359 wakaba 1.1 if ($thread_showSubject) {
1360 wakaba 1.3 echo formatSubject($c,$group).$thread_fontPost."</td>";
1361 wakaba 1.1 echo "<td></td>";
1362     }
1363     if ($thread_showAuthor)
1364 wakaba 1.3 echo '<td>'.$thread_fontPre.formatAuthor($c).$thread_fontPost."</td>";
1365 wakaba 1.1 echo "</tr>";
1366     break;
1367     case 7: // thread, table, graphic
1368     echo "<tr>";
1369     if ($thread_showDate)
1370 wakaba 1.3 echo '<td>'.$thread_fontPre.formatDate($c)." ".$thread_fontPost."</td>";
1371     echo "<td><table>\n";
1372 wakaba 1.1 echo "<td>".formatTreeGraphic($newtree)."</td>";
1373     if ($thread_showSubject)
1374 wakaba 1.3 echo '<td>'.$thread_fontPre."&nbsp;".formatSubject($c,$group).$thread_fontPost."</td>";
1375 wakaba 1.1 echo "</table></td>";
1376     if ($thread_showSubject) echo "<td></td>";
1377     if ($thread_showAuthor)
1378 wakaba 1.3 echo '<td>'.$thread_fontPre.formatAuthor($c).$thread_fontPost."</td>";
1379 wakaba 1.1 echo "</tr>";
1380     break;
1381     }
1382     }
1383     if ((isset($c->answers[0])) && (count($c->answers)>0) &&
1384     ($article_count<=$article_last)) {
1385     if ($thread_treestyle >= 4) {
1386     if (substr($newtree,$depth-2,1) == "+")
1387     $newtree=str_change($newtree,$depth-2,"i");
1388     $newtree=str_change($newtree,$depth-1,"+");
1389     $newtree=strtr($newtree,"`",".");
1390     }
1391     if (!isset($newtree)) $newtree="";
1392     showThread($headers,$c->answers,$depth+1,$newtree."",$group,
1393     $article_first,$article_last,$article_count);
1394     }
1395     flush();
1396     }
1397     if ($thread_treestyle==3) echo "</UL>";
1398     }
1399    
1400    
1401     /*
1402     * Load a thread from disk
1403     *
1404     * $group: name of the newsgroup, is needed to create the filename
1405     *
1406     * the function returns an array of headerType containing the
1407     * overview-data of the thread.
1408     */
1409     function loadThreadData($group) {
1410     global $spooldir,$compress_spoolfiles;
1411     $filename=$spooldir."/".$group."-data.dat";
1412     if ($compress_spoolfiles) {
1413     $file=gzopen("$spooldir/$group-data.dat","r");
1414     $headers=unserialize(gzread($file,1000000));
1415     gzclose($file);
1416     } else {
1417     $file=fopen($filename,"r");
1418     $headers=unserialize(fread($file,filesize($filename)));
1419     fclose($file);
1420     }
1421     return($headers);
1422     }
1423    
1424    
1425     /*
1426     * Save the thread to disk
1427     *
1428     * $header: is an array of headerType containing all overview-information
1429     * of a newsgroup
1430     * $group: name of the newsgroup, is needed to create the filename
1431     */
1432     function saveThreadData($headers,$group) {
1433     global $spooldir,$compress_spoolfiles;
1434     if ($compress_spoolfiles) {
1435     $file=gzopen("$spooldir/$group-data.dat","w");
1436     gzputs($file,serialize($headers));
1437     gzclose($file);
1438     } else {
1439     $file=fopen("$spooldir/$group-data.dat","w");
1440     fputs($file,serialize($headers));
1441     fclose($file);
1442     }
1443     }
1444    
1445    
1446     function showHeaders(&$headers,$group,$article_first=0,$article_last=0) {
1447     global $thread_showDate, $thread_showTable;
1448     global $thread_showAuthor,$thread_showSubject;
1449     global $text_thread,$thread_treestyle;
1450     $article_count=0;
1451     if ($headers == false) {
1452     echo $text_thread["no_articles"];
1453     } else {
1454     reset($headers);
1455     $c=current($headers);
1456     for ($i=0; $i<=count($headers)-1; $i++) { // create the array $liste
1457     if ($c->isAnswer == false) { // where are all the articles
1458     $liste[]=$c->id; // in that don't have
1459     } // references
1460     $c=next($headers);
1461     }
1462     reset($liste);
1463     if (count($liste)>0) {
1464     if (($thread_treestyle==2) || ($thread_treestyle==6) ||
1465     ($thread_treestyle==7)) {
1466     echo "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n";
1467     echo "<tr>\n";
1468     if ($thread_showDate) echo "<td>".$text_thread["date"]."&nbsp;</td>";
1469     if ($thread_showSubject) echo "<td>".$text_thread["subject"]."</td>";
1470     if ($thread_showAuthor) {
1471     echo "<td>&nbsp;&nbsp;</td>";
1472     echo "<td>".$text_thread["author"]."</td>\n";
1473     }
1474     echo "</tr>\n";
1475     showThread($headers,$liste,1,"",$group,$article_first,$article_last,
1476     $article_count);
1477     echo "</table>\n";
1478     } else {
1479     if ($thread_treestyle==1) echo "<ul>\n";
1480     showThread($headers,$liste,1,"",$group,$article_first,$article_last,
1481     $article_count);
1482     if ($thread_treestyle==1) echo "</ul>\n";
1483     }
1484     }
1485     }
1486     }
1487    
1488     function MessageIdToUrl($id) {
1489     $id = ereg_replace("^<","",$id);
1490     $id = ereg_replace(">$","",$id);
1491     return urlencode($id);
1492     }
1493    
1494     /*
1495     * Print the header of a message to the webpage
1496     *
1497     * $head: the header of the message as an headerType
1498     * $group: the name of the newsgroup, is needed for the links to post.php3
1499     * and the header.
1500     */
1501     function show_header($head,$group) {
1502     global $article_show,$text_header,$file_article,$attachment_show;
1503     global $file_attachment, $file_article, $server;
1504     if ($article_show["Subject"]) echo $text_header["subject"].htmlspecialchars($head->subject)."<br>";
1505     if ($article_show["From"]) {
1506     echo $text_header["from"].'<a href="mailto:'.htmlspecialchars($head->from).'">'.$head->from.'</a> ';
1507     if ($head->name != "") echo '('.htmlspecialchars($head->name).')';
1508     echo "<br>";
1509     }
1510     if ($article_show["Newsgroups"])
1511     echo $text_header["newsgroups"].htmlspecialchars(str_replace(',',', ',$head->newsgroups))."<br>\n";
1512     if (isset($head->followup) && ($article_show["Followup"]) && ($head->followup != ""))
1513     echo $text_header["followup"].htmlspecialchars($head->followup)."<br>\n";
1514     if ((isset($head->organization)) && ($article_show["Organization"]) &&
1515     ($head->organization != ""))
1516     echo $text_header["organization"].
1517     html_parse(htmlspecialchars($head->organization))."<br>\n";
1518     if ($article_show["Date"])
1519     echo $text_header["date"].date($text_header["date_format"],$head->date)."<br>\n";
1520     if ($article_show["Message-ID"])
1521     $a = MessageIdToUrl($head->id);
1522     echo $text_header["message-id"].htmlspecialchars($head->id)."[".'<a href="http://'.$server.'/'.$a.'">'."HTTP"."</a>][".'<a href="news://'.$server.'/'.$a.'">'."NNTP"."</a>]<br>\n";
1523     if (($article_show["References"]) && (isset($head->references[0]))) {
1524     echo $text_header["references"];
1525     for ($i=0; $i<=count($head->references)-1; $i++) {
1526     $ref=$head->references[$i];
1527     echo ' '.'<a href="../../'.$file_article.'/'.urlencode($group).'/'.
1528     urlencode($ref).'.html">'.($i+1).'</a>';
1529     }
1530     echo "<br>";
1531     }
1532     if (isset($head->user_agent)) {
1533     if ((isset($article_show["User-Agent"])) &&
1534     ($article_show["User-Agent"])) {
1535     echo $text_header["user-agent"].htmlspecialchars($head->user_agent)."<br>\n";
1536     } else {
1537     echo "<!-- User-Agent: ".htmlspecialchars($head->user_agent)." -->\n";
1538 wakaba 1.27 }
1539     }
1540     if (isset($head->x_moe)) {
1541     if ((isset($article_show["X-Moe"])) && ($article_show["X-Moe"])) {
1542     echo "<span class=\"field x-moe\"><span class=\"name\">".$text_header["X-Moe"]
1543     ."</span> <span class=\"body\">"
1544     .htmlspecialchars($head->x_moe)."</span>\n";
1545 wakaba 1.1 }
1546     }
1547     if ((isset($attachment_show)) && ($attachment_show==true) &&
1548     (isset($head->content_type[1]))) {
1549     echo $text_header["attachments"];
1550     for ($i=1; $i<count($head->content_type); $i++) {
1551     echo '<a href="../../'.$file_attachment.'/'.urlencode($group).'/'.
1552     urlencode($head->number).'/'.
1553     $i.'/'.
1554     urlencode($head->content_type_name[$i]).'">'.
1555     $head->content_type_name[$i].'</a> ('.
1556     $head->content_type[$i].')';
1557     if ($i<count($head->content_type)-1) echo ', ';
1558     }
1559     }
1560     }
1561    
1562    
1563     /*
1564     function showAntwortKnopf($group,$id) {
1565     global $file_post;
1566     echo "<form action=\"$file_post\" method=post>\n";
1567     echo "<input type=submit value=\"Antworten\"\n>";
1568     echo "<input type=hidden name=\"type\" value=\"reply\">\n";
1569     echo "<input type=hidden name=\"id\" value=\"$id\">\n";
1570     echo "<input type=hidden name=\"group\" value=\"$group\">\n";
1571     echo "</form>\n";
1572     }
1573     */
1574    
1575     /*
1576     * print an article to the webpage
1577     *
1578     * $group: The name of the newsgroup
1579     * $id: the ID of the article inside the group or the message-id
1580     * $attachment: The number of the attachment of the article.
1581     * 0 means the normal textbody.
1582     */
1583     function show_article($group,$id,$attachment=0,$article_data=false) {
1584     global $file_article;
1585     global $text_header,$article_showthread;
1586     if ($article_data == false)
1587     $article_data=read_message($id,$attachment,$group);
1588     $head=$article_data->header;
1589     $body=$article_data->body[$attachment];
1590     if ($head!=false) {
1591     if (($head->content_type[$attachment]=="text/plain") &&
1592     ($attachment==0)){
1593     show_header($head,$group);
1594     echo "<pre>\n";
1595     if(count($head->references)){
1596     $refs = $head->references;
1597     array_walk($refs, 'escape_regex');
1598     $msgidregex = "(&lt;|news:)(".join("|", $refs).")(&gt;)?";
1599     $msgidregex = str_replace("><", "|", $msgidregex);
1600     }
1601     $body=split("\n",$body);
1602     for ($i=0; $i<=count($body)-1; $i++) {
1603     // $b=textwrap($body[$i],80,"\n");
1604     // if ((strpos(substr($b,0,strpos($b," ")),'>') != false ) ||
1605     // (strcmp(substr($b,0,1),'>') == 0) ||
1606     // (strcmp(substr($b,0,1),':') == 0)) {
1607     // echo "<i>".html_parse(htmlspecialchars($b))."</i>\n";
1608     // } else {
1609     // echo html_parse(htmlspecialchars($b)."\n");
1610     // }
1611     // echo $body[$i]."\n";
1612     $b=$body[$i];
1613     echo html_parse(htmlspecialchars($b)."\n", $group, $msgidregex);
1614     }
1615     echo "\n</pre>\n";
1616     } else {
1617     echo $body;
1618     }
1619     }
1620     if ($article_showthread > 0) {
1621     }
1622     }
1623    
1624     function escape_regex(&$value, $key){
1625     $value = QuoteMeta(substr($value, 1, -1));
1626     }
1627    
1628     /*
1629     * Encode lines with 8bit-characters to quote-printable
1630     *
1631     * $line: the to be encoded line
1632     *
1633     * the function returns a sting containing the quoted-printable encoded
1634     * $line
1635     */
1636     function quoted_printable_encode($line) {
1637     $qp_table=array(
1638     '=00', '=01', '=02', '=03', '=04', '=05',
1639     '=06', '=07', '=08', '=09', '=0A', '=0B',
1640     '=0C', '=0D', '=0E', '=0F', '=10', '=11',
1641     '=12', '=13', '=14', '=15', '=16', '=17',
1642     '=18', '=19', '=1A', '=1B', '=1C', '=1D',
1643     '=1E', '=1F', '_', '!', '"', '#',
1644     '$', '%', '&', "'", '(', ')',
1645     '*', '+', ',', '-', '.', '/',
1646     '0', '1', '2', '3', '4', '5',
1647     '6', '7', '8', '9', ':', ';',
1648     '<', '=3D', '>', '=3F', '@', 'A',
1649     'B', 'C', 'D', 'E', 'F', 'G',
1650     'H', 'I', 'J', 'K', 'L', 'M',
1651     'N', 'O', 'P', 'Q', 'R', 'S',
1652     'T', 'U', 'V', 'W', 'X', 'Y',
1653     'Z', '[', '\\', ']', '^', '=5F',
1654     '', 'a', 'b', 'c', 'd', 'e',
1655     'f', 'g', 'h', 'i', 'j', 'k',
1656     'l', 'm', 'n', 'o', 'p', 'q',
1657     'r', 's', 't', 'u', 'v', 'w',
1658     'x', 'y', 'z', '{', '|', '}',
1659     '~', '=7F', '=80', '=81', '=82', '=83',
1660     '=84', '=85', '=86', '=87', '=88', '=89',
1661     '=8A', '=8B', '=8C', '=8D', '=8E', '=8F',
1662     '=90', '=91', '=92', '=93', '=94', '=95',
1663     '=96', '=97', '=98', '=99', '=9A', '=9B',
1664     '=9C', '=9D', '=9E', '=9F', '=A0', '=A1',
1665     '=A2', '=A3', '=A4', '=A5', '=A6', '=A7',
1666     '=A8', '=A9', '=AA', '=AB', '=AC', '=AD',
1667     '=AE', '=AF', '=B0', '=B1', '=B2', '=B3',
1668     '=B4', '=B5', '=B6', '=B7', '=B8', '=B9',
1669     '=BA', '=BB', '=BC', '=BD', '=BE', '=BF',
1670     '=C0', '=C1', '=C2', '=C3', '=C4', '=C5',
1671     '=C6', '=C7', '=C8', '=C9', '=CA', '=CB',
1672     '=CC', '=CD', '=CE', '=CF', '=D0', '=D1',
1673     '=D2', '=D3', '=D4', '=D5', '=D6', '=D7',
1674     '=D8', '=D9', '=DA', '=DB', '=DC', '=DD',
1675     '=DE', '=DF', '=E0', '=E1', '=E2', '=E3',
1676     '=E4', '=E5', '=E6', '=E7', '=E8', '=E9',
1677     '=EA', '=EB', '=EC', '=ED', '=EE', '=EF',
1678     '=F0', '=F1', '=F2', '=F3', '=F4', '=F5',
1679     '=F6', '=F7', '=F8', '=F9', '=FA', '=FB',
1680     '=FC', '=FD', '=FE', '=FF');
1681     // are there "forbidden" characters in the string?
1682     for($i=0; $i<strlen($line) && ord($line[$i])<=127 ; $i++);
1683     if ($i<strlen($line)) { // yes, there are. So lets encode them!
1684     $from=$i;
1685     for($to=strlen($line)-1; ord($line[$to])<=127; $to--);
1686     // lets scan for the start and the end of the to be encoded _words_
1687     for(;$from>0 && $line[$from] != ' '; $from--);
1688     if($from>0) $from++;
1689     for(;$to<strlen($line) && $line[$to] != ' '; $to++);
1690     // split the string into the to be encoded middle and the rest
1691     $begin=substr($line,0,$from);
1692     $middle=substr($line,$from,$to-$from);
1693     $end=substr($line,$to);
1694     // ok, now lets encode $middle...
1695     $newmiddle="";
1696     for($i=0; $i<strlen($middle); $i++)
1697     $newmiddle .= $qp_table[ord($middle[$i])];
1698     // now we glue the parts together...
1699     $line=$begin.'=?ISO-8859-1?Q?'.$newmiddle.'?='.$end;
1700     }
1701     return $line;
1702     }
1703    
1704    
1705    
1706     /*
1707     * Post an article to a newsgroup
1708     *
1709     * $subject: The Subject of the article
1710     * $from: The authors name and email of the article
1711     * $newsgroups: The groups to post to
1712     * $ref: The references of the article
1713     * $body: The article itself
1714     */
1715     function verschicken($subject,$from,$newsgroups,$ref,$body) {
1716     global $server,$port,$send_poster_host,$organization,$text_error;
1717     global $file_footer;
1718     flush();
1719     $ns=OpenNNTPconnection($server,$port);
1720     if ($ns != false) {
1721     fputs($ns,"post\r\n");
1722     $weg=lieszeile($ns);
1723     // fputs($ns,'Subject: '.quoted_printable_encode($subject)."\r\n");
1724 wakaba 1.3 fputs($ns,'Subject: '.mb_convert_encoding($subject, "ISO-2022-JP", "EUC-JP")."\r\n");
1725     // fputs($ns,'Subject: '.mb_encode_mimeheader($subject)."\r\n");
1726 wakaba 1.1 fputs($ns,'From: '.$from."\r\n");
1727     fputs($ns,'Newsgroups: '.$newsgroups."\r\n");
1728     // fputs($ns,"Mime-Version: 1.0\r\n");
1729     // fputs($ns,"Content-Type: text/plain; charset=ISO-8859-1\r\n");
1730     // fputs($ns,"Content-Transfer-Encoding: 8bit\r\n");
1731 wakaba 1.6 fputs($ns,"User-Agent: ".$text_ua["user_agent"]."\r\n");
1732 wakaba 1.1 if ($send_poster_host)
1733     fputs($ns,'X-HTTP-Posting-Host: '.gethostbyaddr(getenv("REMOTE_ADDR"))."\r\n");
1734     if ($ref!=false) fputs($ns,'References: '.$ref."\r\n");
1735     if (isset($organization))
1736     fputs($ns,'Organization: '.mb_encode_mimeheader($organization)."\r\n");
1737     if ((isset($file_footer)) && ($file_footer!="")) {
1738     $footerfile=fopen($file_footer,"r");
1739     $body.="\n".fread($footerfile,filesize($file_footer));
1740     fclose($footerfile);
1741     }
1742     $body=str_replace("\n.\r","\n..\r",$body);
1743     $body=str_replace("\r",'',$body);
1744     $b=split("\n",$body);
1745     $body="";
1746     for ($i=0; $i<count($b); $i++) {
1747     if ((strpos(substr($b[$i],0,strpos($b[$i]," ")),">") != false ) | (strcmp(substr($b[$i],0,1),">") == 0)) {
1748     $body .= textwrap(stripSlashes($b[$i]),78,"\r\n")."\r\n";
1749     } else {
1750     $body .= textwrap(stripSlashes($b[$i]),74,"\r\n")."\r\n";
1751     }
1752     }
1753     $body = mb_convert_encoding($body, "ISO-2022-JP", "EUC-JP");
1754     fputs($ns,"\r\n".$body."\r\n.\r\n");
1755     $message=lieszeile($ns);
1756     closeNNTPconnection($ns);
1757     } else {
1758     $message=$text_error["post_failed"];
1759     }
1760     return $message . mb_encode_mimeheader($subject) . mb_encode_mimeheader($from);
1761     }
1762    
1763     ?>

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24