You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

attachments.inc 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. <?php
  2. /**
  3. +-----------------------------------------------------------------------+
  4. | program/steps/mail/attachments.inc |
  5. | |
  6. | This file is part of the Roundcube Webmail client |
  7. | Copyright (C) 2005-2013, The Roundcube Dev Team |
  8. | |
  9. | Licensed under the GNU General Public License version 3 or |
  10. | any later version with exceptions for skins & plugins. |
  11. | See the README file for a full license statement. |
  12. | |
  13. | PURPOSE: |
  14. | Upload, remove, display attachments in compose form |
  15. | |
  16. +-----------------------------------------------------------------------+
  17. | Author: Thomas Bruederli <roundcube@gmail.com> |
  18. +-----------------------------------------------------------------------+
  19. */
  20. // Upload progress update
  21. if (!empty($_GET['_progress'])) {
  22. $RCMAIL->upload_progress();
  23. }
  24. $COMPOSE_ID = rcube_utils::get_input_value('_id', rcube_utils::INPUT_GPC);
  25. $COMPOSE = null;
  26. if ($COMPOSE_ID && $_SESSION['compose_data_' . $COMPOSE_ID]) {
  27. $SESSION_KEY = 'compose_data_' . $COMPOSE_ID;
  28. $COMPOSE =& $_SESSION[$SESSION_KEY];
  29. }
  30. if (!$COMPOSE) {
  31. die("Invalid session var!");
  32. }
  33. // remove an attachment
  34. if ($RCMAIL->action == 'remove-attachment') {
  35. $id = 'undefined';
  36. if (preg_match('/^rcmfile(\w+)$/', $_POST['_file'], $regs)) {
  37. $id = $regs[1];
  38. }
  39. if ($attachment = $COMPOSE['attachments'][$id]) {
  40. $attachment = $RCMAIL->plugins->exec_hook('attachment_delete', $attachment);
  41. }
  42. if ($attachment['status']) {
  43. if (is_array($COMPOSE['attachments'][$id])) {
  44. $RCMAIL->session->remove($SESSION_KEY.'.attachments.'.$id);
  45. $OUTPUT->command('remove_from_attachment_list', "rcmfile$id");
  46. }
  47. }
  48. $OUTPUT->send();
  49. exit;
  50. }
  51. if ($RCMAIL->action == 'display-attachment') {
  52. $id = 'undefined';
  53. if (preg_match('/^rcmfile(\w+)$/', $_GET['_file'], $regs)) {
  54. $id = $regs[1];
  55. }
  56. $RCMAIL->display_uploaded_file($COMPOSE['attachments'][$id]);
  57. exit;
  58. }
  59. /***** attachment upload action *****/
  60. // clear all stored output properties (like scripts and env vars)
  61. $OUTPUT->reset();
  62. $uploadid = rcube_utils::get_input_value('_uploadid', rcube_utils::INPUT_GPC);
  63. $uri = rcube_utils::get_input_value('_uri', rcube_utils::INPUT_POST);
  64. // handle dropping a reference to an attachment part of some message
  65. if ($uri) {
  66. $url = parse_url($uri);
  67. parse_str($url['query'], $params);
  68. if (strlen($params['_mbox']) && $params['_uid'] && $params['_part']) {
  69. // @TODO: at some point we might support drag-n-drop between
  70. // two different accounts on the same server, for now make sure
  71. // this is the same server and the same user
  72. list($host, $port) = explode(':', $_SERVER['HTTP_HOST']);
  73. if ($host == $url['host'] && $port == $url['port']
  74. && $RCMAIL->get_user_name() == rawurldecode($url['user'])
  75. ) {
  76. $message = new rcube_message($params['_uid'], $params['_mbox']);
  77. }
  78. }
  79. if ($message && !empty($message->headers)
  80. && ($attachment = rcmail_save_attachment($message, $params['_part'], $COMPOSE_ID))
  81. ) {
  82. rcmail_attachment_success($attachment, $uploadid);
  83. }
  84. else {
  85. $OUTPUT->command('display_message', $RCMAIL->gettext('filelinkerror'), 'error');
  86. $OUTPUT->command('remove_from_attachment_list', $uploadid);
  87. }
  88. $OUTPUT->send();
  89. return;
  90. }
  91. // handle file(s) upload
  92. if (is_array($_FILES['_attachments']['tmp_name'])) {
  93. $multiple = count($_FILES['_attachments']['tmp_name']) > 1;
  94. foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath) {
  95. // Process uploaded attachment if there is no error
  96. $err = $_FILES['_attachments']['error'][$i];
  97. if (!$err) {
  98. $attachment = $RCMAIL->plugins->exec_hook('attachment_upload', array(
  99. 'path' => $filepath,
  100. 'size' => $_FILES['_attachments']['size'][$i],
  101. 'name' => $_FILES['_attachments']['name'][$i],
  102. 'mimetype' => rcube_mime::file_content_type($filepath, $_FILES['_attachments']['name'][$i], $_FILES['_attachments']['type'][$i]),
  103. 'group' => $COMPOSE_ID,
  104. ));
  105. }
  106. if (!$err && $attachment['status'] && !$attachment['abort']) {
  107. // store new attachment in session
  108. unset($attachment['status'], $attachment['abort']);
  109. $RCMAIL->session->append($SESSION_KEY . '.attachments', $attachment['id'], $attachment);
  110. rcmail_attachment_success($attachment, $uploadid);
  111. }
  112. else { // upload failed
  113. if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
  114. $size = $RCMAIL->show_bytes(parse_bytes(ini_get('upload_max_filesize')));
  115. $msg = $RCMAIL->gettext(array('name' => 'filesizeerror', 'vars' => array('size' => $size)));
  116. }
  117. else if ($attachment['error']) {
  118. $msg = $attachment['error'];
  119. }
  120. else {
  121. $msg = $RCMAIL->gettext('fileuploaderror');
  122. }
  123. if ($attachment['error'] || $err != UPLOAD_ERR_NO_FILE) {
  124. $OUTPUT->command('display_message', $msg, 'error');
  125. $OUTPUT->command('remove_from_attachment_list', $uploadid);
  126. }
  127. }
  128. }
  129. }
  130. else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  131. // if filesize exceeds post_max_size then $_FILES array is empty,
  132. // show filesizeerror instead of fileuploaderror
  133. if ($maxsize = ini_get('post_max_size')) {
  134. $msg = $RCMAIL->gettext(array(
  135. 'name' => 'filesizeerror',
  136. 'vars' => array('size' => $RCMAIL->show_bytes(parse_bytes($maxsize)))
  137. ));
  138. }
  139. else {
  140. $msg = $RCMAIL->gettext('fileuploaderror');
  141. }
  142. $OUTPUT->command('display_message', $msg, 'error');
  143. $OUTPUT->command('remove_from_attachment_list', $uploadid);
  144. }
  145. // send html page with JS calls as response
  146. $OUTPUT->command('auto_save_start', false);
  147. $OUTPUT->send('iframe');
  148. function rcmail_attachment_success($attachment, $uploadid)
  149. {
  150. global $RCMAIL, $COMPOSE;
  151. $id = $attachment['id'];
  152. if (($icon = $COMPOSE['deleteicon']) && is_file($icon)) {
  153. $button = html::img(array(
  154. 'src' => $icon,
  155. 'alt' => $RCMAIL->gettext('delete')
  156. ));
  157. }
  158. else if ($COMPOSE['textbuttons']) {
  159. $button = rcube::Q($RCMAIL->gettext('delete'));
  160. }
  161. else {
  162. $button = '';
  163. }
  164. $content = html::a(array(
  165. 'href' => "#delete",
  166. 'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this)", rcmail_output::JS_OBJECT_NAME, $id),
  167. 'title' => $RCMAIL->gettext('delete'),
  168. 'class' => 'delete',
  169. 'aria-label' => $RCMAIL->gettext('delete') . ' ' . $attachment['name'],
  170. ), $button);
  171. $content .= sprintf('%s <span class="attachment-size">(%s)</span>',
  172. rcube::Q($attachment['name']), $RCMAIL->show_bytes($attachment['size']));
  173. $RCMAIL->output->command('add2attachment_list', "rcmfile$id", array(
  174. 'html' => $content,
  175. 'name' => $attachment['name'],
  176. 'mimetype' => $attachment['mimetype'],
  177. 'classname' => rcube_utils::file2class($attachment['mimetype'], $attachment['name']),
  178. 'complete' => true), $uploadid);
  179. }