PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/zend/classes/Zend/Mail/Storage/Mbox.php

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