Fixed bug in menu bar
[mspang/www.git] / newsgroup / newsportal.php
1 <?
2 /*  Newsportal NNTP<->HTTP Gateway
3  *  Version: 0.36
4  *  Download: http://florian-amrhein.de/newsportal
5  *
6  *  Copyright (C) 2002-2004 Florian Amrhein
7  *  E-Mail: newsportal@florian-amrhein.de
8  *  Web: http://florian-amrhein.de
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23  */
24
25 include "lib/types.inc.php";
26 include "lib/thread.inc.php";
27 include "lib/message.inc.php";
28 include "lib/post.inc.php";
29 //include "lib/validator.inc.php";
30
31 /*
32  * opens the connection to the NNTP-Server
33  *
34  * $server: adress of the NNTP-Server
35  * $port: port of the server
36  */
37 function nntp_open($nserver=0,$nport=0) {
38   global $text_error,$server_auth_user,$server_auth_pass,$readonly;
39   global $server,$port;
40   // echo "<br>NNTP OPEN<br>";
41   $authorize=((isset($server_auth_user)) && (isset($server_auth_pass)) &&
42               ($server_auth_user != ""));
43   if ($nserver==0) $nserver=$server;
44   if ($nport==0) $nport=$port;
45   $ns=@fsockopen($nserver,$nport);
46   $weg=line_read($ns);  // kill the first line
47   if (substr($weg,0,2) != "20") {
48     echo "<p>".$text_error["error:"].$weg."</p>";
49     fclose($ns);
50     $ns=false;
51   } else {
52     if ($ns != false) {
53       fputs($ns,"MODE reader\r\n");
54       $weg=line_read($ns);  // and once more
55       if ((substr($weg,0,2) != "20") && 
56           ((!$authorize) || ((substr($weg,0,3) != "480") && ($authorize)))) {
57         echo "<p>".$text_error["error:"].$weg."</p>";
58         fclose($ns);
59         $ns=false;
60       }
61     }
62     if ((isset($server_auth_user)) && (isset($server_auth_pass)) &&
63         ($server_auth_user != "")) {
64       fputs($ns,"AUTHINFO USER $server_auth_user\r\n");
65       $weg=line_read($ns);
66       fputs($ns,"AUTHINFO PASS $server_auth_pass\r\n"); 
67       $weg=line_read($ns);
68       if (substr($weg,0,3) != "281") {
69         echo "<p>".$text_error["error:"]."</p>";
70         echo "<p>".$text_error["auth_error"]."</p>";
71       }
72     }
73   }
74   if ($ns==false) echo "<p>".$text_error["connection_failed"]."</p>";
75   return $ns;
76 }
77
78 /*
79  * Close a NNTP connection
80  *
81  * $ns: the handle of the connection
82  */
83 function nntp_close(&$ns) {
84   if ($ns != false) {
85     fputs($ns,"QUIT\r\n");
86     fclose($ns);
87   }
88 }
89
90 /*
91  * Validates an email adress
92  *
93  * $address: a string containing the email-address to be validated
94  *
95  * returns true if the address passes the tests, false otherwise.
96  */
97 function validate_email($address)
98 {
99   global $validate_email;
100   $return=true;
101   if (($validate_email >= 1) && ($return == true))
102     $return = (ereg('^[-!#$%&\'*+\\./0-9=?A-Z^_A-z{|}~]+'.'@'.
103                '[-!#$%&\'*+\\/0-9=?A-Z^_A-z{|}~]+\.'.
104                '[-!#$%&\'*+\\./0-9=?A-Z^_A-z{|}~]+$',$address));
105   if (($validate_email >= 2) && ($return == true)) {
106     $addressarray=address_decode($address,"garantiertungueltig");
107     $return=checkdnsrr($addressarray[0]["host"],"MX");
108     if (!$return) $return=checkdnsrr($addressarray[0]["host"],"A");
109   }
110   return($return);
111 }
112
113 /*
114  * decodes a block of 7bit-data in uuencoded format to it's original
115  * 8bit format.
116  * The headerline containing filename and permissions doesn't have to
117  * be included.
118  * 
119  * $data: The uuencoded data as a string
120  *
121  * returns the 8bit data as a string
122  *
123  * Note: this function is very slow and doesn't recognize incorrect code.
124  */
125 function uudecode_line($line) {
126   $data=substr($line,1);
127   $length=ord($line[0])-32;
128   $decoded="";
129   for ($i=0; $i<(strlen($data)>>2); $i++) {
130     $pack=substr($data,$i<<2,4);
131     $upack="";
132     $bitmaske=0;
133     for ($o=0; $o<4; $o++) {
134       $g=((ord($pack[3-$o])-32));
135       if ($g==64) $g=0;
136       $bitmaske=$bitmaske | ($g << (6*$o));
137     }
138     $schablone=255;
139     for ($o=0; $o<3; $o++) {
140       $c=($bitmaske & $schablone) >> ($o << 3);
141       $schablone=($schablone << 8);
142       $upack=chr($c).$upack;
143     }
144     $decoded.=$upack;
145   }
146   $decoded=substr($decoded,0,$length);
147   return $decoded;
148 }
149
150 /*
151  * decodes uuencoded Attachments.
152  *
153  * $data: the encoded data
154  *
155  * returns the decoded data
156  */
157 function uudecode($data) {
158   $d=explode("\n",$data);
159   $u="";
160   for ($i=0; $i<count($d)-1; $i++)
161     $u.=uudecode_line($d[$i]);
162   return $u;
163 }
164
165 /*
166  * returns the mimetype of an filename
167  *
168  * $name: the complete filename of a file
169  *
170  * returns a string containing the mimetype
171  */
172 function get_mimetype_by_filename($name) {
173   $ending=strtolower(strrchr($name,"."));
174   switch($ending) {
175     case ".jpg":
176     case ".jpeg":
177       $type="image/jpeg";
178       break;
179     case ".gif":
180       $type="image/gif";
181       break;
182     case ".png":
183       $type="image/png";
184       break;
185     case ".bmp":
186       $type="image/bmp";
187       break;
188     default:
189       $type="text/plain";
190   }
191   return $type;
192 }
193
194 /*
195  * Test, if the access to a group is allowed. This is true, if $testgroup is
196  * false or the groupname is in groups.txt
197  *
198  * $groupname: name of the group to be checked
199  *
200  * returns true, if access is allowed
201  */
202 function testGroup($groupname) {
203   global $testgroup,$file_groups;
204   if ($testgroup) {
205     $gf=fopen($file_groups,"r");
206     while (!feof($gf)) {
207       $read=trim(line_read($gf));
208       $pos=strpos($read," ");
209       if ($pos != false) {
210         if (substr($read,0,$pos)==trim($groupname)) return true;
211       } else {
212         if ($read == trim($groupname)) return true;
213       }
214     }
215     fclose($gf);
216     return false;
217   } else {
218     return true;
219   }
220 }
221
222 function testGroups($newsgroups) {
223   $groups=explode(",",$newsgroups);
224   $count=count($groups);
225   $return="";
226   $o=0;
227   for ($i=0; $i<$count; $i++) {
228     if (testgroup($groups[$i]) &&
229         (!function_exists("npreg_group_has_write_access") || 
230          npreg_group_has_write_access($groups[$i]))) {
231       if ($o>0) $return.=",";
232       $o++;
233       $return.=$groups[$i];
234     }
235   }
236   return($return);
237 }
238
239 /*
240  * read one line from the NNTP-server
241  */
242 function line_read(&$ns) {
243   if ($ns != false) {
244     $t=str_replace("\n","",str_replace("\r","",fgets($ns,1200)));
245     return $t;
246   }
247 }
248
249 /*
250  * Split an internet-address string into its parts. An address string could
251  * be for example:
252  * - user@host.domain (Realname)
253  * - "Realname" <user@host.domain>
254  * - user@host.domain
255  *
256  * The address will be split into user, host (incl. domain) and realname
257  *
258  * $adrstring: The string containing the address in internet format
259  * $defaulthost: The name of the host which should be returned if the
260  *               address-string doesn't contain a hostname.
261  *
262  * returns an hash containing the fields "mailbox", "host" and "personal"
263  */
264 function address_decode($adrstring,$defaulthost) {
265   $parsestring=trim($adrstring);
266   $len=strlen($parsestring);
267   $at_pos=strpos($parsestring,'@');     // find @
268   $ka_pos=strpos($parsestring,"(");     // find (
269   $kz_pos=strpos($parsestring,')');     // find )
270   $ha_pos=strpos($parsestring,'<');     // find <
271   $hz_pos=strpos($parsestring,'>');     // find >
272   $space_pos=strpos($parsestring,')');  // find ' '
273   $email="";
274   $mailbox="";
275   $host="";
276   $personal="";
277   if ($space_pos != false) {
278     if (($ka_pos != false) && ($kz_pos != false)) {
279       $personal=substr($parsestring,$ka_pos+1,$kz_pos-$ka_pos-1);
280       $email=trim(substr($parsestring,0,$ka_pos-1));
281     }
282   } else {
283     $email=$adrstring;
284   }
285   if (($ha_pos != false) && ($hz_pos != false)) {
286     $email=trim(substr($parsestring,$ha_pos+1,$hz_pos-$ha_pos-1));
287     $personal=substr($parsestring,0,$ha_pos-1);
288   }
289   if ($at_pos != false) {
290     $mailbox=substr($email,0,strpos($email,'@'));
291     $host=substr($email,strpos($email,'@')+1);
292   } else {
293     $mailbox=$email;
294     $host=$defaulthost;
295   }
296   $personal=trim($personal);
297   if (substr($personal,0,1) == '"') $personal=substr($personal,1);
298   if (substr($personal,strlen($personal)-1,1) == '"')
299     $personal=substr($personal,0,strlen($personal)-1);
300   $result["mailbox"]=trim($mailbox);
301   $result["host"]=trim($host);
302   if ($personal!="") $result["personal"]=$personal;
303   $complete[]=$result;
304   return ($complete);
305 }
306
307 /*
308  * Read the groupnames from groups.txt, and get additional informations
309  * of the groups from the newsserver
310  */
311 function groups_read($server,$port) {
312   global $gl_age,$file_groups,$spooldir,$cache_index;
313   // is there a cached version, and is it actual enough?
314   $cachefile=$spooldir.'/groups.dat';
315   if((file_exists($cachefile)) && (filemtime($cachefile)+$cache_index>time())) {
316     // cached file exists and is new enough. so lets read it out.
317     $file=fopen($cachefile,"r");
318     $data="";
319     while(!feof($file)) {
320       $data.=fgets($file,1000);
321     }
322     fclose($file);
323     $newsgroups=unserialize($data);
324   } else {
325     $ns=nntp_open($server,$port);
326     if ($ns == false) return false;
327     $gf=fopen($file_groups,"r");
328     // if we want to mark groups with new articles with colors, wie will later
329     // need the format of the overview
330     $overviewformat=thread_overview_read($ns);
331     while (!feof($gf)) {
332       $gruppe=new newsgroupType;
333       $tmp=trim(line_read($gf));
334       if(substr($tmp,0,1)==":") {
335         $gruppe->text=substr($tmp,1);
336         $newsgroups[]=$gruppe;  
337       } elseif(strlen(trim($tmp))>0) {
338         // is there a description in groups.txt?
339         $pos=strpos($tmp," ");
340         if ($pos != false) {
341           // yes.
342           $gruppe->name=substr($tmp,0,$pos);
343           $desc=substr($tmp,$pos);
344         } else {
345           // no, get it from the newsserver.
346           $gruppe->name=$tmp;
347           fputs($ns,"XGTITLE $gruppe->name\r\n");
348           $response=line_read($ns);
349           if (strcmp(substr($response,0,3),"282") == 0) {
350             $neu=line_read($ns);
351             do {
352               $response=$neu;
353               if ($neu != ".") $neu=line_read($ns);
354             } while ($neu != ".");
355             $desc=strrchr($response,"\t");
356             if (strcmp($response,".") == 0) {
357               $desc="-";
358             }
359           } else {
360             $desc=$response;
361           }
362           if (strcmp(substr($response,0,3),"500") == 0)
363             $desc="-";
364         }
365         if (strcmp($desc,"") == 0) $desc="-";
366         $gruppe->description=$desc;
367         fputs($ns,"GROUP ".$gruppe->name."\r\n"); 
368         $t=explode(" ",line_read($ns));
369         $gruppe->count=$t[1];
370         // mark group with new articles with colors
371         if($gl_age) {
372           fputs($ns,'XOVER '.$t[3]."\r\n");
373           $tmp=explode(" ",line_read($ns));
374           if($tmp[0]=="224") {
375             $tmp=line_read($ns);
376             if($tmp!=".") {
377               $head=thread_overview_interpret($tmp,$overviewformat,$gruppe->name);
378               $tmp=line_read($ns);
379               $gruppe->age=$head->date;
380             }
381           }
382         }
383         if ((strcmp(trim($gruppe->name),"") != 0) &&
384             (substr($gruppe->name,0,1) != "#"))
385           $newsgroups[]=$gruppe;
386       }
387     }
388     fclose($gf);
389     nntp_close($ns);
390     // write the data to the cachefile
391     $file=fopen($cachefile,"w");
392     fputs($file,serialize($newsgroups));
393     fclose($file);
394   }
395   return $newsgroups;
396 }
397
398 /*
399  * print the group names from an array to the webpage
400  */
401 function groups_show($gruppen) {
402   global $gl_age;
403   if ($gruppen == false) return;
404   global $file_thread,$text_groups;
405   $c = count($gruppen);
406   echo '<div class="np_index_groupblock">';
407   $acttype="keins";
408   for($i = 0 ; $i < $c ; $i++) {
409     $g = $gruppen[$i];
410     if(isset($g->text)) {
411       if($acttype!="text") {
412         $acttype="text";
413         if($i>0)
414           echo '</div>';
415         echo '<div class="np_index_grouphead">';
416       }
417       echo $g->text;
418     } else {
419       if($acttype!="group") {
420         $acttype="group";
421         if($i>0)
422           echo '</div>';
423         echo '<div class="np_index_groupblock">';
424       }
425       echo '<div class="np_index_group">';
426       echo '<a ';
427       if ((isset($frame_threadframeset)) && ($frame_threadframeset != ""))
428         echo 'target="'.$frame_threadframeset.'" ';
429       echo 'href="'.$file_thread.'?group='.urlencode($g->name).'">'.$g->name."</a>\n";
430       if($gl_age)
431         $datecolor=thread_format_date_color($g->age);
432       echo '<small>(';
433       if($datecolor!="")
434         echo '<font color="'.$datecolor.'">'.$g->count.'</font>';
435       else
436         echo $g->count;
437       echo ')</small>';
438       if($g->description!="-")
439         echo '<br><small>'.$g->description.'</small>';
440       echo '</div>';
441     }
442     echo "\n";
443     flush();
444   }
445   echo "</div></div>\n";
446 }
447
448 /*
449  * gets a list of aviable articles in the group $groupname
450  */
451 /*
452 function getArticleList(&$ns,$groupname) {
453   fputs($ns,"LISTGROUP $groupname \r\n");
454   $line=line_read($ns);
455   $line=line_read($ns);
456   while(strcmp($line,".") != 0) {
457     $articleList[] = trim($line);
458     $line=line_read($ns);
459   }
460   if (!isset($articleList)) $articleList="-";
461   return $articleList;
462 }
463 */
464
465 /*
466  * Decode quoted-printable or base64 encoded headerlines
467  *
468  * $value: The to be decoded line
469  *
470  * returns the decoded line
471  */
472 function headerDecode($value) {
473   if (eregi('=\?.*\?.\?.*\?=',$value)) { // is there anything encoded?
474     if (eregi('=\?.*\?Q\?.*\?=',$value)) {  // quoted-printable decoding
475
476       $charset=eregi_replace('(.*)=\?(.*)\?Q\?(.*)\?=(.*)','\2',$value);
477       $result1=eregi_replace('(.*)=\?.*\?Q\?(.*)\?=(.*)','\1',$value);
478       $result2=eregi_replace('(.*)=\?.*\?Q\?(.*)\?=(.*)','\2',$value);
479       $result3=eregi_replace('(.*)=\?.*\?Q\?(.*)\?=(.*)','\3',$value);
480       $result2=str_replace("_"," ",quoted_printable_decode($result2));
481       $newvalue=$result1.recode_charset($result2,$charset).$result3;
482     }
483     if (eregi('=\?.*\?B\?.*\?=',$value)) {  // base64 decoding
484       $result1=eregi_replace('(.*)=\?.*\?B\?(.*)\?=(.*)','\1',$value);
485       $result2=eregi_replace('(.*)=\?.*\?B\?(.*)\?=(.*)','\2',$value);
486       $result3=eregi_replace('(.*)=\?.*\?B\?(.*)\?=(.*)','\3',$value);
487       $result2=base64_decode($result2);
488       $newvalue=$result1.$result2.$result3;
489     }
490     if (!isset($newvalue)) // nothing of the above, must be an unknown encoding...
491       $newvalue=$value;
492     else
493       $newvalue=headerDecode($newvalue);  // maybe there are more encoded
494     return($newvalue);                    // parts
495   } else {   // there wasn't anything encoded, return the original string
496     return($value);
497   }
498 }
499
500 /*
501  * calculates an Unix timestamp out of a Date-Header in an article
502  *
503  * $value: Value of the Date: header
504  *
505  * returns an Unix timestamp
506  */
507 function getTimestamp($value) {
508   global $timezone;
509   $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);
510   $value=str_replace("  "," ",$value);
511   $d=split(" ",$value,6);
512   if (strcmp(substr($d[0],strlen($d[0])-1,1),",") == 0) {
513     $date[0]=$d[1];  // day
514     $date[1]=$d[2];  // month
515     $date[2]=$d[3];  // year
516     $date[3]=$d[4];  // hours:minutes:seconds
517     $gmt=$d[5];      // timezone
518   } else {
519     $date[0]=$d[0];  // day
520     $date[1]=$d[1];  // month
521     $date[2]=$d[2];  // year
522     $date[3]=$d[3];  // hours:minutes:seconds
523     $gmt=$d[4];      // timezone
524   }
525   $time=split(":",$date[3]);
526   // timezone handling
527   $msgtimezone=0;
528   if ($gmt[0]=='-') {
529     $msgtimezone=-substr($gmt,1,2);
530     $msgminzone=-substr($gmt,3,2);
531   } else if ($gmt[0]=='+') {
532     $msgtimezone=+substr($gmt,1,2);
533     $msgminzone=+substr($gmt,3,2);
534   }
535   $time[0]=$time[0]-$msgtimezone+$timezone;
536   $time[1]=$time[1]-$msgminzone+$minzone;
537   $timestamp=mktime($time[0],$time[1],$time[2],$months[$date[1]],$date[0],$date[2]);
538   return $timestamp;
539 }
540
541 function parse_header($hdr,$number="") {
542   for ($i=count($hdr)-1; $i>0; $i--)
543     if (preg_match("/^(\x09|\x20)/",$hdr[$i]))
544       $hdr[$i-1]=$hdr[$i-1]." ".ltrim($hdr[$i]);
545   $header = new headerType;
546   $header->isAnswer=false;
547   for ($count=0;$count<count($hdr);$count++) {
548     $variable=substr($hdr[$count],0,strpos($hdr[$count]," "));
549     $value=trim(substr($hdr[$count],strpos($hdr[$count]," ")+1));
550       switch (strtolower($variable)) {
551         case "from:": 
552           $fromline=address_decode(headerDecode($value),"nirgendwo");
553           if (!isset($fromline[0]["host"])) $fromline[0]["host"]="";
554           $header->from=$fromline[0]["mailbox"]."@".$fromline[0]["host"];
555           $header->username=$fromline[0]["mailbox"];
556           if (!isset($fromline[0]["personal"])) {
557             $header->name="";
558           } else {
559             $header->name=$fromline[0]["personal"];
560           }
561           break;
562         case "message-id:":
563           $header->id=$value;
564           break;
565         case "subject:":
566           $header->subject=headerDecode($value);
567           break;
568         case "newsgroups:":
569           $header->newsgroups=$value;
570           break;
571         case "organization:":
572           $header->organization=headerDecode($value);
573           break;
574         case "content-transfer-encoding:":
575           $header->content_transfer_encoding=trim(strtolower($value));
576           break; 
577         case "content-type:":
578           $header->content_type=array();
579           $subheader=split(";",$value);
580           $header->content_type[0]=strtolower(trim($subheader[0]));
581           for ($i=1; $i<count($subheader); $i++) {
582             $gleichpos=strpos($subheader[$i],"=");
583             if ($gleichpos) {
584               $subvariable=trim(substr($subheader[$i],0,$gleichpos));
585               $subvalue=trim(substr($subheader[$i],$gleichpos+1));
586               if (($subvalue[0]=='"') &&
587                   ($subvalue[strlen($subvalue)-1]=='"'))
588                 $subvalue=substr($subvalue,1,strlen($subvalue)-2);
589               switch($subvariable) {
590                 case "charset":
591                   $header->content_type_charset=array(strtolower($subvalue));
592                   break;
593                 case "name":
594                   $header->content_type_name=array($subvalue);
595                   break;
596                 case "boundary":
597                   $header->content_type_boundary=$subvalue;
598                   break;
599                 case "format":
600                   $header->content_type_format=array($subvalue);
601               }
602             }
603           }
604           break;
605         case "references:":
606           $ref=trim($value);
607           while (strpos($ref,"> <") != false) {
608             $header->references[]=substr($ref,0,strpos($ref," "));
609             $ref=substr($ref,strpos($ref,"> <")+2);
610           }
611           $header->references[]=trim($ref);
612           break;
613         case "date:":
614           $header->date=getTimestamp(trim($value));
615           break;
616         case "followup-to:":
617           $header->followup=trim($value);
618           break;
619         case "x-newsreader:":
620         case "x-mailer:":
621         case "user-agent:":
622           $header->user_agent=trim($value);
623           break;
624         case "x-face:": // not ready
625 //          echo "<p>-".base64_decode($value)."-</p>";
626           break;
627         case "x-no-archive:":
628           $header->xnoarchive=strtolower(trim($value));
629       }
630   }
631   if (!isset($header->content_type[0]))
632     $header->content_type[0]="text/plain";
633   if (!isset($header->content_transfer_encoding))
634     $header->content_transfer_encoding="8bit";
635   if ($number != "") $header->number=$number;
636   return $header;
637 }
638
639 /*
640  * convert the charset of a text
641  */
642 function recode_charset($text,$source=false,$dest=false) {
643   global $iconv_enable,$www_charset;
644   if($dest==false)
645     $dest=$www_charset;
646   if(($iconv_enable) && ($source!=false)) {
647     $return=iconv($source,
648                  $dest."//TRANSLIT",$text);
649     if($return!="")
650       return $return;
651     else
652       return $text;
653   } else {
654     return $text;
655   }
656 }
657
658 function decode_body($body,$encoding) {
659   $bodyzeile="";
660   switch ($encoding) {
661     case "base64":
662       $body=base64_decode($body);
663       break;
664     case "quoted-printable":
665       $body=Quoted_printable_decode($body);
666       $body=str_replace("=\n","",$body);
667 //    default:
668 //      $body=str_replace("\n..\n","\n.\n",$body);
669   }
670
671   return $body;
672 }
673
674 /*
675  * makes URLs clickable
676  *
677  * $text: A text-line probably containing links.
678  *
679  * the function returns the text-line with HTML-Links to the links or
680  * email-adresses.
681  */
682 function html_parse($text) {
683   global $frame_externallink;
684   if ((isset($frame_externallink)) && ($frame_externallink != "")) { 
685     $target=' TARGET="'.$frame_externallink.'" ';
686   } else {
687     $target=' ';
688   }
689   // regular expressions that will be applied to every word in the text
690   $regexp_replace=array(
691     'http://((\.*([-a-z0-9_/~@?=%#;+]|&amp;)+)+)' =>
692       '<a'.$target.'href="http://\1">http://\1</a>',
693     '(www\.[-a-z]+\.(de|pl|cz|sk|tk|tv|cc|cx|biz|us|uk|info|int|eu|dk|org|net|at|ch|com))' =>
694       '<a'.$target.'href="http://\1">\1</a>',
695     'https://([-a-z0-9_./~@?=%#&;\n]+)' =>
696       '<a'.$target.'href="https://\1">https://\1</a>',
697     'gopher://([-a-z0-9_./~@?=%\n]+)' =>
698       '<a'.$target.'href="gopher://\1">gopher://\1</a>',
699     'news://([-a-z0-9_./~@?=%\n]+)' =>
700       '<a'.$target.'href="news://\1">news://\1</a>',
701     'ftp://([-a-z0-9_./~@?=%\n]+)' =>
702       '<a'.$target.'href="ftp://\1">ftp://\1</a>',
703     //'([-a-z0-9_./n]+)@([-a-z0-9_.]+)' =>
704     //  $_SESSION["loggedin"]!==true ? '(e-Mail)' :
705     //  '<a href="mailto:\1@\2">\1@\2</a>'
706   );
707   $ntext="";
708   // split every line into it's words
709   $words=explode(" ",$text);
710   $n=count($words);
711   for($i=0; $i<$n; $i++) {
712     $word=$words[$i];
713     // test, if we need the slow walk through all the regular expressions
714     if(eregi('www|\:|@',$word)) {
715       // apply the regular expressions to the word until a matching 
716       // expression is found
717       foreach ($regexp_replace as $key => $value) {
718         $nword=eregi_replace($key,$value,$word);
719         if($nword!=$word) {
720           $word=$nword;
721           break;
722         }
723       }
724     }
725     // add the spaces between the words
726     if($i>0)
727       $ntext.=" ";
728     $ntext.=$word;
729   }
730   return($ntext);
731 }
732
733
734 /*
735  * read the header of an article in plaintext into an array
736  * $articleNumber can be the number of an article or its message-id.
737  */
738 function readPlainHeader(&$ns,$group,$articleNumber) {
739   fputs($ns,"GROUP $group\r\n");
740   $line=line_read($ns);
741   fputs($ns,"HEAD $articleNumber\r\n");
742   $line=line_read($ns);
743   if (substr($line,0,3) != "221") {
744     echo $text_error["article_not_found"];
745     $header=false;
746   } else {
747     $line=line_read($ns);
748     $body="";
749     while(strcmp(trim($line),".") != 0) {
750       $body .= $line."\n";
751       $line=line_read($ns);
752     }
753     return split("\n",str_replace("\r\n","\n",$body));
754   }
755 }
756
757 /*
758  * cancel an article on the newsserver
759  *
760  * DO NOT USE THIS FUNCTION, IF YOU DON'T KNOW WHAT YOU ARE DOING!
761  *
762  * $ns: The handler of the NNTP-Connection
763  * $group: The group of the article
764  * $id: the Number of the article inside the group or the message-id
765  */
766 function message_cancel($subject,$from,$newsgroups,$ref,$body,$id) {
767   global $server,$port,$send_poster_host,$organization,$text_error;
768   global $file_footer,$www_charset;
769   flush();
770   $ns=nntp_open($server,$port);
771   if ($ns != false) {
772     fputs($ns,"POST\r\n");
773     $weg=line_read($ns);
774     fputs($ns,'Subject: '.quoted_printable_encode($subject)."\r\n");
775     fputs($ns,'From: '.$from."\r\n");
776     fputs($ns,'Newsgroups: '.$newsgroups."\r\n");
777     fputs($ns,"Mime-Version: 1.0\r\n");
778     fputs($ns,"Content-Type: text/plain; charset=".$www_charset."\r\n");
779     fputs($ns,"Content-Transfer-Encoding: 8bit\r\n");
780     if ($send_poster_host)
781       fputs($ns,'X-HTTP-Posting-Host: '.gethostbyaddr(getenv("REMOTE_ADDR"))."\r\n");
782     if ($ref!=false) fputs($ns,'References: '.$ref."\r\n");
783     if (isset($organization))
784       fputs($ns,'Organization: '.quoted_printable_encode($organization)."\r\n");
785     fputs($ns,"Control: cancel ".$id."\r\n");
786     if ((isset($file_footer)) && ($file_footer!="")) {
787       $footerfile=fopen($file_footer,"r");
788       $body.="\n".fread($footerfile,filesize($file_footer));
789       fclose($footerfile);
790     }
791     $body=str_replace("\n.\r","\n..\r",$body);
792     $body=str_replace("\r",'',$body);
793     $b=split("\n",$body);
794     $body="";
795     for ($i=0; $i<count($b); $i++) {
796       if ((strpos(substr($b[$i],0,strpos($b[$i]," ")),">") != false ) | (strcmp(substr($b[$i],0,1),">") == 0)) {
797         $body .= textwrap(stripSlashes($b[$i]),78,"\r\n")."\r\n";
798       } else {
799         $body .= textwrap(stripSlashes($b[$i]),74,"\r\n")."\r\n";
800       }
801     }
802     fputs($ns,"\r\n".$body."\r\n.\r\n");
803     $message=line_read($ns);
804     nntp_close($ns);
805   } else {
806     $message=$text_error["post_failed"];
807   }
808   return $message;
809 }
810
811 ?>