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