PageRenderTime 62ms CodeModel.GetById 34ms RepoModel.GetById 0ms app.codeStats 0ms

/fo/library/Zend/Mail/Storage/Mbox.php

https://github.com/openstate/HNS.dev
PHP | 434 lines | 179 code | 48 blank | 207 comment | 28 complexity | e71a13e8cbcd1220faefa4feaa416a23 MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to version 1.0 of the Zend Framework
  8. * license, that is bundled with this package in the file LICENSE.txt, and
  9. * is available through the world-wide-web at the following URL:
  10. * http://framework.zend.com/license/new-bsd. If you did not receive
  11. * a copy of the Zend Framework license and are unable to obtain it
  12. * through the world-wide-web, please send a note to license@zend.com
  13. * so we can mail you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Mail
  17. * @subpackage Storage
  18. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: Mbox.php 8064 2008-02-16 10:58:39Z thomas $
  21. */
  22. /**
  23. * @see Zend_Loader
  24. * May be used in constructor, but commented out for now
  25. */
  26. // require_once 'Zend/Loader.php';
  27. /**
  28. * @see Zend_Mail_Storage_Abstract
  29. */
  30. require_once 'Zend/Mail/Storage/Abstract.php';
  31. /**
  32. * @see Zend_Mail_Message
  33. */
  34. require_once 'Zend/Mail/Message.php';
  35. /**
  36. * @category Zend
  37. * @package Zend_Mail
  38. * @subpackage Storage
  39. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  40. * @license http://framework.zend.com/license/new-bsd New BSD License
  41. */
  42. class Zend_Mail_Storage_Mbox extends Zend_Mail_Storage_Abstract
  43. {
  44. /**
  45. * file handle to mbox file
  46. * @var null|resource
  47. */
  48. protected $_fh;
  49. /**
  50. * filename of mbox file for __wakeup
  51. * @var string
  52. */
  53. protected $_filename;
  54. /**
  55. * modification date of mbox file for __wakeup
  56. * @var int
  57. */
  58. protected $_filemtime;
  59. /**
  60. * start and end position of messages as array('start' => start, 'seperator' => headersep, 'end' => end)
  61. * @var array
  62. */
  63. protected $_positions;
  64. /**
  65. * Count messages all messages in current box
  66. *
  67. * @return int number of messages
  68. * @throws Zend_Mail_Storage_Exception
  69. */
  70. public function countMessages()
  71. {
  72. return count($this->_positions);
  73. }
  74. /**
  75. * Get a list of messages with number and size
  76. *
  77. * @param int|null $id number of message or null for all messages
  78. * @return int|array size of given message of list with all messages as array(num => size)
  79. */
  80. public function getSize($id = 0)
  81. {
  82. if ($id) {
  83. $pos = $this->_positions[$id - 1];
  84. return $pos['end'] - $pos['start'];
  85. }
  86. $result = array();
  87. foreach ($this->_positions as $num => $pos) {
  88. $result[$num + 1] = $pos['end'] - $pos['start'];
  89. }
  90. return $result;
  91. }
  92. /**
  93. * Get positions for mail message or throw exeption if id is invalid
  94. *
  95. * @param int $id number of message
  96. * @return array positions as in _positions
  97. * @throws Zend_Mail_Storage_Exception
  98. */
  99. protected function _getPos($id)
  100. {
  101. if (!isset($this->_positions[$id - 1])) {
  102. /**
  103. * @see Zend_Mail_Storage_Exception
  104. */
  105. require_once 'Zend/Mail/Storage/Exception.php';
  106. throw new Zend_Mail_Storage_Exception('id does not exist');
  107. }
  108. return $this->_positions[$id - 1];
  109. }
  110. /**
  111. * Fetch a message
  112. *
  113. * @param int $id number of message
  114. * @return Zend_Mail_Message
  115. * @throws Zend_Mail_Storage_Exception
  116. */
  117. public function getMessage($id)
  118. {
  119. $bodyLines = 0; // TODO: need a way to change that
  120. $message = $this->getRawHeader($id);
  121. // file pointer is after headers now
  122. if ($bodyLines) {
  123. $message .= "\n";
  124. while ($bodyLines-- && ftell($this->_fh) < $this->_positions[$id - 1]['end']) {
  125. $message .= fgets($this->_fh);
  126. }
  127. }
  128. return new $this->_messageClass(array('handler' => $this, 'id' => $id, 'headers' => $message));
  129. }
  130. /*
  131. * Get raw header of message or part
  132. *
  133. * @param int $id number of message
  134. * @param null|array|string $part path to part or null for messsage header
  135. * @param int $topLines include this many lines with header (after an empty line)
  136. * @return string raw header
  137. * @throws Zend_Mail_Protocol_Exception
  138. * @throws Zend_Mail_Storage_Exception
  139. */
  140. public function getRawHeader($id, $part = null, $topLines = 0)
  141. {
  142. if ($part !== null) {
  143. // TODO: implement
  144. /**
  145. * @see Zend_Mail_Storage_Exception
  146. */
  147. require_once 'Zend/Mail/Storage/Exception.php';
  148. throw new Zend_Mail_Storage_Exception('not implemented');
  149. }
  150. $messagePos = $this->_getPos($id);
  151. // TODO: toplines
  152. return stream_get_contents($this->_fh, $messagePos['separator'] - $messagePos['start'], $messagePos['start']);
  153. }
  154. /*
  155. * Get raw content of message or part
  156. *
  157. * @param int $id number of message
  158. * @param null|array|string $part path to part or null for messsage content
  159. * @return string raw content
  160. * @throws Zend_Mail_Protocol_Exception
  161. * @throws Zend_Mail_Storage_Exception
  162. */
  163. public function getRawContent($id, $part = null)
  164. {
  165. if ($part !== null) {
  166. // TODO: implement
  167. /**
  168. * @see Zend_Mail_Storage_Exception
  169. */
  170. require_once 'Zend/Mail/Storage/Exception.php';
  171. throw new Zend_Mail_Storage_Exception('not implemented');
  172. }
  173. $messagePos = $this->_getPos($id);
  174. return stream_get_contents($this->_fh, $messagePos['end'] - $messagePos['separator'], $messagePos['separator']);
  175. }
  176. /**
  177. * Create instance with parameters
  178. * Supported parameters are:
  179. * - filename filename of mbox file
  180. *
  181. * @param $params array mail reader specific parameters
  182. * @throws Zend_Mail_Storage_Exception
  183. */
  184. public function __construct($params)
  185. {
  186. if (is_array($params)) {
  187. $params = (object)$params;
  188. }
  189. if (!isset($params->filename) /* || Zend_Loader::isReadable($params['filename']) */) {
  190. /**
  191. * @see Zend_Mail_Storage_Exception
  192. */
  193. require_once 'Zend/Mail/Storage/Exception.php';
  194. throw new Zend_Mail_Storage_Exception('no valid filename given in params');
  195. }
  196. $this->_openMboxFile($params->filename);
  197. $this->_has['top'] = true;
  198. $this->_has['uniqueid'] = false;
  199. }
  200. /**
  201. * check if given file is a mbox file
  202. *
  203. * if $file is a resource its file pointer is moved after the first line
  204. *
  205. * @param resource|string $file stream resource of name of file
  206. * @param bool $fileIsString file is string or resource
  207. * @return bool file is mbox file
  208. */
  209. protected function _isMboxFile($file, $fileIsString = true)
  210. {
  211. if ($fileIsString) {
  212. $file = @fopen($file, 'r');
  213. if (!$file) {
  214. return false;
  215. }
  216. } else {
  217. fseek($file, 0);
  218. }
  219. $result = false;
  220. $line = fgets($file);
  221. if (strpos($line, 'From ') === 0) {
  222. $result = true;
  223. }
  224. if ($fileIsString) {
  225. @fclose($file);
  226. }
  227. return $result;
  228. }
  229. /**
  230. * open given file as current mbox file
  231. *
  232. * @param string $filename filename of mbox file
  233. * @return null
  234. * @throws Zend_Mail_Storage_Exception
  235. */
  236. protected function _openMboxFile($filename)
  237. {
  238. if ($this->_fh) {
  239. $this->close();
  240. }
  241. $this->_fh = @fopen($filename, 'r');
  242. if (!$this->_fh) {
  243. /**
  244. * @see Zend_Mail_Storage_Exception
  245. */
  246. require_once 'Zend/Mail/Storage/Exception.php';
  247. throw new Zend_Mail_Storage_Exception('cannot open mbox file');
  248. }
  249. $this->_filename = $filename;
  250. $this->_filemtime = filemtime($this->_filename);
  251. if (!$this->_isMboxFile($this->_fh, false)) {
  252. @fclose($this->_fh);
  253. /**
  254. * @see Zend_Mail_Storage_Exception
  255. */
  256. require_once 'Zend/Mail/Storage/Exception.php';
  257. throw new Zend_Mail_Storage_Exception('file is not a valid mbox format');
  258. }
  259. $messagePos = array('start' => ftell($this->_fh), 'separator' => 0, 'end' => 0);
  260. while (($line = fgets($this->_fh)) !== false) {
  261. if (strpos($line, 'From ') === 0) {
  262. $messagePos['end'] = ftell($this->_fh) - strlen($line) - 2; // + newline
  263. if (!$messagePos['separator']) {
  264. $messagePos['separator'] = $messagePos['end'];
  265. }
  266. $this->_positions[] = $messagePos;
  267. $messagePos = array('start' => ftell($this->_fh), 'separator' => 0, 'end' => 0);
  268. }
  269. if (!$messagePos['separator'] && !trim($line)) {
  270. $messagePos['separator'] = ftell($this->_fh);
  271. }
  272. }
  273. $messagePos['end'] = ftell($this->_fh);
  274. if (!$messagePos['separator']) {
  275. $messagePos['separator'] = $messagePos['end'];
  276. }
  277. $this->_positions[] = $messagePos;
  278. }
  279. /**
  280. * Close resource for mail lib. If you need to control, when the resource
  281. * is closed. Otherwise the destructor would call this.
  282. *
  283. * @return void
  284. */
  285. public function close()
  286. {
  287. @fclose($this->_fh);
  288. $this->_positions = array();
  289. }
  290. /**
  291. * Waste some CPU cycles doing nothing.
  292. *
  293. * @return void
  294. */
  295. public function noop()
  296. {
  297. return true;
  298. }
  299. /**
  300. * stub for not supported message deletion
  301. *
  302. * @return null
  303. * @throws Zend_Mail_Storage_Exception
  304. */
  305. public function removeMessage($id)
  306. {
  307. /**
  308. * @see Zend_Mail_Storage_Exception
  309. */
  310. require_once 'Zend/Mail/Storage/Exception.php';
  311. throw new Zend_Mail_Storage_Exception('mbox is read-only');
  312. }
  313. /**
  314. * get unique id for one or all messages
  315. *
  316. * Mbox does not support unique ids (yet) - it's always the same as the message number.
  317. * That shouldn't be a problem, because we can't change mbox files. Therefor the message
  318. * number is save enough.
  319. *
  320. * @param int|null $id message number
  321. * @return array|string message number for given message or all messages as array
  322. * @throws Zend_Mail_Storage_Exception
  323. */
  324. public function getUniqueId($id = null)
  325. {
  326. if ($id) {
  327. // check if id exists
  328. $this->_getPos($id);
  329. return $id;
  330. }
  331. $range = range(1, $this->countMessages());
  332. return array_combine($range, $range);
  333. }
  334. /**
  335. * get a message number from a unique id
  336. *
  337. * I.e. if you have a webmailer that supports deleting messages you should use unique ids
  338. * as parameter and use this method to translate it to message number right before calling removeMessage()
  339. *
  340. * @param string $id unique id
  341. * @return int message number
  342. * @throws Zend_Mail_Storage_Exception
  343. */
  344. public function getNumberByUniqueId($id)
  345. {
  346. // check if id exists
  347. $this->_getPos($id);
  348. return $id;
  349. }
  350. /**
  351. * magic method for serialize()
  352. *
  353. * with this method you can cache the mbox class
  354. *
  355. * @return array name of variables
  356. */
  357. public function __sleep()
  358. {
  359. return array('_filename', '_positions', '_filemtime');
  360. }
  361. /**
  362. * magic method for unserialize()
  363. *
  364. * with this method you can cache the mbox class
  365. * for cache validation the mtime of the mbox file is used
  366. *
  367. * @return null
  368. * @throws Zend_Mail_Storage_Exception
  369. */
  370. public function __wakeup()
  371. {
  372. if ($this->_filemtime != @filemtime($this->_filename)) {
  373. $this->close();
  374. $this->_openMboxFile($this->_filename);
  375. } else {
  376. $this->_fh = @fopen($this->_filename, 'r');
  377. if (!$this->_fh) {
  378. /**
  379. * @see Zend_Mail_Storage_Exception
  380. */
  381. require_once 'Zend/Mail/Storage/Exception.php';
  382. throw new Zend_Mail_Storage_Exception('cannot open mbox file');
  383. }
  384. }
  385. }
  386. }