File indexing completed on 2025-05-04 05:28:03

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_Mail
0017  * @subpackage Storage
0018  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0019  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0020  * @version    $Id$
0021  */
0022 
0023 
0024 /**
0025  * @see Zend_Mail_Storage_Folder
0026  */
0027 // require_once 'Zend/Mail/Storage/Folder.php';
0028 
0029 /**
0030  * @see Zend_Mail_Storage_Folder_Interface
0031  */
0032 // require_once 'Zend/Mail/Storage/Folder/Interface.php';
0033 
0034 /**
0035  * @see Zend_Mail_Storage_Maildir
0036  */
0037 // require_once 'Zend/Mail/Storage/Maildir.php';
0038 
0039 
0040 /**
0041  * @category   Zend
0042  * @package    Zend_Mail
0043  * @subpackage Storage
0044  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0045  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0046  */
0047 class Zend_Mail_Storage_Folder_Maildir extends Zend_Mail_Storage_Maildir implements Zend_Mail_Storage_Folder_Interface
0048 {
0049     /**
0050      * Zend_Mail_Storage_Folder root folder for folder structure
0051      * @var Zend_Mail_Storage_Folder
0052      */
0053     protected $_rootFolder;
0054 
0055     /**
0056      * rootdir of folder structure
0057      * @var string
0058      */
0059     protected $_rootdir;
0060 
0061     /**
0062      * name of current folder
0063      * @var string
0064      */
0065     protected $_currentFolder;
0066 
0067     /**
0068      * delim char for subfolders
0069      * @var string
0070      */
0071     protected $_delim;
0072 
0073     /**
0074      * Create instance with parameters
0075      * Supported parameters are:
0076      *   - dirname rootdir of maildir structure
0077      *   - delim   delim char for folder structur, default is '.'
0078      *   - folder intial selected folder, default is 'INBOX'
0079      *
0080      * @param array $params mail reader specific parameters
0081      * @throws Zend_Mail_Storage_Exception
0082      */
0083     public function __construct($params)
0084     {
0085         if (is_array($params)) {
0086             $params = (object)$params;
0087         }
0088 
0089         if (!isset($params->dirname) || !is_dir($params->dirname)) {
0090             /**
0091              * @see Zend_Mail_Storage_Exception
0092              */
0093             // require_once 'Zend/Mail/Storage/Exception.php';
0094             throw new Zend_Mail_Storage_Exception('no valid dirname given in params');
0095         }
0096 
0097         $this->_rootdir = rtrim($params->dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
0098 
0099         $this->_delim = isset($params->delim) ? $params->delim : '.';
0100 
0101         $this->_buildFolderTree();
0102         $this->selectFolder(!empty($params->folder) ? $params->folder : 'INBOX');
0103         $this->_has['top'] = true;
0104         $this->_has['flags'] = true;
0105     }
0106 
0107     /**
0108      * find all subfolders and mbox files for folder structure
0109      *
0110      * Result is save in Zend_Mail_Storage_Folder instances with the root in $this->_rootFolder.
0111      * $parentFolder and $parentGlobalName are only used internally for recursion.
0112      *
0113      * @return null
0114      * @throws Zend_Mail_Storage_Exception
0115      */
0116     protected function _buildFolderTree()
0117     {
0118         $this->_rootFolder = new Zend_Mail_Storage_Folder('/', '/', false);
0119         $this->_rootFolder->INBOX = new Zend_Mail_Storage_Folder('INBOX', 'INBOX', true);
0120 
0121         $dh = @opendir($this->_rootdir);
0122         if (!$dh) {
0123             /**
0124              * @see Zend_Mail_Storage_Exception
0125              */
0126             // require_once 'Zend/Mail/Storage/Exception.php';
0127             throw new Zend_Mail_Storage_Exception("can't read folders in maildir");
0128         }
0129         $dirs = array();
0130         while (($entry = readdir($dh)) !== false) {
0131             // maildir++ defines folders must start with .
0132             if ($entry[0] != '.' || $entry == '.' || $entry == '..') {
0133                 continue;
0134             }
0135             if ($this->_isMaildir($this->_rootdir . $entry)) {
0136                 $dirs[] = $entry;
0137             }
0138         }
0139         closedir($dh);
0140 
0141         sort($dirs);
0142         $stack = array(null);
0143         $folderStack = array(null);
0144         $parentFolder = $this->_rootFolder;
0145         $parent = '.';
0146 
0147         foreach ($dirs as $dir) {
0148             do {
0149                 if (strpos($dir, $parent) === 0) {
0150                     $local = substr($dir, strlen($parent));
0151                     if (strpos($local, $this->_delim) !== false) {
0152                         /**
0153                          * @see Zend_Mail_Storage_Exception
0154                          */
0155                         // require_once 'Zend/Mail/Storage/Exception.php';
0156                         throw new Zend_Mail_Storage_Exception('error while reading maildir');
0157                     }
0158                     array_push($stack, $parent);
0159                     $parent = $dir . $this->_delim;
0160                     $folder = new Zend_Mail_Storage_Folder($local, substr($dir, 1), true);
0161                     $parentFolder->$local = $folder;
0162                     array_push($folderStack, $parentFolder);
0163                     $parentFolder = $folder;
0164                     break;
0165                 } else if ($stack) {
0166                     $parent = array_pop($stack);
0167                     $parentFolder = array_pop($folderStack);
0168                 }
0169             } while ($stack);
0170             if (!$stack) {
0171                 /**
0172                  * @see Zend_Mail_Storage_Exception
0173                  */
0174                 // require_once 'Zend/Mail/Storage/Exception.php';
0175                 throw new Zend_Mail_Storage_Exception('error while reading maildir');
0176             }
0177         }
0178     }
0179 
0180     /**
0181      * get root folder or given folder
0182      *
0183      * @param string $rootFolder get folder structure for given folder, else root
0184      * @return Zend_Mail_Storage_Folder root or wanted folder
0185      * @throws Zend_Mail_Storage_Exception
0186      */
0187     public function getFolders($rootFolder = null)
0188     {
0189         if (!$rootFolder || $rootFolder == 'INBOX') {
0190             return $this->_rootFolder;
0191         }
0192 
0193         // rootdir is same as INBOX in maildir
0194         if (strpos($rootFolder, 'INBOX' . $this->_delim) === 0) {
0195             $rootFolder = substr($rootFolder, 6);
0196         }
0197         $currentFolder = $this->_rootFolder;
0198         $subname = trim($rootFolder, $this->_delim);
0199         while ($currentFolder) {
0200             @list($entry, $subname) = @explode($this->_delim, $subname, 2);
0201             $currentFolder = $currentFolder->$entry;
0202             if (!$subname) {
0203                 break;
0204             }
0205         }
0206 
0207         if ($currentFolder->getGlobalName() != rtrim($rootFolder, $this->_delim)) {
0208             /**
0209              * @see Zend_Mail_Storage_Exception
0210              */
0211             // require_once 'Zend/Mail/Storage/Exception.php';
0212             throw new Zend_Mail_Storage_Exception("folder $rootFolder not found");
0213         }
0214         return $currentFolder;
0215     }
0216 
0217     /**
0218      * select given folder
0219      *
0220      * folder must be selectable!
0221      *
0222      * @param Zend_Mail_Storage_Folder|string $globalName global name of folder or instance for subfolder
0223      * @return null
0224      * @throws Zend_Mail_Storage_Exception
0225      */
0226     public function selectFolder($globalName)
0227     {
0228         $this->_currentFolder = (string)$globalName;
0229 
0230         // getting folder from folder tree for validation
0231         $folder = $this->getFolders($this->_currentFolder);
0232 
0233         try {
0234             $this->_openMaildir($this->_rootdir . '.' . $folder->getGlobalName());
0235         } catch(Zend_Mail_Storage_Exception $e) {
0236             // check what went wrong
0237             if (!$folder->isSelectable()) {
0238                 /**
0239                  * @see Zend_Mail_Storage_Exception
0240                  */
0241                 // require_once 'Zend/Mail/Storage/Exception.php';
0242                 throw new Zend_Mail_Storage_Exception("{$this->_currentFolder} is not selectable", 0, $e);
0243             }
0244             // seems like file has vanished; rebuilding folder tree - but it's still an exception
0245             $this->_buildFolderTree($this->_rootdir);
0246             /**
0247              * @see Zend_Mail_Storage_Exception
0248              */
0249             // require_once 'Zend/Mail/Storage/Exception.php';
0250             throw new Zend_Mail_Storage_Exception('seems like the maildir has vanished, I\'ve rebuild the ' .
0251                                                          'folder tree, search for an other folder and try again', 0, $e);
0252         }
0253     }
0254 
0255     /**
0256      * get Zend_Mail_Storage_Folder instance for current folder
0257      *
0258      * @return Zend_Mail_Storage_Folder instance of current folder
0259      * @throws Zend_Mail_Storage_Exception
0260      */
0261     public function getCurrentFolder()
0262     {
0263         return $this->_currentFolder;
0264     }
0265 }