1<?php 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-2015 Zend Technologies USA Inc. (http://www.zend.com) 19 * @license http://framework.zend.com/license/new-bsd New BSD License 20 * @version $Id$ 21 */ 22 23 24/** 25 * @see Zend_Mail_Storage_Folder 26 */ 27 28/** 29 * @see Zend_Mail_Storage_Folder_Interface 30 */ 31 32/** 33 * @see Zend_Mail_Storage_Mbox 34 */ 35 36 37/** 38 * @category Zend 39 * @package Zend_Mail 40 * @subpackage Storage 41 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 42 * @license http://framework.zend.com/license/new-bsd New BSD License 43 */ 44class Zend_Mail_Storage_Folder_Mbox extends Zend_Mail_Storage_Mbox implements Zend_Mail_Storage_Folder_Interface 45{ 46 /** 47 * Zend_Mail_Storage_Folder root folder for folder structure 48 * @var Zend_Mail_Storage_Folder 49 */ 50 protected $_rootFolder; 51 52 /** 53 * rootdir of folder structure 54 * @var string 55 */ 56 protected $_rootdir; 57 58 /** 59 * name of current folder 60 * @var string 61 */ 62 protected $_currentFolder; 63 64 /** 65 * Create instance with parameters 66 * 67 * Disallowed parameters are: 68 * - filename use Zend_Mail_Storage_Mbox for a single file 69 * Supported parameters are: 70 * - dirname rootdir of mbox structure 71 * - folder intial selected folder, default is 'INBOX' 72 * 73 * @param array $params mail reader specific parameters 74 * @throws Zend_Mail_Storage_Exception 75 */ 76 public function __construct($params) 77 { 78 if (is_array($params)) { 79 $params = (object)$params; 80 } 81 82 if (isset($params->filename)) { 83 /** 84 * @see Zend_Mail_Storage_Exception 85 */ 86 throw new Zend_Mail_Storage_Exception('use Zend_Mail_Storage_Mbox for a single file'); 87 } 88 89 if (!isset($params->dirname) || !is_dir($params->dirname)) { 90 /** 91 * @see Zend_Mail_Storage_Exception 92 */ 93 throw new Zend_Mail_Storage_Exception('no valid dirname given in params'); 94 } 95 96 $this->_rootdir = rtrim($params->dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; 97 98 $this->_buildFolderTree($this->_rootdir); 99 $this->selectFolder(!empty($params->folder) ? $params->folder : 'INBOX'); 100 $this->_has['top'] = true; 101 $this->_has['uniqueid'] = false; 102 } 103 104 /** 105 * find all subfolders and mbox files for folder structure 106 * 107 * Result is save in Zend_Mail_Storage_Folder instances with the root in $this->_rootFolder. 108 * $parentFolder and $parentGlobalName are only used internally for recursion. 109 * 110 * @param string $currentDir call with root dir, also used for recursion. 111 * @param Zend_Mail_Storage_Folder|null $parentFolder used for recursion 112 * @param string $parentGlobalName used for rescursion 113 * @return null 114 * @throws Zend_Mail_Storage_Exception 115 */ 116 protected function _buildFolderTree($currentDir, $parentFolder = null, $parentGlobalName = '') 117 { 118 if (!$parentFolder) { 119 $this->_rootFolder = new Zend_Mail_Storage_Folder('/', '/', false); 120 $parentFolder = $this->_rootFolder; 121 } 122 123 $dh = @opendir($currentDir); 124 if (!$dh) { 125 /** 126 * @see Zend_Mail_Storage_Exception 127 */ 128 throw new Zend_Mail_Storage_Exception("can't read dir $currentDir"); 129 } 130 while (($entry = readdir($dh)) !== false) { 131 // ignore hidden files for mbox 132 if ($entry[0] == '.') { 133 continue; 134 } 135 $absoluteEntry = $currentDir . $entry; 136 $globalName = $parentGlobalName . DIRECTORY_SEPARATOR . $entry; 137 if (is_file($absoluteEntry) && $this->_isMboxFile($absoluteEntry)) { 138 $parentFolder->$entry = new Zend_Mail_Storage_Folder($entry, $globalName); 139 continue; 140 } 141 if (!is_dir($absoluteEntry) /* || $entry == '.' || $entry == '..' */) { 142 continue; 143 } 144 $folder = new Zend_Mail_Storage_Folder($entry, $globalName, false); 145 $parentFolder->$entry = $folder; 146 $this->_buildFolderTree($absoluteEntry . DIRECTORY_SEPARATOR, $folder, $globalName); 147 } 148 149 closedir($dh); 150 } 151 152 /** 153 * get root folder or given folder 154 * 155 * @param string $rootFolder get folder structure for given folder, else root 156 * @return Zend_Mail_Storage_Folder root or wanted folder 157 * @throws Zend_Mail_Storage_Exception 158 */ 159 public function getFolders($rootFolder = null) 160 { 161 if (!$rootFolder) { 162 return $this->_rootFolder; 163 } 164 165 $currentFolder = $this->_rootFolder; 166 $subname = trim($rootFolder, DIRECTORY_SEPARATOR); 167 while ($currentFolder) { 168 @list($entry, $subname) = @explode(DIRECTORY_SEPARATOR, $subname, 2); 169 $currentFolder = $currentFolder->$entry; 170 if (!$subname) { 171 break; 172 } 173 } 174 175 if ($currentFolder->getGlobalName() != DIRECTORY_SEPARATOR . trim($rootFolder, DIRECTORY_SEPARATOR)) { 176 /** 177 * @see Zend_Mail_Storage_Exception 178 */ 179 throw new Zend_Mail_Storage_Exception("folder $rootFolder not found"); 180 } 181 return $currentFolder; 182 } 183 184 /** 185 * select given folder 186 * 187 * folder must be selectable! 188 * 189 * @param Zend_Mail_Storage_Folder|string $globalName global name of folder or instance for subfolder 190 * @return null 191 * @throws Zend_Mail_Storage_Exception 192 */ 193 public function selectFolder($globalName) 194 { 195 $this->_currentFolder = (string)$globalName; 196 197 // getting folder from folder tree for validation 198 $folder = $this->getFolders($this->_currentFolder); 199 200 try { 201 $this->_openMboxFile($this->_rootdir . $folder->getGlobalName()); 202 } catch(Zend_Mail_Storage_Exception $e) { 203 // check what went wrong 204 if (!$folder->isSelectable()) { 205 /** 206 * @see Zend_Mail_Storage_Exception 207 */ 208 throw new Zend_Mail_Storage_Exception("{$this->_currentFolder} is not selectable", 0, $e); 209 } 210 // seems like file has vanished; rebuilding folder tree - but it's still an exception 211 $this->_buildFolderTree($this->_rootdir); 212 /** 213 * @see Zend_Mail_Storage_Exception 214 */ 215 throw new Zend_Mail_Storage_Exception('seems like the mbox file has vanished, I\'ve rebuild the ' . 216 'folder tree, search for an other folder and try again', 0, $e); 217 } 218 } 219 220 /** 221 * get Zend_Mail_Storage_Folder instance for current folder 222 * 223 * @return Zend_Mail_Storage_Folder instance of current folder 224 * @throws Zend_Mail_Storage_Exception 225 */ 226 public function getCurrentFolder() 227 { 228 return $this->_currentFolder; 229 } 230 231 /** 232 * magic method for serialize() 233 * 234 * with this method you can cache the mbox class 235 * 236 * @return array name of variables 237 */ 238 public function __sleep() 239 { 240 return array_merge(parent::__sleep(), array('_currentFolder', '_rootFolder', '_rootdir')); 241 } 242 243 /** 244 * magic method for unserialize() 245 * 246 * with this method you can cache the mbox class 247 * 248 * @return null 249 */ 250 public function __wakeup() 251 { 252 // if cache is stall selectFolder() rebuilds the tree on error 253 parent::__wakeup(); 254 } 255} 256