Commit | Line | Data |
---|---|---|
1eed39ee | 1 | <?php |
1eed39ee | 2 | /******************************************************************************** |
3 | * include/posts.inc.php : class for posts | |
4 | * ----------------------- | |
5 | * | |
6 | * This file is part of the banana distribution | |
7 | * Copyright: See COPYING files that comes with this distribution | |
8 | ********************************************************************************/ | |
9 | ||
10 | /** class for posts | |
11 | */ | |
12 | ||
d4c19591 | 13 | class BananaPost |
14 | { | |
b9ea5b30 | 15 | var $id; |
e785d91c | 16 | /** headers */ |
17 | var $headers; | |
18 | /** body */ | |
19 | var $body; | |
8f6f50fb | 20 | /** formating */ |
21 | var $messages; | |
d43ebde4 | 22 | /** attachment */ |
23 | var $pj; | |
01681efd | 24 | /** poster name */ |
25 | var $name; | |
1eed39ee | 26 | |
e785d91c | 27 | /** constructor |
e785d91c | 28 | * @param $_id STRING MSGNUM or MSGID (a group should be selected in this case) |
29 | */ | |
2dbc0167 | 30 | function BananaPost($_id) |
d4c19591 | 31 | { |
2dbc0167 | 32 | global $banana; |
8f6f50fb | 33 | $this->id = $_id; |
34 | $this->pj = array(); | |
35 | $this->messages = array(); | |
2dbc0167 | 36 | $this->_header(); |
01681efd | 37 | |
8d99c683 | 38 | if ($body = $banana->nntp->body($_id)) { |
39 | $this->body = join("\n", $body); | |
40 | } else { | |
41 | return ($this = null); | |
42 | } | |
01681efd | 43 | |
44 | if (isset($this->headers['content-transfer-encoding'])) { | |
45 | if (preg_match("/base64/", $this->headers['content-transfer-encoding'])) { | |
46 | $this->body = base64_decode($this->body); | |
47 | } elseif (preg_match("/quoted-printable/", $this->headers['content-transfer-encoding'])) { | |
48 | $this->body = quoted_printable_decode($this->body); | |
49 | } | |
e785d91c | 50 | } |
01681efd | 51 | |
d43ebde4 | 52 | if (preg_match("@multipart/([^;]+);@", $this->headers['content-type'], $mpart_type)) { |
53 | preg_match("/boundary=\"?([^ \"]+)\"?/", $this->headers['content-type'], $mpart_boundary); | |
d38804c3 | 54 | $this->_split_multipart($mpart_type[1], $mpart_boundary[1]); |
d43ebde4 | 55 | } |
56 | ||
1248ebac | 57 | if (preg_match('!charset=([^;]*)\s*(;|$)!', $this->headers['content-type'], $matches)) { |
25466d0e | 58 | $this->body = iconv($matches[1], 'utf-8', $this->body); |
c42efe2f PHM |
59 | } else { |
60 | $this->body = utf8_encode($this->body); | |
e785d91c | 61 | } |
1eed39ee | 62 | } |
1eed39ee | 63 | |
d43ebde4 | 64 | /** split multipart messages |
65 | * @param $type STRING multipart type description | |
66 | * @param $boundary STRING multipart boundary identification string | |
67 | */ | |
d38804c3 | 68 | function _split_multipart($type, $boundary) |
d43ebde4 | 69 | { |
d43ebde4 | 70 | $parts = preg_split("/\n--$boundary(--|\n)/", $this->body); |
71 | foreach ($parts as $part) { | |
d38804c3 | 72 | $part = $this->_get_part($part); |
d43ebde4 | 73 | $local_header = $part['headers']; |
74 | $local_body = $part['body']; | |
75 | if (isset($local_header['content-disposition']) && preg_match("/attachment/", $local_header['content-disposition'])) { | |
d38804c3 | 76 | $this->_add_attachment($part); |
8f6f50fb | 77 | } else if (isset($local_header['content-type']) && preg_match("@text/([^;]+);@", $local_header['content-type'], $format)) { |
78 | array_push($this->messages, $part); | |
d38804c3 | 79 | } |
8f6f50fb | 80 | } |
81 | if (count($this->messages) > 0) { | |
82 | $this->set_body_to_part(0); | |
d43ebde4 | 83 | } |
84 | } | |
85 | ||
86 | /** extract new headers from the part | |
87 | * @param $part STRING part of a multipart message | |
88 | */ | |
d38804c3 | 89 | function _get_part($part) |
8f6f50fb | 90 | { |
d43ebde4 | 91 | global $banana; |
92 | ||
93 | $lines = split("\n", $part); | |
94 | while (count($lines)) { | |
95 | $line = array_shift($lines); | |
96 | if ($line != "") { | |
97 | list($hdr, $val) = split(":[ \t\r]*", $line, 2); | |
98 | $hdr = strtolower($hdr); | |
99 | if (in_array($hdr, $banana->parse_hdr)) { | |
100 | $local_headers[$hdr] = $val; | |
101 | } | |
102 | } else { | |
103 | break; | |
104 | } | |
105 | } | |
d43ebde4 | 106 | return Array('headers' => $local_headers, 'body' => join("\n", $lines)); |
107 | } | |
108 | ||
8f6f50fb | 109 | /** add an attachment |
110 | */ | |
d38804c3 | 111 | function _add_attachment($part) |
8f6f50fb | 112 | { |
d43ebde4 | 113 | $local_header = $part['headers']; |
114 | $local_body = $part['body']; | |
115 | ||
116 | if (!isset($local_header['content-transfer-encoding'])) { | |
8f6f50fb | 117 | return false; |
d43ebde4 | 118 | } |
119 | ||
120 | if (isset($local_header['content-disposition'])) { | |
121 | if (preg_match("/attachment/", $local_header['content-disposition'])) { | |
122 | preg_match("/filename=\"?([^\"]+)\"?/", $local_header['content-disposition'], $filename); | |
123 | $filename = $filename[1]; | |
124 | } | |
125 | } | |
126 | if (!isset($filename)) { | |
127 | $filename = "attachment".count($pj); | |
128 | } | |
129 | ||
130 | if (isset($local_header['content-type'])) { | |
131 | if (preg_match("/^\\s*([^ ;]+);/", $local_header['content-type'], $mimetype)) { | |
132 | $mimetype = $mimetype[1]; | |
133 | } | |
134 | } | |
135 | if (!isset($mimetype)) { | |
8f6f50fb | 136 | return false; |
d43ebde4 | 137 | } |
138 | ||
139 | array_push($this->pj, Array('MIME' => $mimetype, | |
140 | 'filename' => $filename, | |
141 | 'encoding' => strtolower($local_header['content-transfer-encoding']), | |
142 | 'data' => $local_body)); | |
8f6f50fb | 143 | return true; |
d43ebde4 | 144 | } |
145 | ||
d38804c3 | 146 | /** return body in plain text (useful for messages without a text/plain part) |
147 | */ | |
148 | function get_body() | |
149 | { | |
150 | preg_match("@text/([^;]+);@", $this->headers['content-type'], $format); | |
151 | if ($format[1] == 'plain') { | |
152 | return $this->body; | |
153 | } | |
154 | $res = preg_replace("@<br[^>]>@", "@@@#@", $this->body); | |
155 | $res = trim(html_entity_decode(strip_tags($res))); | |
156 | $res = str_replace("@@@#@", "\n", $res); | |
157 | if (!is_utf8($res)) { | |
158 | $res = utf8_encode($res); | |
159 | } | |
160 | return $res; | |
161 | } | |
162 | ||
d43ebde4 | 163 | /** decode an attachment |
164 | * @param pjid INT id of the attachment to decode | |
165 | * @param action BOOL action to execute : true=view, false=download | |
166 | */ | |
8f6f50fb | 167 | function get_attachment($pjid, $action = false) |
168 | { | |
d43ebde4 | 169 | if ($pjid >= count($this->pj)) { |
170 | return false; | |
171 | } else { | |
172 | $file = $this->pj[$pjid]; | |
d38804c3 | 173 | header('Content-Type: '.$file['MIME'].'; name="'.$file['filename'].'"'); |
d43ebde4 | 174 | if (!$action) { |
175 | header('Content-Disposition: attachment; filename="'.$file['filename'].'"'); | |
d38804c3 | 176 | } else { |
177 | header('Content-Disposition: inline; filename="'.$file['filename'].'"'); | |
178 | } | |
d43ebde4 | 179 | if ($file['encoding'] == 'base64') { |
180 | echo base64_decode($file['data']); | |
181 | } else { | |
182 | header('Content-Transfer-Encoding: '.$file['encoding']); | |
183 | echo $file['data']; | |
184 | } | |
185 | return true; | |
186 | } | |
187 | } | |
188 | ||
8f6f50fb | 189 | /** set body to represent the given part |
190 | * @param partid INT index of the part in messages | |
191 | */ | |
192 | function set_body_to_part($partid) | |
193 | { | |
194 | global $banana; | |
195 | ||
196 | if (count($this->messages) == 0) { | |
197 | return false; | |
198 | } | |
199 | ||
200 | $local_header = $this->messages[$partid]['headers']; | |
201 | $this->body = $this->messages[$partid]['body']; | |
202 | foreach ($banana->parse_hdr as $hdr) { | |
203 | if (isset($local_header[$hdr])) { | |
204 | $this->headers[$hdr] = $local_header[$hdr]; | |
205 | } | |
206 | } | |
207 | return true; | |
208 | } | |
209 | ||
2dbc0167 | 210 | function _header() |
01681efd | 211 | { |
2dbc0167 | 212 | global $banana; |
b9ea5b30 | 213 | $hdrs = $banana->nntp->head($this->id); |
e785d91c | 214 | if (!$hdrs) { |
215 | $this = null; | |
216 | return false; | |
217 | } | |
01681efd | 218 | |
e785d91c | 219 | // parse headers |
220 | foreach ($hdrs as $line) { | |
221 | if (preg_match("/^[\t\r ]+/", $line)) { | |
01681efd | 222 | $line = ($hdr=="X-Face"?"":" ").ltrim($line); |
2dbc0167 | 223 | if (in_array($hdr, $banana->parse_hdr)) { |
01681efd | 224 | $this->headers[$hdr] .= $line; |
e785d91c | 225 | } |
226 | } else { | |
227 | list($hdr, $val) = split(":[ \t\r]*", $line, 2); | |
01681efd | 228 | $hdr = strtolower($hdr); |
2dbc0167 | 229 | if (in_array($hdr, $banana->parse_hdr)) { |
01681efd | 230 | $this->headers[$hdr] = $val; |
e785d91c | 231 | } |
e785d91c | 232 | } |
233 | } | |
234 | // decode headers | |
2dbc0167 | 235 | foreach ($banana->hdecode as $hdr) { |
01681efd | 236 | if (isset($this->headers[$hdr])) { |
237 | $this->headers[$hdr] = headerDecode($this->headers[$hdr]); | |
e785d91c | 238 | } |
239 | } | |
01681efd | 240 | |
241 | $this->name = $this->headers['from']; | |
242 | $this->name = preg_replace('/<[^ ]*>/', '', $this->name); | |
243 | $this->name = trim($this->name); | |
1eed39ee | 244 | } |
b9ea5b30 | 245 | |
65d96b1f | 246 | function checkcancel() |
247 | { | |
b9ea5b30 | 248 | if (function_exists('hook_checkcancel')) { |
249 | return hook_checkcancel($this->headers); | |
250 | } | |
251 | return ($this->headers['from'] == $_SESSION['name']." <".$_SESSION['mail'].">"); | |
252 | } | |
253 | ||
8f6f50fb | 254 | /** convert message to html |
255 | * @param partid INT id of the multipart message that must be displaid | |
256 | */ | |
257 | function to_html($partid = 0) | |
65d96b1f | 258 | { |
259 | global $banana; | |
260 | ||
8f6f50fb | 261 | if ($partid != 0) { |
262 | $this->set_body_to_part($partid); | |
263 | } | |
264 | ||
65d96b1f | 265 | $res = '<table class="bicol banana_msg" cellpadding="0" cellspacing="0">'; |
266 | $res .= '<tr><th colspan="2">'._b_('En-têtes').'</th></tr>'; | |
267 | ||
268 | foreach ($banana->show_hdr as $hdr) { | |
269 | if (isset($this->headers[$hdr])) { | |
270 | $res2 = formatdisplayheader($hdr, $this->headers[$hdr]); | |
271 | if ($res2) { | |
272 | $res .= '<tr><td class="hdr">'.header_translate($hdr)."</td><td class='val'>$res2</td></tr>\n"; | |
273 | } | |
274 | } | |
275 | } | |
276 | ||
8f6f50fb | 277 | $res .= '<tr><th colspan="2">'._b_('Corps'); |
278 | if (count($this->messages) > 1) { | |
279 | for ($i = 0 ; $i < count($this->messages) ; $i++) { | |
280 | if ($i == 0) { | |
281 | $res .= ' : '; | |
282 | } else { | |
283 | $res .= ' . '; | |
284 | } | |
285 | preg_match("@text/([^;]+);@", $this->messages[$i]['headers']['content-type'], $format); | |
286 | $format = textFormat_translate($format[1]); | |
287 | if ($i != $partid) { | |
288 | $res .= '<a href="?group='.$banana->state['group'].'&artid='.$this->id.'&part='.$i.'">'.$format.'</a>'; | |
289 | } else { | |
290 | $res .= $format; | |
291 | } | |
292 | } | |
293 | } | |
294 | $res .= '</th></tr>'; | |
295 | ||
296 | preg_match("@text/([^;]+);@", $this->headers['content-type'], $format); | |
297 | $format = $format[1]; | |
298 | $res .= '<tr><td colspan="2">'; | |
299 | if ($format == 'html') { | |
300 | $res .= formatbody($this->body, $format); | |
301 | } else { | |
302 | $res .= '<pre>'.formatbody($this->body).'</pre>'; | |
303 | } | |
304 | $res .= '</td></tr>'; | |
d43ebde4 | 305 | |
306 | if (count($this->pj) > 0) { | |
307 | $res .= '<tr><th colspan="2">'._b_('Pièces jointes').'</th></tr>'; | |
308 | $res .= '<tr><td colspan="2">'; | |
309 | $i = 0; | |
310 | foreach ($this->pj as $file) { | |
311 | $res .= $file['filename'].' ('.$file['MIME'].') : '; | |
312 | $res .= '<a href="pj.php?group='.$banana->state['group'].'&artid='.$this->id.'&pj='.$i.'">télécharger</a>'; | |
51e89e48 | 313 | $res .= ' . <a href="pj.php?group='.$banana->state['group'].'&artid='.$this->id.'&pj='.$i.'&action=view" target="_blank">aperçu</a>'; |
d43ebde4 | 314 | $res .= '<br/>'; |
315 | $i++; | |
316 | } | |
317 | $res .= '</td></tr>'; | |
318 | } | |
65d96b1f | 319 | |
320 | $res .= '<tr><th colspan="2">'._b_('apercu').'</th></tr>'; | |
321 | $ndx = $banana->spool->getndx($this->id); | |
322 | $res .= '<tr><td class="thrd" colspan="2">'.$banana->spool->to_html($ndx-$banana->tbefore, $ndx+$banana->tafter, $ndx).'</td></tr>'; | |
323 | ||
324 | return $res.'</table>'; | |
325 | } | |
1eed39ee | 326 | } |
327 | ||
328 | ?> |