"Fossies" - the Fresh Open Source Software Archive 
Member "openmailadmin-1.0.1/inc/lib/imap/Cyrus_IMAP.php" (26 May 2007, 7593 Bytes) of package /linux/privat/old/openmailadmin-1.0.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "Cyrus_IMAP.php" see the
Fossies "Dox" file reference documentation.
1 <?php
2 /**
3 * This class encapsulates the administrative backend of cyrus-imapd.
4 * It does not rely on PHP's IMAP/POP classes and connects on demand.
5 *
6 * Relevant RFCs:
7 * - mailboxes: 3501
8 * - quota: 2047
9 * - ACL: 2086
10 */
11 class Cyrus_IMAP
12 implements IMAP_Administrator
13 {
14 private $sp = false; // holds the socket ressource, if connected
15 private $connection_data; // everything neccessary to connect to cyrus
16 private $version; // version of cyrus-imapd we have connected to
17 private $separator; // hierarchy separator
18 private $_logger = null; // logging facility, as defined in PEAR::Log
19
20 public $error_msg; // if an error occured, this variable will hold the error messages
21
22 function __construct(array $connection_data, Log $logger) {
23 $this->version = 'unknown';
24 $this->separator = null;
25 $this->connection_data = $connection_data;
26 $this->_logger = $logger;
27 }
28
29 function __destruct() {
30 $this->imap_logout();
31 }
32
33 private function imap_login() {
34 $this->_logger->debug('I: On opening socket for IMAP connection.');
35 $this->sp = fsockopen( $this->connection_data['HOST'],
36 $this->connection_data['PORT'],
37 $errno, $errstr);
38 $this->error_msg = $errstr;
39
40 if(!$this->sp) {
41 throw new ConfigurationErrorException('Socket for IMAP connection couldn\'t be opened: "'.$errstr.'"');
42 }
43
44 $txt = fgets($this->sp, 1024);
45 $this->_logger->debug('S: '.$txt);
46 if(preg_match('/IMAP4\sv(\d+\.\d+\.\d+)/', $txt, $arr)) {
47 $this->version = $arr[1];
48 $this->_logger->debug('I: Version of IMAP server is: "'.$this->version.'"');
49 }
50
51 $this->_logger->notice('C: -- on logging in with username "'.$this->connection_data['ADMIN'].'" --');
52 if(!$this->command('. login "'.$this->connection_data['ADMIN'].'" "'.$this->connection_data['PASS'].'"')) {
53 throw new ConfigurationErrorException('Login failed. Check your connection data.');
54 }
55 return true;
56 }
57
58 private function imap_logout() {
59 if($this->sp) {
60 $this->command('. logout');
61 fclose($this->sp);
62 }
63 return true;
64 }
65
66 public function getversion() {
67 if(!$this->sp) {
68 $this->imap_login();
69 }
70 return $this->version;
71 }
72
73 private function initial_gethierarchyseparator() {
74 $result = $this->command('. list "" ""');
75 $tmp = strstr($result['0'], '"');
76 $this->separator = $tmp{1};
77 $this->_logger->debug('I: Hierarchy separator is "'.$this->separator.'".');
78 return $this->separator;
79 }
80
81 public function gethierarchyseparator() {
82 if(is_null($this->separator)) {
83 $this->initial_gethierarchyseparator();
84 }
85 return $this->separator;
86 }
87
88 /**
89 * @param cmd Fully formatted command.
90 * @return Unless additional data is provided the return will be either true or false. On additional data an array will be returned.
91 */
92 private function command($cmd) {
93 if(!$this->sp) {
94 $this->imap_login();
95 }
96
97 $out = array();
98
99 fputs($this->sp, $cmd."\n");
100 if(!($cmd{2} == 'l' && strstr($cmd, '. login'))) {
101 $this->_logger->debug('C: '.$cmd);
102 }
103 do {
104 $row = fgets($this->sp, 1024);
105 $this->_logger->debug('S: '.$row);
106 $out[] = $row;
107 } while($row{0} != '.' && !feof($this->sp));
108
109 if(count($out) > 1) {
110 return $out;
111 } else {
112 if($row{2} != 'O') {
113 $this->error_msg = substr($row, 5);
114 }
115 return ($row{2} == 'O');
116 }
117 }
118
119 public function createmb($mailboxname) {
120 return $this->command('. create "'.$mailboxname.'"');
121 }
122
123 public function deletemb($mailboxname) {
124 // we have to grant ourselve admin-rights on the mailbox before deleting it
125 $this->setacl($mailboxname, $this->connection_data['ADMIN'], $this->get_acl_letters());
126 return $this->command('. delete "'.$mailboxname.'"');
127 }
128
129 public function renamemb($oldname, $newname) {
130 // This is for preserving already granted rights.
131 $oldacl = $this->getacl($oldname);
132
133 $this->setacl($oldname, $this->connection_data['ADMIN'], $this->get_acl_letters());
134 $out = $this->command('. rename "'.$oldname.'" "'.$newname.'"');
135
136 if(isset($oldacl[$this->connection_data['ADMIN']])) {
137 $this->setacl($newname, $this->connection_data['ADMIN'], $oldacl[$this->connection_data['ADMIN']]);
138 } else {
139 $this->deleteacl($newname, $this->connection_data['ADMIN']);
140 }
141
142 return $out;
143 }
144
145 public function getmailboxes($ref = '', $pat = '*') {
146 $result = array();
147 foreach($this->command('. list "'.$ref.'" '.$pat) as $folder) {
148 if(preg_match('/\*\sLIST\s\((.*)\)\s\"(.*?)\"\s\"(.*?)\"/', $folder, $arr)) {
149 $result[]
150 = array('attributes' => $arr[1],
151 'delimiter' => $arr[2],
152 'name' => trim($arr[3]));
153 }
154 }
155 return $result;
156 }
157
158 public function getquota($mailboxname) {
159 $out = $this->command('. getquota "'.$mailboxname.'"');
160 if($out == false) {
161 // quota not set, thus unlimited
162 return new Quota();
163 } else if(is_array($out)
164 && preg_match('/\*\sQUOTA.*\(\w*\s(\d+)\s(\d+)\)/i', $out[0], $arr)) {
165 return new Quota($arr[1], $arr[2]);
166 }
167 return new Quota();
168 }
169
170 public function get_users_quota($username) {
171 return $this->getquota($this->format_user($username));
172 }
173
174 /**
175 * @param storage Partition on which quota has to be set. May be ignored.
176 * @see IMAP_Administrator::setquota
177 */
178 public function setquota($mailboxname, $quota, $storage = 'STORAGE') {
179 if(is_numeric($quota)) {
180 return $this->command('. setquota "'.$mailboxname.'" ('.$storage.' '.intval($quota).')');
181 }
182 return false;
183 }
184
185 /**
186 * @returns Array with all available rights as letters.
187 */
188 public function get_acl_available() {
189 $assumed = array('l', 'r', 's', 'w', 'i', 'p', 'c', 'd', 'a');
190 if(version_compare($this->getversion(), '2.3.0', '>=')) {
191 $assumed = array('l', 'r', 's', 'w', 'i', 'p', 'k', 'x', 't', 'e', 'c', 'd', 'a');
192 }
193 return $assumed;
194 }
195
196 /**
197 * @returns String with all available letters which represent rights.
198 */
199 private function get_acl_letters() {
200 return implode('', $this->get_acl_available());
201 }
202
203 public function getacl($mailboxname) {
204 $reult = array();
205 $arr = array();
206 $out = $this->command('. getacl "'.$mailboxname.'"');
207
208 if($out === false) {
209 return array();
210 }
211
212 // In order to prevent confusion due to mailboxnames which may
213 // look like ACL strings we have to eliminate the mailboxnames.
214 $out = str_replace($mailboxname, '##', $out);
215
216 if(preg_match('/\*\sACL\s[^\s]*\s(.*)/', $out[0], $arr)) {
217 if(preg_match_all('/([^\s]*)\s(['.$this->get_acl_letters().']*)\s?/', $arr[1], $arr)) {
218 $result = array_combine($arr[1], $arr[2]);
219 }
220 }
221
222 return $result;
223 }
224
225 public function setacl($mailboxname, $user, $ACL) {
226 return $this->command('. setacl "'.$mailboxname.'" "'.$user.'" '.$ACL);
227 }
228
229 private function deleteacl($mailboxname, $user) {
230 return $this->command('. deleteacl "'.$mailboxname.'" "'.$user.'"');
231 }
232
233 public function format_user($username, $folder = null) {
234 $ret = '';
235 $this->gethierarchyseparator();
236 if(is_null($folder)) {
237 if(isset($this->connection_data['VDOM']) && $this->connection_data['VDOM'] != '') {
238 $ret = $this->connection_data['VDOM'].'!user'.$this->separator.$username;
239 } else {
240 $ret = 'user'.$this->separator.$username;
241 }
242 } else {
243 $ret = $this->format_user($username).$this->separator.$folder;
244 }
245 $this->_logger->notice('I: ("'.$username.'", '.(is_null($folder) ? 'null' : '"'.$folder.'"').') has been formatted as "'.$ret.'"');
246 return $ret;
247 }
248
249 public function is_valid_username($username) {
250 if($this->gethierarchyseparator() == '.') {
251 return preg_match('/^[a-z0-9]+(?:(?<![_-])[_-][a-z0-9]+)*$/i', $username);
252 } else {
253 return preg_match('/^[a-z0-9]+(?:(?<![_.-])[_.-][a-z0-9]+)*$/i', $username);
254 }
255 }
256
257 }
258 ?>