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