Fix from Seth Randall. The range was 1 to large.
[squirrelmail.git] / functions / imap_mailbox.php
CommitLineData
59177427 1<?php
35586184 2/**
3 * imap_mailbox.php
4 *
82d304a0 5 * Copyright (c) 1999-2004 The SquirrelMail Project Team
35586184 6 * Licensed under the GNU GPL. For full terms see the file COPYING.
7 *
8 * This impliments all functions that manipulate mailboxes
9 *
eb19bc67 10 * @version $Id$
d6c32258 11 * @package squirrelmail
eb19bc67 12 * @subpackage imap
35586184 13 */
d6c32258 14
15/** UTF7 support */
334a77f8 16require_once(SM_PATH . 'functions/imap_utf7_local.php');
17
3411d4ec 18global $boxesnew;
1da22cda 19
d6c32258 20/**
21 * Mailboxes class
4669e892 22 *
23 * FIXME. This class should be extracted and placed in a separate file that
d6c32258 24 * can be included before we start the session. That makes caching of the tree
4669e892 25 * possible. On a refresh mailboxes from left_main.php the only function that
26 * should be called is the sqimap_get_status_mbx_tree. In case of subscribe
27 * / rename / delete / new we have to create methods for adding/changing the
d6c32258 28 * mailbox in the mbx_tree without the need for a refresh.
29 * @package squirrelmail
1eb028a9 30*/
31
60b5724d 32class mailboxes {
86c2763d 33 var $mailboxname_full = '', $mailboxname_sub= '', $is_noselect = false, $is_noinferiors = false,
ff245fbd 34 $is_special = false, $is_root = false, $is_inbox = false, $is_sent = false,
4669e892 35 $is_trash = false, $is_draft = false, $mbxs = array(),
ff245fbd 36 $unseen = false, $total = false;
37
38 function addMbx($mbx, $delimiter, $start, $specialfirst) {
39 $ary = explode($delimiter, $mbx->mailboxname_full);
ae7df16e 40 $mbx_parent =& $this;
ff245fbd 41 for ($i = $start, $c = count($ary)-1; $i < $c; $i++) {
ae7df16e 42 $mbx_childs =& $mbx_parent->mbxs;
ff245fbd 43 $found = false;
44 if ($mbx_childs) {
45 foreach ($mbx_childs as $key => $parent) {
46 if ($parent->mailboxname_sub == $ary[$i]) {
ae7df16e 47 $mbx_parent =& $mbx_parent->mbxs[$key];
ff245fbd 48 $found = true;
ae7df16e 49 break;
ff245fbd 50 }
51 }
52 }
53 if (!$found) {
54 $no_select_mbx = new mailboxes();
55 if (isset($mbx_parent->mailboxname_full) && $mbx_parent->mailboxname_full != '') {
56 $no_select_mbx->mailboxname_full = $mbx_parent->mailboxname_full.$delimiter.$ary[$i];
57 } else {
58 $no_select_mbx->mailboxname_full = $ary[$i];
59 }
587ec647 60 $no_select_mbx->mailboxname_sub = $ary[$i];
ff245fbd 61 $no_select_mbx->is_noselect = true;
62 $mbx_parent->mbxs[] = $no_select_mbx;
63 $i--;
64 }
65 }
66 $mbx_parent->mbxs[] = $mbx;
67 if ($mbx->is_special && $specialfirst) {
68 usort($mbx_parent->mbxs, 'sortSpecialMbx');
69 }
70 }
60b5724d 71}
72
73function sortSpecialMbx($a, $b) {
74 if ($a->is_inbox) {
ff245fbd 75 $acmp = '0'. $a->mailboxname_full;
60b5724d 76 } else if ($a->is_special) {
ff245fbd 77 $acmp = '1'. $a->mailboxname_full;
60b5724d 78 } else {
ff245fbd 79 $acmp = '2' . $a->mailboxname_full;
80 }
60b5724d 81 if ($b->is_inbox) {
ff245fbd 82 $bcmp = '0'. $b->mailboxname_full;
60b5724d 83 }else if ($b->is_special) {
ff245fbd 84 $bcmp = '1' . $b->mailboxname_full;
60b5724d 85 } else {
ff245fbd 86 $bcmp = '2' . $b->mailboxname_full;
60b5724d 87 }
4669e892 88 return strnatcasecmp($acmp, $bcmp);
ff245fbd 89}
60b5724d 90
86c2763d 91function compact_mailboxes_response($ary)
92{
93 /*
94 * Workaround for mailboxes returned as literal
4669e892 95 * FIXME : Doesn't work if the mailbox name is multiple lines
86c2763d 96 * (larger then fgets buffer)
97 */
98 for ($i = 0, $iCnt=count($ary); $i < $iCnt; $i++) {
99 if (isset($ary[$i + 1]) && substr($ary[$i], -3) == "}\r\n") {
100 if (ereg("^(\\* [A-Z]+.*)\\{[0-9]+\\}([ \n\r\t]*)$",
101 $ary[$i], $regs)) {
102 $ary[$i] = $regs[1] . '"' . addslashes(trim($ary[$i+1])) . '"' . $regs[2];
103 array_splice($ary, $i+1, 2);
104 }
105 }
106 }
107 /* remove duplicates and ensure array is contiguous */
108 return array_values(array_unique($ary));
109}
110
48af4b64 111/**
112 * Extract the mailbox name from an untagged LIST (7.2.2) or LSUB (7.2.3) answer
113 * (LIST|LSUB) (<Flags list>) (NIL|"<separator atom>") <mailbox name string>\r\n
114 * mailbox name in quoted string MUST be unquoted and stripslashed (sm API)
115 */
bac13dd7 116function find_mailbox_name($line)
117{
118 if (preg_match('/^\* (?:LIST|LSUB) \([^\)]*\) (?:NIL|\"[^\"]*\") ([^\r\n]*)[\r\n]*$/i', $line, $regs)) {
119 if (substr($regs[1], 0, 1) == '"')
120 return stripslashes(substr($regs[1], 1, -1));
121 return $regs[1];
122 }
123 return '';
124}
125
48af4b64 126/**
127 * @return bool whether this is a Noselect mailbox.
128 */
f73348a3 129function check_is_noselect ($lsub_line) {
3698bd49 130 return preg_match("/^\* (LSUB|LIST) \([^\)]*\\\\Noselect[^\)]*\)/i", $lsub_line);
79e07c7e 131}
132
48af4b64 133/**
134 * @return bool whether this is a Noinferiors mailbox.
135 */
86c2763d 136function check_is_noinferiors ($lsub_line) {
137 return preg_match("/^\* (LSUB|LIST) \([^\)]*\\\\Noinferiors[^\)]*\)/i", $lsub_line);
138}
139
97b1248c 140/**
141 * If $haystack is a full mailbox name, and $needle is the mailbox
142 * separator character, returns the second last part of the full
143 * mailbox name (i.e. the mailbox's parent mailbox)
144 */
145function readMailboxParent($haystack, $needle) {
97b1248c 146 if ($needle == '') {
147 $ret = '';
148 } else {
149 $parts = explode($needle, $haystack);
150 $elem = array_pop($parts);
151 while ($elem == '' && count($parts)) {
152 $elem = array_pop($parts);
153 }
154 $ret = join($needle, $parts);
155 }
156 return( $ret );
157}
158
4669e892 159/**
6a8e7cae 160 * Check if $subbox is below the specified $parentbox
161 */
162function isBoxBelow( $subbox, $parentbox ) {
cef054e4 163 global $delimiter;
4669e892 164 /*
165 * Eliminate the obvious mismatch, where the
6a8e7cae 166 * subfolder path is shorter than that of the potential parent
167 */
168 if ( strlen($subbox) < strlen($parentbox) ) {
169 return false;
170 }
cef054e4 171 /* check for delimiter */
172 if (!substr($parentbox,-1) == $delimiter) {
173 $parentbox.=$delimiter;
174 }
175 if (substr($subbox,0,strlen($parentbox)) == $parentbox) {
176 return true;
177 } else {
178 return false;
179 }
1e18bf95 180}
181
48af4b64 182/**
183 * Defines special mailboxes: given a mailbox name, it checks if this is a
184 * "special" one: INBOX, Trash, Sent or Draft.
185 */
1e18bf95 186function isSpecialMailbox( $box ) {
90de1755 187 $ret = ( (strtolower($box) == 'inbox') ||
6a8e7cae 188 isTrashMailbox($box) || isSentMailbox($box) || isDraftMailbox($box) );
90de1755 189
2586d588 190 if ( !$ret ) {
5576644b 191 $ret = boolean_hook_function('special_mailbox',$box,1);
2586d588 192 }
3411d4ec 193 return $ret;
90de1755 194}
195
48af4b64 196/**
197 * @return bool whether this is a Trash folder
198 */
6a8e7cae 199function isTrashMailbox ($box) {
200 global $trash_folder, $move_to_trash;
201 return $move_to_trash && $trash_folder &&
202 ( $box == $trash_folder || isBoxBelow($box, $trash_folder) );
203}
204
48af4b64 205/**
206 * @return bool whether this is a Sent folder
207 */
6a8e7cae 208function isSentMailbox($box) {
209 global $sent_folder, $move_to_sent;
210 return $move_to_sent && $sent_folder &&
211 ( $box == $sent_folder || isBoxBelow($box, $sent_folder) );
212}
213
48af4b64 214/**
215 * @return bool whether this is a Draft folder
216 */
6a8e7cae 217function isDraftMailbox($box) {
218 global $draft_folder, $save_as_draft;
219 return $save_as_draft &&
220 ( $box == $draft_folder || isBoxBelow($box, $draft_folder) );
221}
222
48af4b64 223/**
224 * Expunges a mailbox, ie. delete all contents.
225 */
8f6505f6 226function sqimap_mailbox_expunge ($imap_stream, $mailbox, $handle_errors = true, $id='') {
06b5c3ff 227 if ($id) {
ff245fbd 228 if (is_array($id)) {
229 $id = sqimap_message_list_squisher($id);
230 }
231 $id = ' '.$id;
6201339c 232 $uid = TRUE;
06b5c3ff 233 } else {
ff245fbd 234 $uid = false;
8f6505f6 235 }
06b5c3ff 236 $read = sqimap_run_command($imap_stream, 'EXPUNGE'.$id, $handle_errors,
237 $response, $message, $uid);
63240b90 238 $cnt = 0;
ff245fbd 239
240 if (is_array($read)) {
63240b90 241 foreach ($read as $r) {
ff245fbd 242 if (preg_match('/^\*\s[0-9]+\sEXPUNGE/AUi',$r,$regs)) {
243 $cnt++;
244 }
63240b90 245 }
8f6505f6 246 }
ff245fbd 247 return $cnt;
43b698c7 248}
249
ffb776c4 250
653ff1e6 251/**
e0e30169 252 * Expunge specified message
4669e892 253 *
e0e30169 254 * We'll use this wrapper function to
653ff1e6 255 * remove the message with the matching UID .. the order
256 * won't be changed - the array element for the message
257 * will just be removed.
258 */
653ff1e6 259
e0e30169 260function sqimap_mailbox_expunge_dmn($imapConnection, &$aMailbox, $message_id) {
261 $cnt = 0;
653ff1e6 262
e0e30169 263 if ($aMailbox['AUTO_EXPUNGE']) {
264 $cnt = sqimap_mailbox_expunge($imapConnection, $aMailbox['NAME'], true);
26e90c74 265 } else {
266 return $cnt;
653ff1e6 267 }
ffb776c4 268 $error = '';
e0e30169 269 $message_id = (int) $message_id; // we use strickt array_search
270 if (is_array($aMailbox['UIDSET'])) {
271 $key = array_search($message_id,$aMailbox['UIDSET'],true);
ffb776c4 272 if ($key !== false) {
e0e30169 273 unset($aMailbox['UIDSET'][$key]);
274 $aMailbox['UIDSET'] = array_values($aMailbox['UIDSET']);
275 // adapt the exists count to avoid triggering of a new sort
276 $aMailbox['EXISTS'] -= 1;
26e90c74 277 } else {
e0e30169 278 $aMailbox['UIDSET'] = get_sorted_msgs_list($imapConnection,$aMailbox,$error);
fe6efa94 279 }
26e90c74 280 } else {
e0e30169 281 $aMailbox['UIDSET'] = get_sorted_msgs_list($imapConnection,$aMailbox,$error);
653ff1e6 282 }
e0e30169 283 sqsession_register($aMailbox,'aLastSelectedMailbox');
284 sqsession_register($aMailbox['UIDSET'],'server_sort_array'); //fix me, use aMailbox instead
b0b9d81c 285 return $cnt;
653ff1e6 286}
287
48af4b64 288/**
289 * Checks whether or not the specified mailbox exists
290 */
1da22cda 291function sqimap_mailbox_exists ($imap_stream, $mailbox) {
247f700e 292 if (!isset($mailbox) || empty($mailbox)) {
43b698c7 293 return false;
294 }
568cb884 295 $mbx = sqimap_run_command($imap_stream, 'LIST "" ' . sqimap_encode_mailbox_name($mailbox),
3411d4ec 296 true, $response, $message);
43b698c7 297 return isset($mbx[0]);
298}
299
48af4b64 300/**
301 * Selects a mailbox
302 */
e4c6fe41 303function sqimap_mailbox_select ($imap_stream, $mailbox) {
ff245fbd 304 if ($mailbox == 'None') {
43b698c7 305 return;
306 }
f69feefe 307
568cb884 308 $read = sqimap_run_command($imap_stream, 'SELECT ' . sqimap_encode_mailbox_name($mailbox),
3411d4ec 309 true, $response, $message);
e4c6fe41 310 $result = array();
ff245fbd 311 for ($i = 0, $cnt = count($read); $i < $cnt; $i++) {
e4c6fe41 312 if (preg_match('/^\*\s+OK\s\[(\w+)\s(\w+)\]/',$read[$i], $regs)) {
ff245fbd 313 $result[strtoupper($regs[1])] = $regs[2];
314 } else if (preg_match('/^\*\s([0-9]+)\s(\w+)/',$read[$i], $regs)) {
315 $result[strtoupper($regs[2])] = $regs[1];
316 } else {
317 if (preg_match("/PERMANENTFLAGS(.*)/i",$read[$i], $regs)) {
318 $regs[1]=trim(preg_replace ( array ("/\(/","/\)/","/\]/") ,'', $regs[1])) ;
4669e892 319 $result['PERMANENTFLAGS'] = explode(' ',strtolower($regs[1]));
ff245fbd 320 } else if (preg_match("/FLAGS(.*)/i",$read[$i], $regs)) {
321 $regs[1]=trim(preg_replace ( array ("/\(/","/\)/") ,'', $regs[1])) ;
4669e892 322 $result['FLAGS'] = explode(' ',strtolower($regs[1]));
ff245fbd 323 }
324 }
e4c6fe41 325 }
4669e892 326 if (!isset($result['PERMANENTFLAGS'])) {
327 $result['PERMANENTFLAGS'] = $result['FLAGS'];
328 }
e4c6fe41 329 if (preg_match('/^\[(.+)\]/',$message, $regs)) {
4669e892 330 $result['RIGHTS']=strtoupper($regs[1]);
e4c6fe41 331 }
f69feefe 332
e4c6fe41 333 return $result;
43b698c7 334}
335
48af4b64 336/**
337 * Creates a folder.
338 */
3411d4ec 339function sqimap_mailbox_create ($imap_stream, $mailbox, $type) {
43b698c7 340 global $delimiter;
341 if (strtolower($type) == 'noselect') {
3411d4ec 342 $mailbox .= $delimiter;
43b698c7 343 }
e429f014 344
48af4b64 345 $read_ary = sqimap_run_command($imap_stream, 'CREATE ' .
346 sqimap_encode_mailbox_name($mailbox),
3411d4ec 347 true, $response, $message);
43b698c7 348 sqimap_subscribe ($imap_stream, $mailbox);
349}
350
48af4b64 351/**
352 * Subscribes to an existing folder.
353 */
852abae7 354function sqimap_subscribe ($imap_stream, $mailbox,$debug=true) {
48af4b64 355 $read_ary = sqimap_run_command($imap_stream, 'SUBSCRIBE ' .
356 sqimap_encode_mailbox_name($mailbox),
852abae7 357 $debug, $response, $message);
43b698c7 358}
359
48af4b64 360/**
361 * Unsubscribes from an existing folder
362 */
3411d4ec 363function sqimap_unsubscribe ($imap_stream, $mailbox) {
48af4b64 364 $read_ary = sqimap_run_command($imap_stream, 'UNSUBSCRIBE ' .
365 sqimap_encode_mailbox_name($mailbox),
e2e8b92b 366 false, $response, $message);
43b698c7 367}
368
48af4b64 369/**
370 * Deletes the given folder
371 */
3411d4ec 372function sqimap_mailbox_delete ($imap_stream, $mailbox) {
78cc4b12 373 global $data_dir, $username;
e2e8b92b 374 sqimap_unsubscribe ($imap_stream, $mailbox);
48af4b64 375 $read_ary = sqimap_run_command($imap_stream, 'DELETE ' .
376 sqimap_encode_mailbox_name($mailbox),
3411d4ec 377 true, $response, $message);
e2e8b92b 378 if ($response !== 'OK') {
379 // subscribe again
380 sqimap_subscribe ($imap_stream, $mailbox);
381 } else {
382 do_hook_function('rename_or_delete_folder', $args = array($mailbox, 'delete', ''));
383 removePref($data_dir, $username, "thread_$mailbox");
384 }
43b698c7 385}
386
48af4b64 387/**
388 * Determines if the user is subscribed to the folder or not
389 */
1da22cda 390function sqimap_mailbox_is_subscribed($imap_stream, $folder) {
1da22cda 391 $boxesall = sqimap_mailbox_list ($imap_stream);
392 foreach ($boxesall as $ref) {
43b698c7 393 if ($ref['unformatted'] == $folder) {
3411d4ec 394 return true;
43b698c7 395 }
396 }
397 return false;
398}
399
48af4b64 400/**
401 * Renames a mailbox.
402 */
1c52ba77 403function sqimap_mailbox_rename( $imap_stream, $old_name, $new_name ) {
3411d4ec 404 if ( $old_name != $new_name ) {
78cc4b12 405 global $delimiter, $imap_server_type, $data_dir, $username;
1c52ba77 406 if ( substr( $old_name, -1 ) == $delimiter ) {
407 $old_name = substr( $old_name, 0, strlen( $old_name ) - 1 );
408 $new_name = substr( $new_name, 0, strlen( $new_name ) - 1 );
409 $postfix = $delimiter;
1c52ba77 410 } else {
411 $postfix = '';
1c52ba77 412 }
68f2ce7a 413
648713af 414 $boxesall = sqimap_mailbox_list($imap_stream);
48af4b64 415 $cmd = 'RENAME ' . sqimap_encode_mailbox_name($old_name) .
416 ' ' . sqimap_encode_mailbox_name($new_name);
3411d4ec 417 $data = sqimap_run_command($imap_stream, $cmd, true, $response, $message);
1c52ba77 418 sqimap_unsubscribe($imap_stream, $old_name.$postfix);
68f2ce7a 419 $oldpref = getPref($data_dir, $username, 'thread_'.$old_name.$postfix);
420 removePref($data_dir, $username, 'thread_'.$old_name.$postfix);
1c52ba77 421 sqimap_subscribe($imap_stream, $new_name.$postfix);
68f2ce7a 422 setPref($data_dir, $username, 'thread_'.$new_name.$postfix, $oldpref);
e429f014 423 do_hook_function('rename_or_delete_folder',$args = array($old_name, 'rename', $new_name));
648713af 424 $l = strlen( $old_name ) + 1;
425 $p = 'unformatted';
68f2ce7a 426
ff245fbd 427 foreach ($boxesall as $box) {
428 if (substr($box[$p], 0, $l) == $old_name . $delimiter) {
648713af 429 $new_sub = $new_name . $delimiter . substr($box[$p], $l);
430 if ($imap_server_type == 'cyrus') {
68f2ce7a 431 $cmd = 'RENAME "' . $box[$p] . '" "' . $new_sub . '"';
3411d4ec 432 $data = sqimap_run_command($imap_stream, $cmd, true,
648713af 433 $response, $message);
1c52ba77 434 }
648713af 435 sqimap_unsubscribe($imap_stream, $box[$p]);
68f2ce7a 436 $oldpref = getPref($data_dir, $username, 'thread_'.$box[$p]);
437 removePref($data_dir, $username, 'thread_'.$box[$p]);
648713af 438 sqimap_subscribe($imap_stream, $new_sub);
68f2ce7a 439 setPref($data_dir, $username, 'thread_'.$new_sub, $oldpref);
440 do_hook_function('rename_or_delete_folder',
3411d4ec 441 $args = array($box[$p], 'rename', $new_sub));
1c52ba77 442 }
443 }
1c52ba77 444 }
1c52ba77 445}
43b698c7 446
48af4b64 447/**
86c2763d 448 * Formats a mailbox into parts for the $boxesall array
3411d4ec 449 *
86c2763d 450 * The parts are:
3411d4ec 451 *
452 * raw - Raw LIST/LSUB response from the IMAP server
453 * formatted - nicely formatted folder name
454 * unformatted - unformatted, but with delimiter at end removed
455 * unformatted-dm - folder name as it appears in raw response
456 * unformatted-disp - unformatted without $folder_prefix
457 */
458function sqimap_mailbox_parse ($line, $line_lsub) {
43b698c7 459 global $folder_prefix, $delimiter;
3411d4ec 460
43b698c7 461 /* Process each folder line */
cef054e4 462 for ($g = 0, $cnt = count($line); $g < $cnt; ++$g) {
43b698c7 463 /* Store the raw IMAP reply */
464 if (isset($line[$g])) {
e429f014 465 $boxesall[$g]['raw'] = $line[$g];
ff245fbd 466 } else {
e429f014 467 $boxesall[$g]['raw'] = '';
43b698c7 468 }
3411d4ec 469
43b698c7 470 /* Count number of delimiters ($delimiter) in folder name */
86c2763d 471 $mailbox = /*trim(*/$line_lsub[$g]/*)*/;
ff245fbd 472 $dm_count = substr_count($mailbox, $delimiter);
43b698c7 473 if (substr($mailbox, -1) == $delimiter) {
3411d4ec 474 /* If name ends in delimiter, decrement count by one */
475 $dm_count--;
43b698c7 476 }
3411d4ec 477
478 /* Format folder name, but only if it's a INBOX.* or has a parent. */
1da22cda 479 $boxesallbyname[$mailbox] = $g;
43b698c7 480 $parentfolder = readMailboxParent($mailbox, $delimiter);
481 if ( (strtolower(substr($mailbox, 0, 5)) == "inbox") ||
482 (substr($mailbox, 0, strlen($folder_prefix)) == $folder_prefix) ||
ff245fbd 483 (isset($boxesallbyname[$parentfolder]) &&
484 (strlen($parentfolder) > 0) ) ) {
485 $indent = $dm_count - (substr_count($folder_prefix, $delimiter));
43b698c7 486 if ($indent > 0) {
ff245fbd 487 $boxesall[$g]['formatted'] = str_repeat('&nbsp;&nbsp;', $indent);
488 } else {
1da22cda 489 $boxesall[$g]['formatted'] = '';
43b698c7 490 }
447b2166 491 $boxesall[$g]['formatted'] .= imap_utf7_decode_local(readShortMailboxName($mailbox, $delimiter));
ff245fbd 492 } else {
447b2166 493 $boxesall[$g]['formatted'] = imap_utf7_decode_local($mailbox);
43b698c7 494 }
90de1755 495
1da22cda 496 $boxesall[$g]['unformatted-dm'] = $mailbox;
43b698c7 497 if (substr($mailbox, -1) == $delimiter) {
8e9e8afa 498 $mailbox = substr($mailbox, 0, strlen($mailbox) - 1);
43b698c7 499 }
1da22cda 500 $boxesall[$g]['unformatted'] = $mailbox;
43b698c7 501 if (substr($mailbox,0,strlen($folder_prefix))==$folder_prefix) {
631b9da3 502 $mailbox = substr($mailbox, strlen($folder_prefix));
43b698c7 503 }
1da22cda 504 $boxesall[$g]['unformatted-disp'] = $mailbox;
505 $boxesall[$g]['id'] = $g;
90de1755 506
1da22cda 507 $boxesall[$g]['flags'] = array();
43b698c7 508 if (isset($line[$g])) {
36dfb0c9 509 ereg("\(([^)]*)\)",$line[$g],$regs);
4669e892 510 // FIXME Flags do contain the \ character. \NoSelect \NoInferiors
5c300c60 511 // and $MDNSent <= last one doesn't have the \
512 // It's better to follow RFC3501 instead of using our own naming.
1a7e1e97 513 $flags = trim(strtolower(str_replace('\\', '',$regs[1])));
43b698c7 514 if ($flags) {
1da22cda 515 $boxesall[$g]['flags'] = explode(' ', $flags);
43b698c7 516 }
517 }
518 }
1da22cda 519 return $boxesall;
43b698c7 520}
521
48af4b64 522/**
be2d5495 523 * Returns list of options (to be echoed into select statement
524 * based on available mailboxes and separators
525 * Caller should surround options with <SELECT..> </SELECT> and
526 * any formatting.
527 * $imap_stream - $imapConnection to query for mailboxes
528 * $show_selected - array containing list of mailboxes to pre-select (0 if none)
529 * $folder_skip - array of folders to keep out of option list (compared in lower)
530 * $boxes - list of already fetched boxes (for places like folder panel, where
531 * you know these options will be shown 3 times in a row.. (most often unset).
59a8e3e8 532 * $flag - flag to check for in mailbox flags, used to filter out mailboxes.
533 * 'noselect' by default to remove unselectable mailboxes.
534 * 'noinferiors' used to filter out folders that can not contain subfolders.
535 * NULL to avoid flag check entirely.
d0928dd5 536 * NOTE: noselect and noiferiors are used internally. The IMAP representation is
537 * \NoSelect and \NoInferiors
59a8e3e8 538 * $use_long_format - override folder display preference and always show full folder name.
be2d5495 539 */
4669e892 540function sqimap_mailbox_option_list($imap_stream, $show_selected = 0, $folder_skip = 0, $boxes = 0,
59a8e3e8 541 $flag = 'noselect', $use_long_format = false ) {
be2d5495 542 global $username, $data_dir;
543 $mbox_options = '';
45f836eb 544 if ( $use_long_format ) {
545 $shorten_box_names = 0;
546 } else {
547 $shorten_box_names = getPref($data_dir, $username, 'mailbox_select_style', SMPREF_OFF);
548 }
ff245fbd 549
550 if ($boxes == 0) {
be2d5495 551 $boxes = sqimap_mailbox_list($imap_stream);
ff245fbd 552 }
59a8e3e8 553
be2d5495 554 foreach ($boxes as $boxes_part) {
59a8e3e8 555 if ($flag == NULL || !in_array($flag, $boxes_part['flags'])) {
be2d5495 556 $box = $boxes_part['unformatted'];
be2d5495 557
d0928dd5 558 if ($folder_skip != 0 && in_array($box, $folder_skip) ) {
be2d5495 559 continue;
560 }
4669e892 561 $lowerbox = strtolower($box);
5c300c60 562 // mailboxes are casesensitive => inbox.sent != inbox.Sent
563 // nevermind, to many dependencies this should be fixed!
4669e892 564
d0928dd5 565 if (strtolower($box) == 'inbox') { // inbox is special and not casesensitive
be2d5495 566 $box2 = _("INBOX");
4669e892 567 } else {
5c300c60 568 switch ($shorten_box_names)
569 {
570 case 2: /* delimited, style = 2 */
d0928dd5 571 $box2 = str_replace('&nbsp;&nbsp;', '.&nbsp;', $boxes_part['formatted']);
5c300c60 572 break;
d0928dd5 573 case 1: /* indent, style = 1 */
574 $box2 = $boxes_part['formatted'];
5c300c60 575 break;
d0928dd5 576 default: /* default, long names, style = 0 */
6c4f0fa1 577 $box2 = str_replace(' ', '&nbsp;', htmlspecialchars(imap_utf7_decode_local($boxes_part['unformatted-disp'])));
5c300c60 578 break;
579 }
be2d5495 580 }
581 if ($show_selected != 0 && in_array($lowerbox, $show_selected) ) {
86c2763d 582 $mbox_options .= '<OPTION VALUE="' . htmlspecialchars($box) .'" SELECTED>'.$box2.'</OPTION>' . "\n";
be2d5495 583 } else {
86c2763d 584 $mbox_options .= '<OPTION VALUE="' . htmlspecialchars($box) .'">'.$box2.'</OPTION>' . "\n";
be2d5495 585 }
586 }
587 }
588 return $mbox_options;
589}
43b698c7 590
48af4b64 591/**
4669e892 592 * Returns sorted mailbox lists in several different ways.
3411d4ec 593 * See comment on sqimap_mailbox_parse() for info about the returned array.
594 */
fe6efa94 595
596
597function sqimap_mailbox_list($imap_stream, $force=false) {
4b2fe13a 598 global $default_folder_prefix;
7e235a1a 599
fe6efa94 600 if (!sqgetGlobalVar('boxesnew',$boxesnew,SQ_SESSION) || $force) {
3411d4ec 601 global $data_dir, $username, $list_special_folders_first,
7e235a1a 602 $folder_prefix, $trash_folder, $sent_folder, $draft_folder,
603 $move_to_trash, $move_to_sent, $save_as_draft,
60a132f8 604 $delimiter, $noselect_fix_enable, $imap_server_type;
3411d4ec 605 $inbox_in_list = false;
606 $inbox_subscribed = false;
60a132f8 607 $listsubscribed = sqimap_capability($imap_stream,'LIST-SUBSCRIBED');
7e235a1a 608
08185f2a 609 require_once(SM_PATH . 'include/load_prefs.php');
7e235a1a 610
60a132f8 611
612 if ($listsubscribed) {
613 $lsub = 'LIST (SUBSCRIBED)';
614 } else {
615 $lsub = 'LSUB';
4669e892 616 }
617
ff245fbd 618 if ($noselect_fix_enable) {
4669e892 619
60a132f8 620 $lsub_args = "$lsub \"$folder_prefix\" \"*%\"";
ff245fbd 621 } else {
60a132f8 622 $lsub_args = "$lsub \"$folder_prefix\" \"*\"";
ff245fbd 623 }
3411d4ec 624 /* LSUB array */
ca85aabe 625 $lsub_ary = sqimap_run_command ($imap_stream, $lsub_args,
3411d4ec 626 true, $response, $message);
4669e892 627 $lsub_ary = compact_mailboxes_response($lsub_ary);
7e235a1a 628
7e235a1a 629 $sorted_lsub_ary = array();
ff245fbd 630 for ($i = 0, $cnt = count($lsub_ary);$i < $cnt; $i++) {
159d2af7 631
7e235a1a 632 $temp_mailbox_name = find_mailbox_name($lsub_ary[$i]);
633 $sorted_lsub_ary[] = $temp_mailbox_name;
cef054e4 634 if (!$inbox_subscribed && strtoupper($temp_mailbox_name) == 'INBOX') {
3411d4ec 635 $inbox_subscribed = true;
7e235a1a 636 }
637 }
cef054e4 638
5c300c60 639 /* natural sort mailboxes */
7e235a1a 640 if (isset($sorted_lsub_ary)) {
159d2af7 641 usort($sorted_lsub_ary, 'strnatcasecmp');
7e235a1a 642 }
5c300c60 643 /*
644 * The LSUB response doesn't provide us information about \Noselect
645 * mail boxes. The LIST response does, that's why we need to do a LIST
646 * call to retrieve the flags for the mailbox
cef054e4 647 * Note: according RFC2060 an imap server may provide \NoSelect flags in the LSUB response.
648 * in other words, we cannot rely on it.
fe6efa94 649 */
cef054e4 650 $sorted_list_ary = array();
60a132f8 651 // if (!$listsubscribed) {
652 for ($i=0; $i < count($sorted_lsub_ary); $i++) {
7e235a1a 653 if (substr($sorted_lsub_ary[$i], -1) == $delimiter) {
654 $mbx = substr($sorted_lsub_ary[$i], 0, strlen($sorted_lsub_ary[$i])-1);
655 }
656 else {
657 $mbx = $sorted_lsub_ary[$i];
658 }
fe6efa94 659
159d2af7 660 $read = sqimap_run_command ($imap_stream, 'LIST "" ' . sqimap_encode_mailbox_name($mbx),
3411d4ec 661 true, $response, $message);
4669e892 662
159d2af7 663 $read = compact_mailboxes_response($read);
4669e892 664
7e235a1a 665 if (isset($read[0])) {
666 $sorted_list_ary[$i] = $read[0];
cef054e4 667 } else {
7e235a1a 668 $sorted_list_ary[$i] = '';
669 }
60a132f8 670 }
671 // }
3411d4ec 672 /*
7e235a1a 673 * Just in case they're not subscribed to their inbox,
674 * we'll get it for them anyway
675 */
cef054e4 676 if (!$inbox_subscribed) {
159d2af7 677 $inbox_ary = sqimap_run_command ($imap_stream, 'LIST "" "INBOX"',
3411d4ec 678 true, $response, $message);
159d2af7 679 $sorted_list_ary[] = implode('',compact_mailboxes_response($inbox_ary));
7e235a1a 680 $sorted_lsub_ary[] = find_mailbox_name($inbox_ary[0]);
681 }
682
683 $boxesall = sqimap_mailbox_parse ($sorted_list_ary, $sorted_lsub_ary);
684
3411d4ec 685 /* Now, lets sort for special folders */
7e235a1a 686 $boxesnew = $used = array();
687
688 /* Find INBOX */
ff245fbd 689 $cnt = count($boxesall);
5c300c60 690 $used = array_pad($used,$cnt,false);
cef054e4 691 for($k = 0; $k < $cnt; ++$k) {
ff245fbd 692 if (strtolower($boxesall[$k]['unformatted']) == 'inbox') {
693 $boxesnew[] = $boxesall[$k];
3411d4ec 694 $used[$k] = true;
5c300c60 695 break;
7e235a1a 696 }
697 }
7e235a1a 698 /* List special folders and their subfolders, if requested. */
3411d4ec 699 if ($list_special_folders_first) {
cef054e4 700 for($k = 0; $k < $cnt; ++$k) {
ff245fbd 701 if (!$used[$k] && isSpecialMailbox($boxesall[$k]['unformatted'])) {
702 $boxesnew[] = $boxesall[$k];
703 $used[$k] = true;
7e235a1a 704 }
5c300c60 705 }
706 }
fe6efa94 707 /* Rest of the folders */
ff245fbd 708 for($k = 0; $k < $cnt; $k++) {
709 if (!$used[$k]) {
710 $boxesnew[] = $boxesall[$k];
7e235a1a 711 }
712 }
fe6efa94 713 sqsession_register($boxesnew,'boxesnew');
43b698c7 714 }
3411d4ec 715 return $boxesnew;
43b698c7 716}
717
48af4b64 718/**
90de1755 719 * Returns a list of all folders, subscribed or not
720 */
1da22cda 721function sqimap_mailbox_list_all($imap_stream) {
3411d4ec 722 global $list_special_folders_first, $folder_prefix, $delimiter;
bac13dd7 723
724 $read_ary = sqimap_run_command($imap_stream,"LIST \"$folder_prefix\" *",true,$response, $message,false);
725 $read_ary = compact_mailboxes_response($read_ary);
726
43b698c7 727 $g = 0;
90de1755 728 $phase = 'inbox';
7d82bceb 729 $fld_pre_length = strlen($folder_prefix);
ff245fbd 730 for ($i = 0, $cnt = count($read_ary); $i < $cnt; $i++) {
780dd344 731 /* Store the raw IMAP reply */
732 $boxes[$g]['raw'] = $read_ary[$i];
90de1755 733
780dd344 734 /* Count number of delimiters ($delimiter) in folder name */
735 $mailbox = find_mailbox_name($read_ary[$i]);
736 $dm_count = substr_count($mailbox, $delimiter);
737 if (substr($mailbox, -1) == $delimiter) {
738 /* If name ends in delimiter - decrement count by one */
739 $dm_count--;
740 }
90de1755 741
780dd344 742 /* Format folder name, but only if it's a INBOX.* or has a parent. */
743 $boxesallbyname[$mailbox] = $g;
744 $parentfolder = readMailboxParent($mailbox, $delimiter);
745 if((eregi('^inbox'.quotemeta($delimiter), $mailbox)) ||
746 (ereg('^'.$folder_prefix, $mailbox)) ||
747 ( isset($boxesallbyname[$parentfolder]) && (strlen($parentfolder) > 0) ) ) {
748 if ($dm_count) {
749 $boxes[$g]['formatted'] = str_repeat('&nbsp;&nbsp;', $dm_count);
90de1755 750 } else {
780dd344 751 $boxes[$g]['formatted'] = '';
12d61439 752 }
780dd344 753 $boxes[$g]['formatted'] .= imap_utf7_decode_local(readShortMailboxName($mailbox, $delimiter));
754 } else {
755 $boxes[$g]['formatted'] = imap_utf7_decode_local($mailbox);
756 }
757
758 $boxes[$g]['unformatted-dm'] = $mailbox;
759 if (substr($mailbox, -1) == $delimiter) {
760 $mailbox = substr($mailbox, 0, strlen($mailbox) - 1);
761 }
762 $boxes[$g]['unformatted'] = $mailbox;
763 $boxes[$g]['unformatted-disp'] = substr($mailbox,$fld_pre_length);
764
765 $boxes[$g]['id'] = $g;
766
767 /* Now lets get the flags for this mailbox */
768 $read_mlbx = $read_ary[$i];
769 $flags = substr($read_mlbx, strpos($read_mlbx, '(')+1);
770 $flags = substr($flags, 0, strpos($flags, ')'));
771 $flags = str_replace('\\', '', $flags);
772 $flags = trim(strtolower($flags));
773 if ($flags) {
774 $boxes[$g]['flags'] = explode(' ', $flags);
775 } else {
776 $boxes[$g]['flags'] = array();
43b698c7 777 }
778 $g++;
779 }
780 if(is_array($boxes)) {
e429f014 781 sort ($boxes);
43b698c7 782 }
90de1755 783
43b698c7 784 return $boxes;
785}
5bdd7223 786
60b5724d 787function sqimap_mailbox_tree($imap_stream) {
788 global $boxesnew, $default_folder_prefix, $unseen_notify, $unseen_type;
60a132f8 789 if (true) {
60b5724d 790
791 global $data_dir, $username, $list_special_folders_first,
a2e66c6d 792 $folder_prefix, $delimiter, $trash_folder, $move_to_trash,
793 $imap_server_type;
60b5724d 794
795
796 $inbox_in_list = false;
797 $inbox_subscribed = false;
f08ba804 798 $noselect = false;
86c2763d 799 $noinferiors = false;
60b5724d 800
08185f2a 801 require_once(SM_PATH . 'include/load_prefs.php');
60b5724d 802
803 /* LSUB array */
34c7eef3 804 $lsub_ary = sqimap_run_command ($imap_stream, "LSUB \"$folder_prefix\" \"*\"",
60b5724d 805 true, $response, $message);
bac13dd7 806 $lsub_ary = compact_mailboxes_response($lsub_ary);
60b5724d 807
9871bdaa 808 /* Check to see if we have an INBOX */
78bc908d 809 $has_inbox = false;
810
811 for ($i = 0, $cnt = count($lsub_ary); $i < $cnt; $i++) {
6e097fb5 812 if (preg_match("/^\*\s+LSUB.*\s\"?INBOX\"?[^(\/\.)].*$/i",$lsub_ary[$i])) {
49774174 813 $lsub_ary[$i] = strtoupper($lsub_ary[$i]);
31a5064d 814 // in case of an unsubscribed inbox an imap server can
4669e892 815 // return the inbox in the lsub results with a \NoSelect
31a5064d 816 // flag.
817 if (!preg_match("/\*\s+LSUB\s+\(.*\\\\NoSelect.*\).*/i",$lsub_ary[$i])) {
818 $has_inbox = true;
819 } else {
820 // remove the result and request it again with a list
821 // response at a later stage.
822 unset($lsub_ary[$i]);
4669e892 823 // re-index the array otherwise the addition of the LIST
35314c5c 824 // response will fail in PHP 4.1.2 and probably other older versions
825 $lsub_ary = array_values($lsub_ary);
31a5064d 826 }
78bc908d 827 break;
828 }
829 }
830
831 if ($has_inbox == false) {
31a5064d 832 // do a list request for inbox because we should always show
833 // inbox even if the user isn't subscribed to it.
834 $inbox_ary = sqimap_run_command ($imap_stream, 'LIST "" INBOX',
835 true, $response, $message);
836 $inbox_ary = compact_mailboxes_response($inbox_ary);
837 if (count($inbox_ary)) {
838 $lsub_ary[] = $inbox_ary[0];
839 }
78bc908d 840 }
841
60b5724d 842 /*
4669e892 843 * Section about removing the last element was removed
60b5724d 844 * We don't return "* OK" anymore from sqimap_read_data
845 */
bac13dd7 846
60b5724d 847 $sorted_lsub_ary = array();
e4c6fe41 848 $cnt = count($lsub_ary);
ff245fbd 849 for ($i = 0; $i < $cnt; $i++) {
ff245fbd 850 $mbx = find_mailbox_name($lsub_ary[$i]);
a2e66c6d 851
483f9ef9 852 // only do the noselect test if !uw, is checked later. FIX ME see conf.pl setting
4669e892 853 if ($imap_server_type != "uw") {
483f9ef9 854 $noselect = check_is_noselect($lsub_ary[$i]);
86c2763d 855 $noinferiors = check_is_noinferiors($lsub_ary[$i]);
a2e66c6d 856 }
ff245fbd 857 if (substr($mbx, -1) == $delimiter) {
858 $mbx = substr($mbx, 0, strlen($mbx) - 1);
859 }
4669e892 860 $sorted_lsub_ary[] = array ('mbx' => $mbx, 'noselect' => $noselect, 'noinferiors' => $noinferiors);
60b5724d 861 }
5c300c60 862 // FIX ME this requires a config setting inside conf.pl instead of checking on server type
483f9ef9 863 if ($imap_server_type == "uw") {
5c300c60 864 $aQuery = array();
865 $aTag = array();
866 // prepare an array with queries
867 foreach ($sorted_lsub_ary as $aMbx) {
bac13dd7 868 $mbx = stripslashes($aMbx['mbx']);
568cb884 869 sqimap_prepare_pipelined_query('LIST "" ' . sqimap_encode_mailbox_name($mbx), $tag, $aQuery, false);
5c300c60 870 $aTag[$tag] = $mbx;
4669e892 871 }
5c300c60 872 $sorted_lsub_ary = array();
873 // execute all the queries at once
874 $aResponse = sqimap_run_pipelined_command ($imap_stream, $aQuery, false, $aServerResponse, $aServerMessage);
875 foreach($aTag as $tag => $mbx) {
876 if ($aServerResponse[$tag] == 'OK') {
877 $sResponse = implode('', $aResponse[$tag]);
878 $noselect = check_is_noselect($sResponse);
86c2763d 879 $noinferiors = check_is_noinferiors($sResponse);
880 $sorted_lsub_ary[] = array ('mbx' => $mbx, 'noselect' => $noselect, 'noinferiors' => $noinferiors);
5c300c60 881 }
882 }
883 $cnt = count($sorted_lsub_ary);
483f9ef9 884 }
bac13dd7 885 $sorted_lsub_ary = array_values($sorted_lsub_ary);
483f9ef9 886 array_multisort($sorted_lsub_ary, SORT_ASC, SORT_REGULAR);
887 $boxesnew = sqimap_fill_mailbox_tree($sorted_lsub_ary,false,$imap_stream);
888 return $boxesnew;
60b5724d 889 }
890}
891
483f9ef9 892function sqimap_fill_mailbox_tree($mbx_ary, $mbxs=false,$imap_stream) {
60b5724d 893 global $data_dir, $username, $list_special_folders_first,
894 $folder_prefix, $trash_folder, $sent_folder, $draft_folder,
895 $move_to_trash, $move_to_sent, $save_as_draft,
43a31298 896 $delimiter, $imap_server_type;
60b5724d 897
898 $special_folders = array ('INBOX', $sent_folder, $draft_folder, $trash_folder);
ff245fbd 899
60b5724d 900 /* create virtual root node */
901 $mailboxes= new mailboxes();
902 $mailboxes->is_root = true;
ff245fbd 903 $trail_del = false;
78bc908d 904 $start = 0;
905
587ec647 906
43a31298 907 if (isset($folder_prefix) && ($folder_prefix != '')) {
ff245fbd 908 $start = substr_count($folder_prefix,$delimiter);
909 if (strrpos($folder_prefix, $delimiter) == (strlen($folder_prefix)-1)) {
910 $trail_del = true;
911 $mailboxes->mailboxname_full = substr($folder_prefix,0, (strlen($folder_prefix)-1));
912 } else {
913 $mailboxes->mailboxname_full = $folder_prefix;
914 $start++;
915 }
916 $mailboxes->mailboxname_sub = $mailboxes->mailboxname_full;
917 } else {
918 $start = 0;
919 }
78bc908d 920
e4c6fe41 921 $cnt = count($mbx_ary);
922 for ($i=0; $i < $cnt; $i++) {
ff245fbd 923 if ($mbx_ary[$i]['mbx'] !='' ) {
924 $mbx = new mailboxes();
925 $mailbox = $mbx_ary[$i]['mbx'];
cc82c2b7 926
4669e892 927 /*
cc82c2b7 928 sent subfolders messes up using existing code as subfolders
929 were marked, but the parents were ordered somewhere else in
930 the list, despite having "special folders at top" option set.
931 Need a better method than this.
97a5e85f 932 */
8edc9f31 933/*
97a5e85f 934 if ($mailbox == 'INBOX') {
935 $mbx->is_special = true;
936 } elseif (stristr($trash_folder , $mailbox)) {
937 $mbx->is_special = true;
938 } elseif (stristr($sent_folder , $mailbox)) {
939 $mbx->is_special = true;
940 } elseif (stristr($draft_folder , $mailbox)) {
941 $mbx->is_special = true;
942 }
cc82c2b7 943
ff245fbd 944 switch ($mailbox) {
945 case 'INBOX':
946 $mbx->is_inbox = true;
947 $mbx->is_special = true;
8edc9f31 948 $mbx_ary[$i]['noselect'] = false;
ff245fbd 949 break;
950 case $trash_folder:
951 $mbx->is_trash = true;
952 $mbx->is_special = true;
953 break;
954 case $sent_folder:
955 $mbx->is_sent = true;
956 $mbx->is_special = true;
957 break;
958 case $draft_folder:
959 $mbx->is_draft = true;
960 $mbx->is_special = true;
961 break;
962 }
8edc9f31 963*/
964 $mbx->is_special |= ($mbx->is_inbox = (strtoupper($mailbox) == 'INBOX'));
965 $mbx->is_special |= ($mbx->is_trash = isTrashMailbox($mailbox));
966 $mbx->is_special |= ($mbx->is_sent = isSentMailbox($mailbox));
967 $mbx->is_special |= ($mbx->is_draft = isDraftMailbox($mailbox));
968 if (!$mbx->is_special)
fda01075 969 $mbx->is_special = boolean_hook_function('special_mailbox', $mailbox, 1);
4669e892 970
ff245fbd 971 if (isset($mbx_ary[$i]['unseen'])) {
972 $mbx->unseen = $mbx_ary[$i]['unseen'];
973 }
974 if (isset($mbx_ary[$i]['nummessages'])) {
975 $mbx->total = $mbx_ary[$i]['nummessages'];
976 }
977
978 $mbx->is_noselect = $mbx_ary[$i]['noselect'];
86c2763d 979 $mbx->is_noinferiors = $mbx_ary[$i]['noinferiors'];
ff245fbd 980
60b5724d 981 $r_del_pos = strrpos($mbx_ary[$i]['mbx'], $delimiter);
ff245fbd 982 if ($r_del_pos) {
587ec647 983 $mbx->mailboxname_sub = substr($mbx_ary[$i]['mbx'],$r_del_pos+1);
ff245fbd 984 } else { /* mailbox is root folder */
587ec647 985 $mbx->mailboxname_sub = $mbx_ary[$i]['mbx'];
ff245fbd 986 }
987 $mbx->mailboxname_full = $mbx_ary[$i]['mbx'];
38068e69 988
9871bdaa 989 $mailboxes->addMbx($mbx, $delimiter, $start, $list_special_folders_first);
ff245fbd 990 }
60b5724d 991 }
587ec647 992 sqimap_utf7_decode_mbx_tree($mailboxes);
483f9ef9 993 sqimap_get_status_mbx_tree($imap_stream,$mailboxes);
60b5724d 994 return $mailboxes;
995}
259faa39 996
587ec647 997function sqimap_utf7_decode_mbx_tree(&$mbx_tree) {
bd27b70b 998 if (strtoupper($mbx_tree->mailboxname_full) == 'INBOX')
d94c8d61 999 $mbx_tree->mailboxname_sub = _("INBOX");
1000 else
1001 $mbx_tree->mailboxname_sub = imap_utf7_decode_local($mbx_tree->mailboxname_sub);
587ec647 1002 if ($mbx_tree->mbxs) {
1003 $iCnt = count($mbx_tree->mbxs);
1004 for ($i=0;$i<$iCnt;++$i) {
d94c8d61 1005 $mbxs_tree->mbxs[$i] = sqimap_utf7_decode_mbx_tree($mbx_tree->mbxs[$i]);
587ec647 1006 }
1007 }
483f9ef9 1008}
1009
1010
1011function sqimap_tree_to_ref_array(&$mbx_tree,&$aMbxs) {
5c300c60 1012 if ($mbx_tree)
483f9ef9 1013 $aMbxs[] =& $mbx_tree;
1014 if ($mbx_tree->mbxs) {
1015 $iCnt = count($mbx_tree->mbxs);
1016 for ($i=0;$i<$iCnt;++$i) {
5c300c60 1017 sqimap_tree_to_ref_array($mbx_tree->mbxs[$i],$aMbxs);
483f9ef9 1018 }
1019 }
4669e892 1020}
483f9ef9 1021
483f9ef9 1022function sqimap_get_status_mbx_tree($imap_stream,&$mbx_tree) {
1023 global $unseen_notify, $unseen_type, $trash_folder,$move_to_trash;
1024 $aMbxs = $aQuery = $aTag = array();
1025 sqimap_tree_to_ref_array($mbx_tree,$aMbxs);
1026 // remove the root node
1027 array_shift($aMbxs);
1028
1029 if($unseen_notify == 3) {
1030 $cnt = count($aMbxs);
1031 for($i=0;$i<$cnt;++$i) {
5c300c60 1032 $oMbx =& $aMbxs[$i];
1033 if (!$oMbx->is_noselect) {
483f9ef9 1034 $mbx = $oMbx->mailboxname_full;
5c300c60 1035 if ($unseen_type == 2 ||
1036 ($move_to_trash && $oMbx->mailboxname_full == $trash_folder)) {
568cb884 1037 $query = 'STATUS ' . sqimap_encode_mailbox_name($mbx) . ' (MESSAGES UNSEEN)';
5c300c60 1038 } else {
568cb884 1039 $query = 'STATUS ' . sqimap_encode_mailbox_name($mbx) . ' (UNSEEN)';
5c300c60 1040 }
483f9ef9 1041 sqimap_prepare_pipelined_query($query,$tag,$aQuery,false);
5c300c60 1042 } else {
1043 $oMbx->unseen = $oMbx->total = false;
1044 $tag = false;
1045 }
1046 $oMbx->tag = $tag;
1047 $aMbxs[$i] =& $oMbx;
483f9ef9 1048 }
1049 // execute all the queries at once
1050 $aResponse = sqimap_run_pipelined_command ($imap_stream, $aQuery, false, $aServerResponse, $aServerMessage);
1051 $cnt = count($aMbxs);
1052 for($i=0;$i<$cnt;++$i) {
5c300c60 1053 $oMbx =& $aMbxs[$i];
1054 $tag = $oMbx->tag;
1055 if ($tag && $aServerResponse[$tag] == 'OK') {
1056 $sResponse = implode('', $aResponse[$tag]);
483f9ef9 1057 if (preg_match('/UNSEEN\s+([0-9]+)/i', $sResponse, $regs)) {
1058 $oMbx->unseen = $regs[1];
1059 }
1060 if (preg_match('/MESSAGES\s+([0-9]+)/i', $sResponse, $regs)) {
1061 $oMbx->total = $regs[1];
5c300c60 1062 }
1063 }
1064 unset($oMbx->tag);
1065 }
483f9ef9 1066 } else if ($unseen_notify == 2) { // INBOX only
1067 $cnt = count($aMbxs);
1068 for($i=0;$i<$cnt;++$i) {
5c300c60 1069 $oMbx =& $aMbxs[$i];
1070 if (strtoupper($oMbx->mailboxname_full) == 'INBOX' ||
1071 ($move_to_trash && $oMbx->mailboxname_full == $trash_folder)) {
4669e892 1072 if ($unseen_type == 2 ||
5c300c60 1073 ($oMbx->mailboxname_full == $trash_folder && $move_to_trash)) {
1074 $aStatus = sqimap_status_messages($imap_stream,$oMbx->mailboxname_full);
1075 $oMbx->unseen = $aStatus['UNSEEN'];
1076 $oMbx->total = $aStatus['MESSAGES'];
1077 } else {
1078 $oMbx->unseen = sqimap_unseen_messages($imap_stream,$oMbx->mailboxname_full);
1079 }
1080 $aMbxs[$i] =& $oMbx;
1081 if (!$move_to_trash && $trash_folder) {
1082 break;
1083 } else {
1084 // trash comes after INBOX
1085 if ($oMbx->mailboxname_full == $trash_folder) {
1086 break;
1087 }
1088 }
1089 }
1090 }
4669e892 1091 }
1092}
587ec647 1093
648713af 1094?>