/imp/lib/Mbox/Import.php

https://github.com/imr/horde · PHP · 206 lines · 119 code · 27 blank · 60 comment · 16 complexity · 905b721f70110caf87d23566871944c6 MD5 · raw file

  1. <?php
  2. /**
  3. * Copyright 2011-2014 Horde LLC (http://www.horde.org/)
  4. *
  5. * See the enclosed file COPYING for license information (GPL). If you
  6. * did not receive this file, see http://www.horde.org/licenses/gpl.
  7. *
  8. * @category Horde
  9. * @copyright 2011-2014 Horde LLC
  10. * @license http://www.horde.org/licenses/gpl GPL
  11. * @package IMP
  12. */
  13. /**
  14. * Method to import MBOX data into a mailbox.
  15. *
  16. * @author Michael Slusarz <slusarz@horde.org>
  17. * @category Horde
  18. * @copyright 2011-2014 Horde LLC
  19. * @license http://www.horde.org/licenses/gpl GPL
  20. * @package IMP
  21. */
  22. class IMP_Mbox_Import
  23. {
  24. /**
  25. * Temporary data.
  26. *
  27. * @var array
  28. */
  29. protected $_import;
  30. /**
  31. * Import mailbox.
  32. *
  33. * @var IMP_Mailbox
  34. */
  35. protected $_mbox;
  36. /**
  37. * Import a MBOX file into a mailbox.
  38. *
  39. * @param string $mbox The mailbox name to import into (UTF-8).
  40. * @param string $form_name The form field name that contains the MBOX
  41. * data.
  42. *
  43. * @return string Notification message.
  44. * @throws Horde_Exception
  45. */
  46. public function import($mbox, $form_name)
  47. {
  48. $GLOBALS['browser']->wasFileUploaded($form_name, _("mailbox file"));
  49. $this->_mbox = $mbox;
  50. $res = $this->_import($_FILES[$form_name]['tmp_name'], $_FILES[$form_name]['type']);
  51. $mbox_name = basename(Horde_Util::dispelMagicQuotes($_FILES[$form_name]['name']));
  52. if ($res === false) {
  53. throw new IMP_Exception(sprintf(_("There was an error importing %s."), $mbox_name));
  54. }
  55. return sprintf(ngettext('Imported %d message from %s.', 'Imported %d messages from %s', $res), $res, $mbox_name);
  56. }
  57. /**
  58. * Imports messages from a mbox (see RFC 4155) -or- a message source
  59. * (eml) file.
  60. *
  61. * @param string $fname Filename containing the message data.
  62. * @param string $type The MIME type of the message data.
  63. *
  64. * @return mixed False (boolean) on fail or the number of messages
  65. * imported (integer) on success.
  66. * @throws IMP_Exception
  67. */
  68. protected function _import($fname, $type)
  69. {
  70. if (!is_readable($fname)) {
  71. return false;
  72. }
  73. $fd = null;
  74. switch ($type) {
  75. case 'application/gzip':
  76. case 'application/x-gzip':
  77. case 'application/x-gzip-compressed':
  78. // No need to default to Horde_Compress because it uses zlib
  79. // also.
  80. if (in_array('compress.zlib', stream_get_wrappers())) {
  81. $fd = 'compress.zlib://' . $fname;
  82. }
  83. break;
  84. case 'application/x-bzip2':
  85. case 'application/x-bzip':
  86. if (in_array('compress.bzip2', stream_get_wrappers())) {
  87. $fd = 'compress.bzip2://' . $fname;
  88. }
  89. break;
  90. case 'application/zip':
  91. case 'application/x-compressed':
  92. case 'application/x-zip-compressed':
  93. if (in_array('zip', stream_get_wrappers())) {
  94. $fd = 'zip://' . $fname;
  95. } else {
  96. try {
  97. $zip = Horde_Compress::factory('Zip');
  98. if ($zip->canDecompress) {
  99. $file_data = file_get_contents($fname);
  100. $zip_info = $zip->decompress($file_data, array(
  101. 'action' => Horde_Compress_Zip::ZIP_LIST
  102. ));
  103. if (!empty($zip_info)) {
  104. $fd = fopen('php://temp', 'r+');
  105. foreach (array_keys($zip_info) as $key) {
  106. fwrite($fd, $zip->decompress($file_data, array(
  107. 'action' => Horde_Compress_Zip::ZIP_DATA,
  108. 'info' => $zip_info,
  109. 'key' => $key
  110. )));
  111. }
  112. rewind($fd);
  113. }
  114. }
  115. } catch (Horde_Compress_Exception $e) {
  116. if ($fd) {
  117. fclose($fd);
  118. $fd = null;
  119. }
  120. }
  121. }
  122. break;
  123. default:
  124. $fd = $fname;
  125. break;
  126. }
  127. if (is_null($fd)) {
  128. throw new IMP_Exception(_("The uploaded file cannot be opened."));
  129. }
  130. $parsed = new IMP_Mbox_Parse(
  131. $fd,
  132. $GLOBALS['injector']->getInstance('IMP_Factory_Imap')->create()->config->import_limit
  133. );
  134. $this->_import = array(
  135. 'data' => array(),
  136. 'msgs' => 0,
  137. 'size' => 0
  138. );
  139. if ($pcount = count($parsed)) {
  140. foreach ($parsed as $key => $val) {
  141. $this->_importHelper($val, ($key + 1) != $pcount);
  142. }
  143. } else {
  144. $this->_importHelper($parsed[0]);
  145. }
  146. return $this->_import['msgs']
  147. ? $this->_import['msgs']
  148. : false;
  149. }
  150. /**
  151. * Helper for _import().
  152. *
  153. * @param array $msg Message data.
  154. * @param integer $buffer Buffer messages before sending?
  155. */
  156. protected function _importHelper($msg, $buffer = false)
  157. {
  158. $this->_import['data'][] = array_filter(array(
  159. 'data' => $msg['data'],
  160. 'internaldate' => $msg['date']
  161. ));
  162. $this->_import['size'] += $msg['size'];
  163. /* Buffer 1 MB of messages before sending. */
  164. if ($buffer && ($this->_import['size'] < 1048576)) {
  165. return;
  166. }
  167. try {
  168. $this->_mbox->imp_imap->append($this->_mbox, $this->_import['data']);
  169. $this->_import['msgs'] += count($this->_import['data']);
  170. } catch (IMP_Imap_Exception $e) {
  171. throw new IMP_Exception(sprintf(_("Error when importing messages; %u messages successfully imported before error."), $this->_import['msgs']));
  172. }
  173. foreach ($this->_import['data'] as $val) {
  174. fclose($val['data']);
  175. }
  176. $this->_import['data'] = array();
  177. $this->_import['size'] = 0;
  178. }
  179. }