uid support?
[squirrelmail.git] / src / download.php
1 <?php
2
3 /**
4 * download.php
5 *
6 * Copyright (c) 1999-2002 The SquirrelMail Project Team
7 * Licensed under the GNU GPL. For full terms see the file COPYING.
8 *
9 * Handles attachment downloads to the users computer.
10 * Also allows displaying of attachments when possible.
11 *
12 * $Id$
13 */
14
15 require_once('../src/validate.php');
16 require_once('../functions/imap.php');
17 require_once('../functions/mime.php');
18 require_once('../functions/date.php');
19 require_once('../functions/html.php');
20
21 header('Pragma: ');
22 header('Cache-Control: cache');
23
24 function viewText($color, $body, $id, $entid, $mailbox, $type1, $wrap_at, $imapConnection) {
25 global $where, $what, $charset;
26 global $startMessage;
27
28 displayPageHeader($color, 'None');
29
30 if ($where && $what) {
31 // from a search
32 $message_link_str = "<a href=\"read_body.php?mailbox=".urlencode($mailbox)."&passed_id=$id&where=".urlencode($where)."&what=".urlencode($what)."\">". _("View message") . "</a>";
33 } else {
34 $message_link_str = "<a href=\"read_body.php?mailbox=".urlencode($mailbox)."&passed_id=$id&startMessage=$startMessage&show_more=0\">". _("View message") . "</a>";
35 }
36 $urlmailbox = urlencode($mailbox);
37
38 echo '<br>' .
39 html_tag( 'table',
40 html_tag( 'tr',
41 html_tag( 'td',
42 '<b><center>' .
43 _("Viewing a text attachment") . ' - ' . $message_link_str . '</b></center>',
44 'left', $color[0] )
45 ) .
46 html_tag( 'tr',
47 html_tag( 'td',
48 '<center>' .
49 "<A HREF=\"../src/download.php?absolute_dl=true&passed_id=$id&passed_ent_id=$entid&mailbox=$urlmailbox\">".
50 _("Download this as a file").
51 "</A></CENTER><BR>",
52 'left' )
53 ),
54 'center', '', 'width="100%" border="0" cellspacing="0" cellpadding="2"' );
55
56 if ($type1 == 'html') {
57 $msg = sqimap_get_message($imapConnection, $id, $mailbox);
58 $body = MagicHTML( $body, $id, $msg );
59 } else {
60 translateText($body, $wrap_at, $charset);
61 }
62
63 flush();
64
65 html_tag( 'table',
66 html_tag( 'tr',
67 html_tag( 'td', '<tt>' . $body . '</tt>', 'left', $color[4] )
68 ) ,
69 'center', '', 'width="98%" border="0" cellspacing="0" cellpadding="2"' );
70 }
71
72 function viewMessage($imapConnection, $id, $mailbox, $ent_id, $color, $wrap_at, $extracted) {
73 global $startMessage;
74
75
76 $msg = sqimap_get_message($imapConnection, $id, $mailbox);
77 $msg = getEntity($msg, $ent_id);
78
79 $header = sqimap_get_ent_header($imapConnection,$id,$mailbox,$ent_id);
80 $header->id = $id;
81 $msg->header = $header;
82
83 $ent_ar = findDisplayEntity($msg, 0);
84 $body = '';
85 for ($i = 0; $i < count($ent_ar); $i++) {
86 $body .= formatBody($imapConnection, $msg, $color, $wrap_at, $ent_ar[$i], false);
87 }
88
89 $bodyheader = viewHeader($header, $color);
90 displayPageHeader($color, 'None');
91
92 echo '<br>' .
93 html_tag( 'table', '', 'center', '', 'width="100%" border="0" cellspacing="0" cellpadding="2"' );
94
95 if ($extracted) {
96 echo html_tag( 'tr',
97 html_tag( 'td', '<center><h1>Message succesfully extracted</h1></center>', 'left', '', 'width="100%"' )
98 );
99 }
100
101 $td_str = "<b><center>". _("Viewing a message attachment") . " - ";
102 $td_str .= "<a href=\"read_body.php?mailbox=".urlencode($mailbox)."&passed_id=$id&startMessage=$startMessage&show_more=0\">". _("View message") . "</a></b></center>";
103 echo html_tag( 'tr',
104 html_tag( 'td', $td_str, 'left', $color[0] )
105 );
106
107 $urlmailbox = urlencode($mailbox);
108 $td_str = "<center><b><A HREF=\"../src/download.php?absolute_dl=true&passed_id=$id&passed_ent_id=$ent_id&mailbox=$urlmailbox\">".
109 _("Download this as a file").
110 "</A><BR>".
111 "</b></center>";
112 echo html_tag( 'tr',
113 html_tag( 'td', $td_str, 'left' )
114 ) .
115
116 "</TABLE>\n" .
117 html_tag( 'table',
118 html_tag( 'tr',
119 html_tag( 'td', $bodyheader, 'left', $color[4] )
120 ) ,
121 'center', '', 'width="100%" border="0" cellspacing="0" cellpadding="2"' ) . "\n" .
122 html_tag( 'table',
123 html_tag( 'tr',
124 html_tag( 'td', '<tt><br>' . $body . '</tt>', 'left', $color[4] )
125 ) ,
126 'center', '', 'width="98%" border="0" cellspacing="0" cellpadding="2"' ) . "<br>\n";
127
128 echo html_tag( 'table', '', '', '', 'width="100%"' ) .
129 html_tag( 'tr' ) .
130 html_tag( 'td', '', 'center', $color[9], 'width="100%"' ) .
131 '<form action="download.php" method="post"><small>'.
132 "<input type=\"hidden\" name=\"passed_id\" value=\"$id\">".
133 "<input type=\"hidden\" name=\"mailbox\" value=\"".$mailbox."\">".
134 "<input type=\"hidden\" name=\"startMessage\" value=\"$startMessage\">".
135 "<input type=\"hidden\" name=\"passed_ent_id\" value=\"$ent_id\">".
136 "<input type=\"hidden\" name=\"extract_message\" value=\"1\">".
137 _("Save to:") .
138 ' <select name="targetMailbox">';
139 get_extract_to_target_list($imapConnection);
140 echo '</select> '.'&nbsp'.
141 '<input type="submit" value="' . _("Extract") . '">'.
142 '</small>'.
143 '</form>'.
144 '</td></tr></table>';
145
146 }
147
148 function get_extract_to_target_list($imapConnection) {
149
150 $boxes = sqimap_mailbox_list($imapConnection);
151 for ($i = 0; $i < count($boxes); $i++) {
152 if (!in_array('noselect', $boxes[$i]['flags'])) {
153 $box = $boxes[$i]['unformatted'];
154 $box2 = str_replace(' ', '&nbsp;', $boxes[$i]['unformatted-disp']);
155 if ( $box2 == 'INBOX' ) {
156 $box2 = _("INBOX");
157 }
158 echo "<option value=\"$box\">$box2</option>\n";
159 }
160 }
161 }
162
163
164 function viewHeader($header,$color) {
165
166 $bodyheader = '';
167
168 /** FORMAT THE FROM STRING **/
169 $from_name = decodeHeader(htmlspecialchars($header->from));
170 if(isset($from_name) && $from_name !='') {
171 $bodyheader .= makeTableEntry($from_name,_("From"), $color);
172 }
173
174 $subject_string = decodeHeader(htmlspecialchars($header->subject));
175 if(isset($subject_string) && $subject_string !='') {
176 $bodyheader .= makeTableEntry($subject_string,_("Subject:"), $color);
177 }
178 /** FORMAT THE TO STRING **/
179 $to = formatRecipientString($header->to, "to");
180 $to_string = $to['str'];
181 $url_to_string = $to['url_str'];
182 if(isset($to_string) && $to_string !='') {
183 $bodyheader .= makeTableEntry($to_string,_("To:"), $color);
184 }
185
186 /** FORMAT THE DATE STRING **/
187 $dateString = getLongDateString($header->date);
188 if(isset($dateString) && $dateString !='') {
189 $bodyheader .= makeTableEntry($dateString,_("Date:"), $color);
190 }
191
192 /** FORMAT THE CC STRING **/
193 $cc = formatRecipientString($header->cc, "cc");
194 $cc_string = $cc['str'];
195 $url_cc_string = $cc['url_str'];
196 if(isset($cc_string) && $cc_string !='') {
197 $bodyheader .= makeTableEntry($cc_string,_("Cc:"), $color);
198 }
199
200 /** FORMAT THE BCC STRING **/
201 $bcc = formatRecipientString($header->bcc, "bcc");
202 $bcc_string = $bcc['str'];
203 $url_bcc_string = $bcc['url_str'];
204 if(isset($bcc_string) && $bcc_string !='') {
205 $bodyheader .= makeTableEntry($bcc_string,_("Bcc:"), $color);
206 }
207
208 return $bodyheader;
209 }
210
211 function makeTableEntry($str, $str_name, $color) {
212 $entry = html_tag( 'tr',
213 html_tag( 'td', $str_name, 'right', $color[0], 'valign="top"' ) .
214 html_tag( 'td', '<b>' . $str .'</b>&nbsp;', 'left', $color[0], 'valign="top" colspan="2"' )
215 );
216 return $entry;
217 }
218
219 function formatRecipientString($recipients, $item ) {
220 global $base_uri, $passed_id, $startMessage, $show_more_cc, $show_more, $show_more_bcc, $passed_ent_id;
221 global $where, $what, $mailbox, $sort;
222
223 /** TEXT STRINGS DEFINITIONS **/
224 $echo_more = _("more");
225 $echo_less = _("less");
226
227 if (!isset($show_more_cc)) {
228 $show_more_cc = FALSE;
229 }
230 if (!isset($show_more_bcc)) {
231 $show_more_bcc = FALSE;
232 }
233
234
235 $urlMailbox = urlencode($mailbox);
236 $i = 0;
237 $url_string = '';
238
239 if (isset ($recipients[0]) && trim($recipients[0])) {
240 $string = '';
241 $ary = explode(",",$recipients[0]);
242
243 switch ($item) {
244 case 'to':
245 $show = "&amp;show_more=1&amp;show_more_cc=$show_more_cc&amp;show_more_bcc=$show_more_bcc";
246 $show_n = "&amp;show_more=0&amp;show_more_cc=$show_more_cc&amp;show_more_bcc=$show_more_bcc";
247 break;
248 case 'cc':
249 $show = "&amp;show_more=$show_more&amp;show_more_cc=1&amp;show_more_bcc=$show_more_bcc";
250 $show_n = "&amp;show_more=$show_more&amp;show_more_cc=0&amp;show_more_bcc=$show_more_bcc";
251 $show_more = $show_more_cc;
252 break;
253 case 'bcc':
254 $show = "&amp;show_more=$show_more&amp;show_more_cc=$show_more_cc&amp;show_more_bcc=1";
255 $show_n = "&amp;show_more=$show_more&amp;show_more_cc=$show_more_cc&amp;show_more_bcc=0";
256 $show_more = $show_more_bcc;
257 break;
258 default:
259 $break;
260 }
261
262 while ($i < count($ary)) {
263 $ary[$i] = htmlspecialchars(decodeHeader($ary[$i]));
264 $url_string .= $ary[$i];
265 if ($string) {
266 $string = "$string<BR>$ary[$i]";
267 } else {
268 $string = "$ary[$i]";
269 }
270
271 $i++;
272 if (count($ary) > 1) {
273 if ($show_more == false) {
274 if ($i == 1) {
275
276 $string .= '&nbsp;(<A HREF="' . $base_uri .
277 "src/download.php?mailbox=$urlMailbox&amp;passed_id=$passed_id&amp;";
278 if (isset($where) && isset($what)) {
279 $string .= 'what=' . urlencode($what)."&amp;where=".urlencode($where)."&amp;passed_ent_id=$passed_ent_id$show\">$echo_more</A>)";
280 } else {
281 $string .= "sort=$sort&amp;startMessage=$startMessage"."&amp;passed_ent_id=$passed_ent_id$show\">$echo_more</A>)";
282 }
283 $i = count($ary);
284 }
285 } else if ($i == 1) {
286
287 $string .= '&nbsp;(<A HREF="' . $base_uri .
288 "src/download.php?mailbox=$urlMailbox&amp;passed_id=$passed_id&amp;";
289 if (isset($where) && isset($what)) {
290 $string .= 'what=' . urlencode($what)."&amp;where=".urlencode($where)."&amp;passed_ent_id=$passed_ent_id$show_n\">$echo_less</A>)";
291 } else {
292 $string .= "sort=$sort&amp;startMessage=$startMessage"."&amp;passed_ent_id=$passed_ent_id$show_n\">$echo_less</A>)";
293 }
294 }
295 }
296
297 }
298 }
299 else {
300 $string = '';
301 }
302 $url_string = urlencode($url_string);
303 $result = array();
304 $result['str'] = $string;
305 $result['url_str'] = $url_string;
306 return $result;
307
308 }
309
310
311 $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0);
312 sqimap_mailbox_select($imapConnection, $mailbox);
313
314 $extracted = false;
315 if (isset($extract_message) && $extract_message) {
316 $cmd = "FETCH $passed_id BODY[$passed_ent_id]";
317 $read = sqimap_run_command ($imapConnection, $cmd, true, $response, $message);
318 $cnt = count($read);
319 $body = '';
320 $length = 0;
321 for ($i=1;$i<$cnt;$i++) {
322 $length = $length + strlen($read[$i]);
323 $body .= $read[$i];
324 }
325 if (isset($targetMailbox) && $length>0) {
326 sqimap_append ($imapConnection, $targetMailbox, $length);
327 fputs($imapConnection,$body);
328 sqimap_append_done ($imapConnection);
329 $extracted = true;
330 }
331 }
332
333 if (isset($showHeaders)) {
334 $top_header = sqimap_get_message_header ($imapConnection, $passed_id, $mailbox);
335 }
336 /*
337 * lets redefine message as this particular entity that we wish to display.
338 * it should hold only the header for this entity. We need to fetch the body
339 * yet before we can display anything.
340 */
341
342 $header = sqimap_get_mime_ent_header ($imapConnection, $passed_id, $mailbox, $passed_ent_id);
343 $header->entity_id = $passed_ent_id;
344 $header->mailbox = $mailbox;
345
346 $charset = $header->charset;
347 $type0 = $header->type0;
348 $type1 = $header->type1;
349 if (isset($override_type0)) {
350 $type0 = $override_type0;
351 }
352 if (isset($override_type1)) {
353 $type1 = $override_type1;
354 }
355 $filename = decodeHeader($header->filename);
356 if (!$filename) {
357 $filename = decodeHeader($header->name);
358 }
359
360 if (strlen($filename) < 1) {
361 if ($type1 == 'plain' && $type0 == 'text') {
362 $suffix = 'txt';
363 } else if ($type1 == 'richtext' && $type0 == 'text') {
364 $suffix = 'rtf';
365 } else if ($type1 == 'postscript' && $type0 == 'application') {
366 $suffix = 'ps';
367 } else if ($type1 == 'rfc822' && $type0 == 'message') {
368 $suffix = 'eml';
369 } else {
370 $suffix = $type1;
371 }
372
373 $filename = "untitled$passed_ent_id.$suffix";
374 }
375
376
377 /*
378 * Note:
379 * The following sections display the attachment in different
380 * ways depending on how they choose. The first way will download
381 * under any circumstance. This sets the Content-type to be
382 * applicatin/octet-stream, which should be interpreted by the
383 * browser as "download me".
384 * The second method (view) is used for images or other formats
385 * that should be able to be handled by the browser. It will
386 * most likely display the attachment inline inside the browser.
387 * And finally, the third one will be used by default. If it
388 * is displayable (text or html), it will load them up in a text
389 * viewer (built in to squirrelmail). Otherwise, it sets the
390 * content-type as application/octet-stream
391 */
392 if (isset($absolute_dl) && $absolute_dl == 'true') {
393 switch($type0) {
394 case 'text':
395 DumpHeaders($type0, $type1, $filename, 1);
396 $body = mime_fetch_body($imapConnection, $passed_id, $passed_ent_id);
397 $body = decodeBody($body, $header->encoding);
398 if ($type1 == 'plain' && isset($showHeaders)) {
399 echo _("Subject") . ": " . decodeHeader($top_header->subject) . "\n".
400 " " . _("From") . ": " . decodeHeader($top_header->from) . "\n".
401 " " . _("To") . ": " . decodeHeader(getLineOfAddrs($top_header->to)) . "\n".
402 " " . _("Date") . ": " . getLongDateString($top_header->date) . "\n\n";
403 } elseif ($type1 == 'html' && isset($showHeaders)) {
404 echo html_tag( 'table',
405 html_tag( 'tr',
406 html_tag( 'th', _("Subject") . ':', 'right' ) .
407 html_tag( 'th', decodeHeader($top_header->subject), 'left' ) . "\n" .
408 html_tag( 'th', _("From") . ':', 'right' ) .
409 html_tag( 'th', decodeHeader($top_header->from), 'left' ) . "\n" .
410 html_tag( 'th', _("To") . ':', 'right' ) .
411 html_tag( 'th', decodeHeader(getLineOfAddrs($top_header->to)), 'left' ) . "\n" .
412 html_tag( 'th', _("Date") . ':', 'right' ) .
413 html_tag( 'th', getLongDateString($top_header->date), 'left' ) . "\n"
414 )
415 ) . "\n<hr>\n";
416 }
417 echo $body;
418 break;
419
420 default:
421 DumpHeaders($type0, $type1, $filename, 1);
422 mime_print_body_lines ($imapConnection, $passed_id, $passed_ent_id, $header->encoding);
423 break;
424 }
425 } else {
426 switch ($type0) {
427 case 'text':
428 if ($type1 == 'plain' || $type1 == 'html') {
429 $body = mime_fetch_body($imapConnection, $passed_id, $passed_ent_id);
430 $body = decodeBody($body, $header->encoding);
431 viewText($color, $body, $passed_id, $passed_ent_id, $mailbox, $type1, $wrap_at, $imapConnection);
432 } else {
433 DumpHeaders($type0, $type1, $filename, 0);
434 $body = mime_fetch_body($imapConnection, $passed_id, $passed_ent_id);
435 $body = decodeBody($body, $header->encoding);
436 echo $body;
437 }
438 break;
439 case 'message':
440 if ($type1 == 'rfc822' ) {
441 viewMessage($imapConnection, $passed_id, $mailbox, $passed_ent_id, $color, $wrap_at, $extracted);
442 } else {
443 $body = mime_fetch_body($imapConnection, $passed_id, $passed_ent_id);
444 $body = decodeBody($body, $msgheader->encoding);
445 viewText($color, $body, $passed_id, $passed_ent_id, $mailbox, $type1, $wrap_at, $imapConnection);
446 }
447 break;
448 default:
449 DumpHeaders($type0, $type1, $filename, 0);
450 mime_print_body_lines ($imapConnection, $passed_id, $passed_ent_id, $header->encoding);
451 break;
452 }
453 }
454
455
456 /*
457 * This function is verified to work with Netscape and the *very latest*
458 * version of IE. I don't know if it works with Opera, but it should now.
459 */
460 function DumpHeaders($type0, $type1, $filename, $force) {
461 global $HTTP_USER_AGENT;
462
463 $isIE = 0;
464
465 if (strstr($HTTP_USER_AGENT, 'compatible; MSIE ') !== false &&
466 strstr($HTTP_USER_AGENT, 'Opera') === false) {
467 $isIE = 1;
468 }
469
470 if (strstr($HTTP_USER_AGENT, 'compatible; MSIE 6') !== false &&
471 strstr($HTTP_USER_AGENT, 'Opera') === false) {
472 $isIE6 = 1;
473 }
474
475 $filename = ereg_replace('[^-a-zA-Z0-9\.]', '_', $filename);
476
477 // A Pox on Microsoft and it's Office!
478 if (! $force) {
479 // Try to show in browser window
480 header("Content-Disposition: inline; filename=\"$filename\"");
481 header("Content-Type: $type0/$type1; name=\"$filename\"");
482 } else {
483 // Try to pop up the "save as" box
484 // IE makes this hard. It pops up 2 save boxes, or none.
485 // http://support.microsoft.com/support/kb/articles/Q238/5/88.ASP
486 // But, accordint to Microsoft, it is "RFC compliant but doesn't
487 // take into account some deviations that allowed within the
488 // specification." Doesn't that mean RFC non-compliant?
489 // http://support.microsoft.com/support/kb/articles/Q258/4/52.ASP
490 //
491 // The best thing you can do for IE is to upgrade to the latest
492 // version
493 if ($isIE && !isset($isIE6)) {
494 // http://support.microsoft.com/support/kb/articles/Q182/3/15.asp
495 // Do not have quotes around filename, but that applied to
496 // "attachment"... does it apply to inline too?
497 //
498 // This combination seems to work mostly. IE 5.5 SP 1 has
499 // known issues (see the Microsoft Knowledge Base)
500 header("Content-Disposition: inline; filename=$filename");
501
502 // This works for most types, but doesn't work with Word files
503 header("Content-Type: application/download; name=\"$filename\"");
504
505 // These are spares, just in case. :-)
506 //header("Content-Type: $type0/$type1; name=\"$filename\"");
507 //header("Content-Type: application/x-msdownload; name=\"$filename\"");
508 //header("Content-Type: application/octet-stream; name=\"$filename\"");
509 } else {
510 header("Content-Disposition: attachment; filename=\"$filename\"");
511 // application/octet-stream forces download for Netscape
512 header("Content-Type: application/octet-stream; name=\"$filename\"");
513 }
514 }
515 }
516 ?>