Fix file permission brain damage.
[mspang/www.git] / newsgroup / lib / post.inc.php
1 <?
2 /*
3  *  NewsPortal: Functions for posting articles to a newsgroup
4  *
5  *  Copyright (C) 2002-2004 Florian Amrhein
6  *  E-Mail: newsportal@florian-amrhein.de
7  *  Web: http://florian-amrhein.de
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  */
23
24 /*
25  * Encode lines with 8bit-characters to quote-printable
26  *
27  * $line: the to be encoded line
28  *
29  * the function returns a sting containing the quoted-printable encoded
30  * $line
31  */
32 function quoted_printable_encode($line) {
33   global $www_charset;
34   $qp_table=array(
35      '=00', '=01', '=02', '=03', '=04', '=05',
36      '=06', '=07', '=08', '=09', '=0A', '=0B',
37      '=0C', '=0D', '=0E', '=0F', '=10', '=11',
38      '=12', '=13', '=14', '=15', '=16', '=17',
39      '=18', '=19', '=1A', '=1B', '=1C', '=1D',
40      '=1E', '=1F', '_',   '!',   '"',   '#',
41      '$',   '%',   '&',   "'",   '(',   ')',
42      '*',   '+',   ',',   '-',   '.',   '/',
43      '0',   '1',   '2',   '3',   '4',   '5',
44      '6',   '7',   '8',   '9',   ':',   ';',
45      '<',   '=3D', '>',   '=3F', '@',   'A',
46      'B',   'C',   'D',   'E',   'F',   'G',
47      'H',   'I',   'J',   'K',   'L',   'M',
48      'N',   'O',   'P',   'Q',   'R',   'S',
49      'T',   'U',   'V',   'W',   'X',   'Y',
50      'Z',   '[',   '\\',  ']',   '^',   '=5F',
51      '',    'a',   'b',   'c',   'd',   'e',
52      'f',   'g',   'h',   'i',   'j',   'k',
53      'l',   'm',   'n',   'o',   'p',   'q',
54      'r',   's',   't',   'u',   'v',   'w',
55      'x',   'y',   'z',   '{',   '|',   '}',
56      '~',   '=7F', '=80', '=81', '=82', '=83',
57      '=84', '=85', '=86', '=87', '=88', '=89',
58      '=8A', '=8B', '=8C', '=8D', '=8E', '=8F',
59      '=90', '=91', '=92', '=93', '=94', '=95',
60      '=96', '=97', '=98', '=99', '=9A', '=9B',
61      '=9C', '=9D', '=9E', '=9F', '=A0', '=A1',
62      '=A2', '=A3', '=A4', '=A5', '=A6', '=A7',
63      '=A8', '=A9', '=AA', '=AB', '=AC', '=AD',
64      '=AE', '=AF', '=B0', '=B1', '=B2', '=B3',
65      '=B4', '=B5', '=B6', '=B7', '=B8', '=B9',
66      '=BA', '=BB', '=BC', '=BD', '=BE', '=BF',
67      '=C0', '=C1', '=C2', '=C3', '=C4', '=C5',
68      '=C6', '=C7', '=C8', '=C9', '=CA', '=CB',
69      '=CC', '=CD', '=CE', '=CF', '=D0', '=D1',
70      '=D2', '=D3', '=D4', '=D5', '=D6', '=D7',
71      '=D8', '=D9', '=DA', '=DB', '=DC', '=DD',
72      '=DE', '=DF', '=E0', '=E1', '=E2', '=E3',
73      '=E4', '=E5', '=E6', '=E7', '=E8', '=E9',
74      '=EA', '=EB', '=EC', '=ED', '=EE', '=EF',
75      '=F0', '=F1', '=F2', '=F3', '=F4', '=F5',
76      '=F6', '=F7', '=F8', '=F9', '=FA', '=FB',
77      '=FC', '=FD', '=FE', '=FF');
78   // are there "forbidden" characters in the string?
79   for($i=0; $i<strlen($line) && ord($line[$i])<=127 ; $i++);
80   if ($i<strlen($line)) { // yes, there are. So lets encode them!
81     $from=$i;
82     for($to=strlen($line)-1; ord($line[$to])<=127; $to--);
83     // lets scan for the start and the end of the to be encoded _words_
84     for(;$from>0 && $line[$from] != ' '; $from--);
85     if($from>0) $from++;
86     for(;$to<strlen($line) && $line[$to] != ' '; $to++);
87     // split the string into the to be encoded middle and the rest
88     $begin=substr($line,0,$from);
89     $middle=substr($line,$from,$to-$from);
90     $end=substr($line,$to);
91     // ok, now lets encode $middle...
92     $newmiddle="";
93     for($i=0; $i<strlen($middle); $i++)
94       $newmiddle .= $qp_table[ord($middle[$i])];
95     // now we glue the parts together...
96     $line=$begin.'=?'.$www_charset.'?Q?'.$newmiddle.'?='.$end;
97   }
98   return $line;
99 }
100
101 /*
102  * generate a message-id for posting.
103  * $identity: a string containing informations about the article, to
104  *     make a md5-hash out of it.
105  *
106  * returns: a complete message-id
107  */
108 function generate_msgid($identity) {
109   global $msgid_generate,$msgid_fqdn;
110   switch($msgid_generate) {
111     case "no":
112       // no, we don't want to generate a message-id.
113       return false;
114       break;
115     case "md5":
116       return '<'.md5($identity).'$1@'.$msgid_fqdn.'>';
117       break;
118     default:
119       return false;
120       break;
121   }
122 }
123
124 /*
125  * Post an article to a newsgroup
126  *
127  * $subject: The Subject of the article
128  * $from: The authors name and email of the article
129  * $newsgroups: The groups to post to
130  * $ref: The references of the article
131  * $body: The article itself
132  */
133 function message_post($subject,$from,$newsgroups,$ref,$body) {
134   global $server,$port,$send_poster_host,$organization,$text_error;
135   global $file_footer,$www_charset,$spooldir;
136   global $msgid_generate,$msgid_fqdn;
137   flush();
138   $ns=nntp_open($server,$port);
139   if ($ns != false) {
140     fputs($ns,"POST\r\n");
141     $weg=line_read($ns);
142     fputs($ns,'Subject: '.quoted_printable_encode($subject)."\r\n");
143     fputs($ns,'From: '.$from."\r\n");
144     fputs($ns,'Newsgroups: '.$newsgroups."\r\n");
145     fputs($ns,"Mime-Version: 1.0\r\n");
146     fputs($ns,"Content-Type: text/plain; charset=".$www_charset."; format=flowed\r\n");
147     fputs($ns,"Content-Transfer-Encoding: 8bit\r\n");
148     fputs($ns,"User-Agent: NewsPortal/0.36 (http://florian-amrhein.de/newsportal)\r\n");
149     if ($send_poster_host)
150       @fputs($ns,'X-HTTP-Posting-Host: '.gethostbyaddr(getenv("REMOTE_ADDR"))."\r\n");
151     if (($ref!=false) && (count($ref)>0)) {
152       // strip references
153       if(strlen(implode(" ",$ref))>900) {
154         $ref_first=array_shift($ref);
155         do {
156           $ref=array_slice($ref,1);
157         } while(strlen(implode(" ",$ref))>800);
158         array_unshift($ref,$ref_first);
159       }
160       fputs($ns,'References: '.implode(" ",$ref)."\r\n");
161     }
162     if (isset($organization))
163       fputs($ns,'Organization: '.quoted_printable_encode($organization)."\r\n");
164     if ((isset($file_footer)) && ($file_footer!="")) {
165       $footerfile=fopen($file_footer,"r");
166       $body.="\n".fread($footerfile,filesize($file_footer));
167       fclose($footerfile);
168     }
169     if($msgid=generate_msgid(
170                  $subject.",".$from.",".$newsgroups.",".$ref.",".$body))
171       fputs($ns,'Message-ID: '.$msgid."\r\n");
172     $body=str_replace("\n.\r","\n..\r",$body);
173     $body=str_replace("\r",'',$body);
174     $b=split("\n",$body);
175     $body="";
176     for ($i=0; $i<count($b); $i++) {
177       if ((strpos(substr($b[$i],0,strpos($b[$i]," ")),">") != false) | (strcmp(substr($b[$i],0,1),">") == 0)) {
178         $body .= textwrap(stripSlashes($b[$i]),78," \r\n")."\r\n";
179       } else {
180         $body .= textwrap(stripSlashes($b[$i]),74," \r\n")."\r\n";
181       }
182     }
183     fputs($ns,"\r\n".$body."\r\n.\r\n");
184     $message=line_read($ns);
185     nntp_close($ns);
186   } else {
187     $message=$text_error["post_failed"];
188   }
189   // let thread.php ignore the cache for this group, so this new
190   // article will be visible instantly
191   $cachefile=$spooldir.'/'.$newsgroups.'-cache.txt';
192   @unlink($cachefile);
193   return $message;
194 }
195 ?>