1<?php 2/** 3 * EGroupware Api: Support for Cyrus IMAP 4 * 5 * @link http://www.stylite.de 6 * @package api 7 * @subpackage mail 8 * @author Ralf Becker <rb@stylite.de> 9 * @author Klaus Leithoff <kl@stylite.de> 10 * @author Lars Kneschke 11 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License 12 * @version $Id$ 13 */ 14 15namespace EGroupware\Api\Mail\Imap; 16 17use EGroupware\Api\Mail; 18 19use Horde_Imap_Client_Exception; 20 21/** 22 * Manages connection to Cyrus IMAP server 23 */ 24class Cyrus extends Mail\Imap 25{ 26 /** 27 * Label shown in EMailAdmin 28 */ 29 const DESCRIPTION = 'Cyrus'; 30 31 /** 32 * Capabilities of this class (pipe-separated): default, sieve, admin, logintypeemail 33 */ 34 const CAPABILITIES = 'default|sieve|timedsieve|admin|logintypeemail'; 35 36 /** 37 * prefix for groupnames, when using groups in ACL Management 38 */ 39 const ACL_GROUP_PREFIX = 'group:'; 40 41 // mailbox delimiter 42 var $mailboxDelimiter = '.'; 43 44 // mailbox prefix 45 var $mailboxPrefix = ''; 46 47 /** 48 * Updates an account 49 * 50 * @param array $_hookValues only value for key 'account_lid' and 'account_passwd' is used 51 */ 52 function addAccount($_hookValues) 53 { 54 return $this->updateAccount($_hookValues); 55 } 56 57 /** 58 * Delete an account 59 * 60 * @param array $_hookValues only value for key 'account_lid' is used 61 */ 62 function deleteAccount($_hookValues) 63 { 64 // some precausion to really delete just _one_ account 65 if (strpos($_hookValues['account_lid'],'%') !== false || 66 strpos($_hookValues['account_lid'],'*') !== false) 67 { 68 return false; 69 } 70 return !!$this->deleteUsers($_hookValues['account_lid']); 71 } 72 73 /** 74 * Delete multiple (user-)mailboxes via a wildcard, eg. '%' for whole domain 75 * 76 * Domain is the configured domain and it uses the Cyrus admin user 77 * 78 * @return string $username='%' username containing wildcards, default '%' for all users of a domain 79 * @return int|boolean number of deleted mailboxes on success or false on error 80 */ 81 function deleteUsers($username='%') 82 { 83 if(!$this->acc_imap_administration || empty($username)) 84 { 85 return false; 86 } 87 88 // we need a admin connection 89 $this->adminConnection(); 90 91 $mailboxName = $this->getUserMailboxString($username); 92 93 try { 94 $mboxes = (array)$this->getMailboxes($mailboxName, 1); 95 //error_log(__METHOD__."('$username') getMailboxes('$reference','$username$restriction') = ".array2string($mboxes)); 96 97 foreach(array_keys($mboxes) as $mbox) 98 { 99 // give the admin account the rights to delete this mailbox 100 $this->setACL($mbox, $this->acc_imap_admin_username, array('rights' => 'aeiklprstwx')); 101 $this->deleteMailbox($mbox); 102 } 103 } 104 catch(Horde_Imap_Client_Exception $e) { 105 _egw_log_exception($e); 106 $this->disconnect(); 107 return false; 108 } 109 $this->disconnect(); 110 111 return count($mboxes); 112 } 113 114 /** 115 * returns information about a user 116 * currently only supported information is the current quota 117 * 118 * @param string $_username 119 * @return array userdata 120 */ 121 function getUserData($_username) 122 { 123 // no need to switch to admin-connection for reading quota of current user 124 if ($_username !== $GLOBALS['egw_info']['user']['account_lid']) $this->adminConnection(); 125 $userData = array(); 126 127 if(($quota = $this->getQuotaByUser($_username,'ALL'))) 128 { 129 $userData['quotaLimit'] = (int)($quota['limit'] / 1024); 130 $userData['quotaUsed'] = (int)($quota['usage'] / 1024); 131 } 132 //error_log(__LINE__.': '.__METHOD__."('$_username') quota=".array2string($quota).' returning '.array2string($userData)); 133 134 if ($_username !== $GLOBALS['egw_info']['user']['account_lid']) $this->disconnect(); 135 136 return $userData; 137 } 138 139 /** 140 * Set information about a user 141 * currently only supported information is the current quota 142 * 143 * @param string $_username 144 * @param int $_quota 145 */ 146 function setUserData($_username, $_quota) 147 { 148 if(!$this->acc_imap_administration) 149 { 150 return false; 151 } 152 153 // create a admin connection 154 $this->adminConnection(); 155 156 $mailboxName = $this->getUserMailboxString($_username); 157 158 $this->setQuota($mailboxName, array('STORAGE' => (int)$_quota > 0 ? (int)$_quota*1024 : -1)); 159 160 $this->disconnect(); 161 162 return true; 163 } 164 165 /** 166 * Updates an account 167 * 168 * @param array $_hookValues only value for key 'account_lid' and 'account_passwd' is used 169 */ 170 function updateAccount($_hookValues) 171 { 172 if(!$this->acc_imap_administration) 173 { 174 return false; 175 } 176 177 // we need a admin connection 178 $this->adminConnection(); 179 180 // create the mailbox, with the account_lid, as it is passed from the hook values (gets transformed there if needed) 181 $mailboxName = $this->getUserMailboxString($_hookValues['account_lid'], $mailboxName); 182 // make sure we use the correct username here. 183 $username = $this->getMailBoxUserName($_hookValues['account_lid']); 184 $folderInfo = $this->getMailboxes('', $mailboxName, true); 185 if(empty($folderInfo)) 186 { 187 try { 188 $this->createMailbox($mailboxName); 189 $this->setACL($mailboxName, $username, array('rights' => 'aeiklprstwx')); 190 // create defined folders and subscribe them (have to use user-credentials to subscribe!) 191 $userimap = null; 192 foreach($this->params as $name => $value) 193 { 194 if (substr($name, 0, 11) == 'acc_folder_' && !empty($value)) 195 { 196 if (!isset($userimap)) 197 { 198 $params = $this->params; 199 $params['acc_imap_username'] = $username; 200 $params['acc_imap_password'] = $_hookValues['account_passwd']; 201 $userimap = new Cyrus($params); 202 } 203 $userimap->createMailbox($value); 204 $userimap->subscribeMailbox($value); 205 } 206 } 207 if (isset($userimap)) $userimap->logout(); 208 } 209 catch(Horde_Imap_Client_Exception $e) { 210 _egw_log_exception($e); 211 } 212 } 213 $this->disconnect(); 214 } 215 216 /** 217 * Proxy former bosieve methods to internal Mail\Sieve instance 218 * 219 * @param string $name 220 * @param array $params 221 * @throws Exception 222 */ 223 public function __call($name,array $params=null) 224 { 225 switch($name) 226 { 227 case 'setRules': // call setRules with 3. param of true, to enable utf7imap fileinto for Cyrus 228 $params += array(null, null, true); 229 break; 230 } 231 return parent::__call($name, $params); 232 } 233} 234