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); | |
54 | $this->split_multipart($mpart_type[1], $mpart_boundary[1]); | |
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 | */ | |
68 | function split_multipart($type, $boundary) | |
69 | { | |
d43ebde4 | 70 | $parts = preg_split("/\n--$boundary(--|\n)/", $this->body); |
71 | foreach ($parts as $part) { | |
72 | $part = $this->get_part($part); | |
73 | $local_header = $part['headers']; | |
74 | $local_body = $part['body']; | |
75 | if (isset($local_header['content-disposition']) && preg_match("/attachment/", $local_header['content-disposition'])) { | |
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); | |
79 | } | |
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 | */ | |
8f6f50fb | 89 | function get_part($part) |
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 | */ | |
111 | function add_attachment($part) | |
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 | ||
146 | /** decode an attachment | |
147 | * @param pjid INT id of the attachment to decode | |
148 | * @param action BOOL action to execute : true=view, false=download | |
149 | */ | |
8f6f50fb | 150 | function get_attachment($pjid, $action = false) |
151 | { | |
d43ebde4 | 152 | if ($pjid >= count($this->pj)) { |
153 | return false; | |
154 | } else { | |
155 | $file = $this->pj[$pjid]; | |
156 | header('Content-Type: '.$file['MIME']); | |
157 | if (!$action) { | |
158 | header('Content-Disposition: attachment; filename="'.$file['filename'].'"'); | |
159 | } | |
160 | if ($file['encoding'] == 'base64') { | |
161 | echo base64_decode($file['data']); | |
162 | } else { | |
163 | header('Content-Transfer-Encoding: '.$file['encoding']); | |
164 | echo $file['data']; | |
165 | } | |
166 | return true; | |
167 | } | |
168 | } | |
169 | ||
8f6f50fb | 170 | /** set body to represent the given part |
171 | * @param partid INT index of the part in messages | |
172 | */ | |
173 | function set_body_to_part($partid) | |
174 | { | |
175 | global $banana; | |
176 | ||
177 | if (count($this->messages) == 0) { | |
178 | return false; | |
179 | } | |
180 | ||
181 | $local_header = $this->messages[$partid]['headers']; | |
182 | $this->body = $this->messages[$partid]['body']; | |
183 | foreach ($banana->parse_hdr as $hdr) { | |
184 | if (isset($local_header[$hdr])) { | |
185 | $this->headers[$hdr] = $local_header[$hdr]; | |
186 | } | |
187 | } | |
188 | return true; | |
189 | } | |
190 | ||
2dbc0167 | 191 | function _header() |
01681efd | 192 | { |
2dbc0167 | 193 | global $banana; |
b9ea5b30 | 194 | $hdrs = $banana->nntp->head($this->id); |
e785d91c | 195 | if (!$hdrs) { |
196 | $this = null; | |
197 | return false; | |
198 | } | |
01681efd | 199 | |
e785d91c | 200 | // parse headers |
201 | foreach ($hdrs as $line) { | |
202 | if (preg_match("/^[\t\r ]+/", $line)) { | |
01681efd | 203 | $line = ($hdr=="X-Face"?"":" ").ltrim($line); |
2dbc0167 | 204 | if (in_array($hdr, $banana->parse_hdr)) { |
01681efd | 205 | $this->headers[$hdr] .= $line; |
e785d91c | 206 | } |
207 | } else { | |
208 | list($hdr, $val) = split(":[ \t\r]*", $line, 2); | |
01681efd | 209 | $hdr = strtolower($hdr); |
2dbc0167 | 210 | if (in_array($hdr, $banana->parse_hdr)) { |
01681efd | 211 | $this->headers[$hdr] = $val; |
e785d91c | 212 | } |
e785d91c | 213 | } |
214 | } | |
215 | // decode headers | |
2dbc0167 | 216 | foreach ($banana->hdecode as $hdr) { |
01681efd | 217 | if (isset($this->headers[$hdr])) { |
218 | $this->headers[$hdr] = headerDecode($this->headers[$hdr]); | |
e785d91c | 219 | } |
220 | } | |
01681efd | 221 | |
222 | $this->name = $this->headers['from']; | |
223 | $this->name = preg_replace('/<[^ ]*>/', '', $this->name); | |
224 | $this->name = trim($this->name); | |
1eed39ee | 225 | } |
b9ea5b30 | 226 | |
65d96b1f | 227 | function checkcancel() |
228 | { | |
b9ea5b30 | 229 | if (function_exists('hook_checkcancel')) { |
230 | return hook_checkcancel($this->headers); | |
231 | } | |
232 | return ($this->headers['from'] == $_SESSION['name']." <".$_SESSION['mail'].">"); | |
233 | } | |
234 | ||
8f6f50fb | 235 | /** convert message to html |
236 | * @param partid INT id of the multipart message that must be displaid | |
237 | */ | |
238 | function to_html($partid = 0) | |
65d96b1f | 239 | { |
240 | global $banana; | |
241 | ||
8f6f50fb | 242 | if ($partid != 0) { |
243 | $this->set_body_to_part($partid); | |
244 | } | |
245 | ||
65d96b1f | 246 | $res = '<table class="bicol banana_msg" cellpadding="0" cellspacing="0">'; |
247 | $res .= '<tr><th colspan="2">'._b_('En-têtes').'</th></tr>'; | |
248 | ||
249 | foreach ($banana->show_hdr as $hdr) { | |
250 | if (isset($this->headers[$hdr])) { | |
251 | $res2 = formatdisplayheader($hdr, $this->headers[$hdr]); | |
252 | if ($res2) { | |
253 | $res .= '<tr><td class="hdr">'.header_translate($hdr)."</td><td class='val'>$res2</td></tr>\n"; | |
254 | } | |
255 | } | |
256 | } | |
257 | ||
8f6f50fb | 258 | $res .= '<tr><th colspan="2">'._b_('Corps'); |
259 | if (count($this->messages) > 1) { | |
260 | for ($i = 0 ; $i < count($this->messages) ; $i++) { | |
261 | if ($i == 0) { | |
262 | $res .= ' : '; | |
263 | } else { | |
264 | $res .= ' . '; | |
265 | } | |
266 | preg_match("@text/([^;]+);@", $this->messages[$i]['headers']['content-type'], $format); | |
267 | $format = textFormat_translate($format[1]); | |
268 | if ($i != $partid) { | |
269 | $res .= '<a href="?group='.$banana->state['group'].'&artid='.$this->id.'&part='.$i.'">'.$format.'</a>'; | |
270 | } else { | |
271 | $res .= $format; | |
272 | } | |
273 | } | |
274 | } | |
275 | $res .= '</th></tr>'; | |
276 | ||
277 | preg_match("@text/([^;]+);@", $this->headers['content-type'], $format); | |
278 | $format = $format[1]; | |
279 | $res .= '<tr><td colspan="2">'; | |
280 | if ($format == 'html') { | |
281 | $res .= formatbody($this->body, $format); | |
282 | } else { | |
283 | $res .= '<pre>'.formatbody($this->body).'</pre>'; | |
284 | } | |
285 | $res .= '</td></tr>'; | |
d43ebde4 | 286 | |
287 | if (count($this->pj) > 0) { | |
288 | $res .= '<tr><th colspan="2">'._b_('Pièces jointes').'</th></tr>'; | |
289 | $res .= '<tr><td colspan="2">'; | |
290 | $i = 0; | |
291 | foreach ($this->pj as $file) { | |
292 | $res .= $file['filename'].' ('.$file['MIME'].') : '; | |
293 | $res .= '<a href="pj.php?group='.$banana->state['group'].'&artid='.$this->id.'&pj='.$i.'">télécharger</a>'; | |
294 | if (preg_match("@(image|text)/@", $file['MIME'])) { | |
295 | $res .= ' . <a href="pj.php?group='.$banana->state['group'].'&artid='.$this->id.'&pj='.$i.'&action=view">aperçu</a>'; | |
296 | } | |
297 | $res .= '<br/>'; | |
298 | $i++; | |
299 | } | |
300 | $res .= '</td></tr>'; | |
301 | } | |
65d96b1f | 302 | |
303 | $res .= '<tr><th colspan="2">'._b_('apercu').'</th></tr>'; | |
304 | $ndx = $banana->spool->getndx($this->id); | |
305 | $res .= '<tr><td class="thrd" colspan="2">'.$banana->spool->to_html($ndx-$banana->tbefore, $ndx+$banana->tafter, $ndx).'</td></tr>'; | |
306 | ||
307 | return $res.'</table>'; | |
308 | } | |
1eed39ee | 309 | } |
310 | ||
311 | ?> |