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