Source for file imap_mailbox.php
Documentation is available at imap_mailbox.php
* This implements all functions that manipulate mailboxes
* @copyright © 1999-2006 The SquirrelMail Project Team
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
* @version $Id: imap_mailbox.php,v 1.277 2006/09/30 07:34:47 tokul Exp $
require_once(SM_PATH .
'functions/imap_utf7_local.php');
* FIXME. This class should be extracted and placed in a separate file that
* can be included before we start the session. That makes caching of the tree
* possible. On a refresh mailboxes from left_main.php the only function that
* should be called is the sqimap_get_status_mbx_tree. In case of subscribe
* / rename / delete / new we have to create methods for adding/changing the
* mailbox in the mbx_tree without the need for a refresh.
* Some code fragments are present in 1.3.0 - 1.4.4.
function addMbx($mbx, $delimiter, $start, $specialfirst) {
$ary =
explode($delimiter, $mbx->mailboxname_full);
for ($i =
$start, $c =
count($ary)-
1; $i <
$c; $i++
) {
$mbx_childs =
& $mbx_parent->mbxs;
foreach ($mbx_childs as $key =>
$parent) {
if ($parent->mailboxname_sub ==
$ary[$i]) {
$mbx_parent =
& $mbx_parent->mbxs[$key];
if (isset
($mbx_parent->mailboxname_full) &&
$mbx_parent->mailboxname_full !=
'') {
$no_select_mbx->mailboxname_full =
$mbx_parent->mailboxname_full.
$delimiter.
$ary[$i];
$no_select_mbx->mailboxname_full =
$ary[$i];
$no_select_mbx->mailboxname_sub =
$ary[$i];
$no_select_mbx->is_noselect =
true;
$mbx_parent->mbxs[] =
$no_select_mbx;
$mbx_parent->mbxs[] =
$mbx;
if ($mbx->is_special &&
$specialfirst) {
usort($mbx_parent->mbxs, 'sortSpecialMbx');
* array callback used for sorting in mailboxes class
* @return integer see php strnatcasecmp()
* Workaround for mailboxes returned as literal
* FIXME : Doesn't work if the mailbox name is multiple lines
* (larger then fgets buffer)
for ($i =
0, $iCnt=
count($ary); $i <
$iCnt; $i++
) {
if (isset
($ary[$i +
1]) &&
substr($ary[$i], -
3) ==
"}\r\n") {
if (ereg("^(\\* [A-Z]+.*)\\{[0-9]+\\}([ \n\r\t]*)$",
$ary[$i] =
$regs[1] .
'"' .
addslashes(trim($ary[$i+
1])) .
'"' .
$regs[2];
/* remove duplicates and ensure array is contiguous */
* Extract the mailbox name from an untagged LIST (7.2.2) or LSUB (7.2.3) answer
* (LIST|LSUB) (<Flags list>) (NIL|"<separator atom>") <mailbox name string>\r\n
* mailbox name in quoted string MUST be unquoted and stripslashed (sm API)
* Originally stored in functions/strings.php. Since 1.2.6 stored in
* functions/imap_mailbox.php
* @param string $line imap LIST/LSUB response line
* @return string mailbox name
if (preg_match('/^\* (?:LIST|LSUB) \([^\)]*\) (?:NIL|\"[^\"]*\") ([^\r\n]*)[\r\n]*$/i', $line, $regs)) {
if (substr($regs[1], 0, 1) ==
'"')
* Detects if mailbox has noselect flag (can't store messages)
* In versions older than 1.4.5 function checks only LSUB responses
* and can produce pcre warnings.
* @param string $lsub_line mailbox line from untagged LIST or LSUB response
* @return bool whether this is a Noselect mailbox.
return preg_match("/^\* (LSUB|LIST) \([^\)]*\\\\Noselect[^\)]*\)/i", $lsub_line);
* Detects if mailbox has noinferiors flag (can't store subfolders)
* @param string $lsub_line mailbox line from untagged LIST or LSUB response
* @return bool whether this is a Noinferiors mailbox.
return preg_match("/^\* (LSUB|LIST) \([^\)]*\\\\Noinferiors[^\)]*\)/i", $lsub_line);
* Detects mailbox's parent folder
* If $haystack is a full mailbox name, and $needle is the mailbox
* separator character, returns the second last part of the full
* mailbox name (i.e. the mailbox's parent mailbox)
* Originally stored in functions/strings.php. Since 1.2.6 stored in
* functions/imap_mailbox.php
* @param string $haystack full mailbox name
* @param string $needle delimiter
* @return string parent mailbox
$parts =
explode($needle, $haystack);
while ($elem ==
'' &&
count($parts)) {
$ret =
join($needle, $parts);
* Check if $subbox is below the specified $parentbox
* @param string $subbox potential sub folder
* @param string $parentbox potential parent
* Eliminate the obvious mismatch, where the
* subfolder path is shorter than that of the potential parent
/* check for delimiter */
if (substr($parentbox,-
1) !=
$delimiter) {
$parentbox .=
$delimiter;
return (substr($subbox,0,strlen($parentbox)) ==
$parentbox);
* Defines special mailboxes: given a mailbox name, it checks if this is a
* "special" one: INBOX, Trash, Sent or Draft.
* Since 1.2.5 function includes special_mailbox hook.<br>
* Since 1.4.3 hook supports more than one plugin.
* @param string $box mailbox name
* @param boolean $include_subs (since 1.5.2) if true, subfolders of system
* folders are special. if false, subfolders are not special mailboxes
* unless they are tagged as special in 'special_mailbox' hook.
* Detects if mailbox is a Trash folder or subfolder of Trash
* @param string $box mailbox name
* @param boolean $include_subs (since 1.5.2) if true, subfolders of system
* folders are special. if false, subfolders are not special mailboxes.
* @return bool whether this is a Trash folder
global $trash_folder, $move_to_trash;
return $move_to_trash &&
$trash_folder &&
( $box ==
$trash_folder ||
($include_subs &&
isBoxBelow($box, $trash_folder)) );
* Detects if mailbox is a Sent folder or subfolder of Sent
* @param string $box mailbox name
* @param boolean $include_subs (since 1.5.2) if true, subfolders of system
* folders are special. if false, subfolders are not special mailboxes.
* @return bool whether this is a Sent folder
global $sent_folder, $move_to_sent;
return $move_to_sent &&
$sent_folder &&
( $box ==
$sent_folder ||
($include_subs &&
isBoxBelow($box, $sent_folder)) );
* Detects if mailbox is a Drafts folder or subfolder of Drafts
* @param string $box mailbox name
* @param boolean $include_subs (since 1.5.2) if true, subfolders of system
* folders are special. if false, subfolders are not special mailboxes.
* @return bool whether this is a Draft folder
global $draft_folder, $save_as_draft;
( $box ==
$draft_folder ||
($include_subs &&
isBoxBelow($box, $draft_folder)) );
* WARNING: Select mailbox before calling this function.
* permanently removes all messages that have the \Deleted flag
* set from the selected mailbox. See EXPUNGE command chapter in
* @param stream $imap_stream imap connection resource
* @param string $mailbox mailbox name (unused since 1.1.3).
* @param boolean $handle_errors error handling control (displays error_box on error).
* @param mixed $id (since 1.3.0) integer message id or array with integer ids
* @return integer number of expunged messages
$response, $message, $uid);
if (preg_match('/^\*\s[0-9]+\sEXPUNGE/AUi',$r,$regs)) {
* Checks whether or not the specified mailbox exists
* @param stream $imap_stream imap connection resource
* @param string $mailbox mailbox name
* @param array $mailboxlist (since 1.5.1) optional array of mailboxes from
* sqimap_get_mailboxes() (to avoid having to talk to imap server)
if (!isset
($mailbox) ||
empty($mailbox)) {
// use previously retrieved mailbox list
foreach ($mailboxlist as $mbox) {
if ($mbox['unformatted-dm'] ==
$mailbox) { return true; }
true, $response, $message);
* Before 1.3.0 used more arguments and returned data depended on those arguments.
* @param stream $imap_stream imap connection resource
* @param string $mailbox mailbox name
* @return array results of select command (on success - permanentflags, flags and rights)
// FIX ME: WHAAAA DO NOT USE "None" for something that does not exist. Use false or NULL instead
if ($mailbox ==
'None') {
// cleanup $mailbox in order to prevent IMAP injection attacks
$mailbox =
str_replace(array("\r","\n"), array("",""),$mailbox);
* Default UW IMAP server configuration allows to access other files
* on server. $imap_server_type is not checked because interface can
* be used with 'other' or any other server type setting. $mailbox
* variable can be modified in any script that uses variable from GET
* or POST. This code blocks all standard SquirrelMail IMAP API requests
* that use mailbox with full path (/etc/passwd) or with ../ characters
* in path (../../etc/passwd)
if (strstr($mailbox, '../') ||
substr($mailbox, 0, 1) ==
'/') {
$oTemplate->display('footer.tpl');
true, $response, $message);
for ($i =
0, $cnt =
count($read); $i <
$cnt; $i++
) {
if (preg_match('/^\*\s+OK\s\[(\w+)\s(\w+)\]/',$read[$i], $regs)) {
} else if (preg_match('/^\*\s([0-9]+)\s(\w+)/',$read[$i], $regs)) {
if (preg_match("/PERMANENTFLAGS(.*)/i",$read[$i], $regs)) {
} else if (preg_match("/FLAGS(.*)/i",$read[$i], $regs)) {
if (!isset
($result['PERMANENTFLAGS'])) {
$result['PERMANENTFLAGS'] =
$result['FLAGS'];
* Mailbox is automatically subscribed.
* Set $type to string that does not match 'noselect' (case insensitive),
* if you don't want to prepend delimiter to mailbox name. Please note
* that 'noinferiors' might be used someday as keyword for folders
* that store only messages.
* @param stream $imap_steam imap connection resource
* @param string $mailbox mailbox name
* @param string $type folder type.
$create_mailbox =
$mailbox .
$delimiter;
$create_mailbox =
$mailbox;
true, $response, $message);
* Subscribes to an existing folder.
* @param stream $imap_stream imap connection resource
* @param string $mailbox mailbox name
* @param boolean $debug (since 1.5.1)
$debug, $response, $message);
* Unsubscribes from an existing folder
* @param stream $imap_stream imap connection resource
* @param string $mailbox mailbox name
false, $response, $message);
* Deletes the given folder
* Since 1.2.6 and 1.3.0 contains rename_or_delete_folder hook
* @param stream $imap_stream imap connection resource
* @param string $mailbox mailbox name
true, $response, $message);
if ($response !==
'OK') {
do_hook_function('rename_or_delete_folder', $args =
array($mailbox, 'delete', ''));
removePref($data_dir, $username, "thread_$mailbox");
removePref($data_dir, $username, "collapse_folder_$mailbox");
* Determines if the user is subscribed to the folder or not
* @param stream $imap_stream imap connection resource
* @param string $mailbox mailbox name
foreach ($boxesall as $ref) {
if ($ref['unformatted'] ==
$folder) {
* Since 1.2.6 and 1.3.0 contains rename_or_delete_folder hook
* @param stream $imap_stream imap connection resource
* @param string $old_name mailbox name
* @param string $new_name new mailbox name
if ( $old_name !=
$new_name ) {
if ( substr( $old_name, -
1 ) ==
$delimiter ) {
$old_name =
substr( $old_name, 0, strlen( $old_name ) -
1 );
$new_name =
substr( $new_name, 0, strlen( $new_name ) -
1 );
$oldpref_thread =
getPref($data_dir, $username, 'thread_'.
$old_name.
$postfix);
$oldpref_collapse =
getPref($data_dir, $username, 'collapse_folder_'.
$old_name.
$postfix);
removePref($data_dir, $username, 'thread_'.
$old_name.
$postfix);
removePref($data_dir, $username, 'collapse_folder_'.
$old_name.
$postfix);
setPref($data_dir, $username, 'thread_'.
$new_name.
$postfix, $oldpref_thread);
setPref($data_dir, $username, 'collapse_folder_'.
$new_name.
$postfix, $oldpref_collapse);
do_hook_function('rename_or_delete_folder',$args =
array($old_name, 'rename', $new_name));
foreach ($boxesall as $box) {
if (substr($box[$p], 0, $l) ==
$old_name .
$delimiter) {
$new_sub =
$new_name .
$delimiter .
substr($box[$p], $l);
/* With Cyrus IMAPd >= 2.0 rename is recursive, so don't check for errors here */
if ($imap_server_type ==
'cyrus') {
$cmd =
'RENAME "' .
$box[$p] .
'" "' .
$new_sub .
'"';
$oldpref_thread =
getPref($data_dir, $username, 'thread_'.
$box[$p]);
$oldpref_collapse =
getPref($data_dir, $username, 'collapse_folder_'.
$box[$p]);
removePref($data_dir, $username, 'thread_'.
$box[$p]);
removePref($data_dir, $username, 'collapse_folder_'.
$box[$p]);
setPref($data_dir, $username, 'thread_'.
$new_sub, $oldpref_thread);
setPref($data_dir, $username, 'collapse_folder_'.
$new_sub, $oldpref_collapse);
$args =
array($box[$p], 'rename', $new_sub));
* Formats a mailbox into parts for the $boxesall array
* <li>raw - Raw LIST/LSUB response from the IMAP server
* <li>formatted - nicely formatted folder name
* <li>unformatted - unformatted, but with delimiter at end removed
* <li>unformatted-dm - folder name as it appears in raw response
* <li>unformatted-disp - unformatted without $folder_prefix
* <li>id - TODO: document me
* <li>flags - TODO: document me
* Before 1.2.0 used third argument for delimiter.
* Before 1.5.1 used second argument for lsub line. Argument was removed in order to use
* find_mailbox_name() on the raw input. Since 1.5.1 includes RFC3501 names in flags
* array (for example, "\NoSelect" in addition to "noselect")
* @todo document id and flags keys in boxes array and function arguments.
global $folder_prefix, $delimiter;
/* Process each folder line */
for ($g =
0, $cnt =
count($line); $g <
$cnt; ++
$g) {
/* Store the raw IMAP reply */
$boxesall[$g]['raw'] =
$line[$g];
$boxesall[$g]['raw'] =
'';
/* Count number of delimiters ($delimiter) in folder name */
if (substr($mailbox, -
1) ==
$delimiter) {
/* If name ends in delimiter, decrement count by one */
/* Format folder name, but only if it's a INBOX.* or has a parent. */
$boxesallbyname[$mailbox] =
$g;
(substr($mailbox, 0, strlen($folder_prefix)) ==
$folder_prefix) ||
(isset
($boxesallbyname[$parentfolder]) &&
(strlen($parentfolder) >
0) ) ) {
$indent =
$dm_count -
(substr_count($folder_prefix, $delimiter));
$boxesall[$g]['formatted'] =
str_repeat(' ', $indent);
$boxesall[$g]['formatted'] =
'';
$boxesall[$g]['unformatted-dm'] =
$mailbox;
if (substr($mailbox, -
1) ==
$delimiter) {
$boxesall[$g]['unformatted'] =
$mailbox;
if (substr($mailbox,0,strlen($folder_prefix))==
$folder_prefix) {
$boxesall[$g]['unformatted-disp'] =
$mailbox;
$boxesall[$g]['id'] =
$g;
$boxesall[$g]['flags'] =
array();
ereg("\(([^)]*)\)",$line[$g],$regs);
* Since 1.5.1 flags are stored with RFC3501 naming
* and also the old way for backwards compatibility
* so for example "\NoSelect" and "noselect"
foreach ($flagsarr as $flag) {
$boxesall[$g]['flags']=
$flagsarrnew;
* Returns an array of mailboxes available. Separated from sqimap_mailbox_option_list()
* below for template development.
$flag =
'noselect', $use_long_format =
false ) {
global $username, $data_dir, $translate_special_folders, $sent_folder,
$trash_folder, $draft_folder;
if ( $use_long_format ) {
$shorten_box_names =
getPref($data_dir, $username, 'mailbox_select_style', SMPREF_OFF);
foreach ($boxes as $boxes_part) {
if ($flag ==
NULL ||
(is_array($boxes_part['flags'])
&&
!in_array($flag, $boxes_part['flags']))) {
$box =
$boxes_part['unformatted'];
if ($folder_skip !=
0 &&
in_array($box, $folder_skip) ) {
// mailboxes are casesensitive => inbox.sent != inbox.Sent
// nevermind, to many dependencies this should be fixed!
if (strtolower($box) ==
'inbox') { // inbox is special and not casesensitive
switch ($shorten_box_names)
case 2:
/* delimited, style = 2 */
if ($translate_special_folders &&
$boxes_part['unformatted-dm']==
$sent_folder) {
* calculate pad level from number of delimiters. do it inside if control in order
* to reduce number of calculations. Other folders don't need it.
// i18n: Name of Sent folder
$box2 =
$pad .
_("Sent");
} elseif ($translate_special_folders &&
$boxes_part['unformatted-dm']==
$trash_folder) {
// i18n: Name of Trash folder
$box2 =
$pad .
_("Trash");
} elseif ($translate_special_folders &&
$boxes_part['unformatted-dm']==
$draft_folder) {
// i18n: Name of Drafts folder
$box2 =
$pad .
_("Drafts");
case 1:
/* indent, style = 1 */
if ($translate_special_folders &&
$boxes_part['unformatted-dm']==
$sent_folder) {
$pad =
str_pad('',12 *
(count(explode($delimiter,$boxes_part['unformatted-dm']))-
1),' ');
$box2 =
$pad .
_("Sent");
} elseif ($translate_special_folders &&
$boxes_part['unformatted-dm']==
$trash_folder) {
$pad =
str_pad('',12 *
(count(explode($delimiter,$boxes_part['unformatted-dm']))-
1),' ');
$box2 =
$pad .
_("Trash");
} elseif ($translate_special_folders &&
$boxes_part['unformatted-dm']==
$draft_folder) {
$pad =
str_pad('',12 *
(count(explode($delimiter,$boxes_part['unformatted-dm']))-
1),' ');
$box2 =
$pad .
_("Drafts");
default:
/* default, long names, style = 0 */
* Returns list of options (to be echoed into select statement
* based on available mailboxes and separators
* Caller should surround options with <select ...> </select> and
* @param stream $imap_stream imap connection resource to query for mailboxes
* @param array $show_selected array containing list of mailboxes to pre-select (0 if none)
* @param array $folder_skip array of folders to keep out of option list (compared in lower)
* @param $boxes list of already fetched boxes (for places like folder panel, where
* you know these options will be shown 3 times in a row.. (most often unset).
* @param string $flag (since 1.4.1) flag to check for in mailbox flags, used to filter out mailboxes.
* 'noselect' by default to remove unselectable mailboxes.
* 'noinferiors' used to filter out folders that can not contain subfolders.
* NULL to avoid flag check entirely.
* NOTE: noselect and noiferiors are used internally. The IMAP representation is
* \NoSelect and \NoInferiors
* @param boolean $use_long_format (since 1.4.1) override folder display preference and always show full folder name.
* @return string html formated mailbox selection options
$flag =
'noselect', $use_long_format =
false ) {
global $username, $data_dir, $translate_special_folders, $sent_folder,
$trash_folder, $draft_folder;
foreach ($boxes as $value=>
$option) {
if ($show_selected !=
0) {
while (!$sel &&
(list
($x, $val) =
each($show_selected))) {
$str .=
'<option value="'.
$value .
'"'.
($sel ?
' selected="selected"' :
'').
'>'.
$option .
"</option>\n";
* Returns sorted mailbox lists in several different ways.
* Since 1.5.1 most of the functionality has been moved to new function sqimap_get_mailboxes
* See comment on sqimap_mailbox_parse() for info about the returned array.
* @param resource $imap_stream imap connection resource
* @param boolean $force force update of mailbox listing. available since 1.4.2 and 1.5.0
* @return array list of mailboxes
global $boxesnew,$show_only_subscribed_folders;
* Returns a list of all folders, subscribed or not
* Since 1.5.1 code moved to sqimap_get_mailboxes()
* @param stream $imap_stream imap connection resource
* @return array see sqimap_mailbox_parse()
global $show_only_subscribed_folders;
// fourth argument prevents registration of retrieved list of mailboxes in session
* Gets the list of mailboxes for sqimap_maolbox_tree and sqimap_mailbox_list
* This is because both of those functions had duplicated logic, but with slightly different
* implementations. This will make both use the same implementation, which should make it
* easier to maintain and easier to modify in the future
* @param stream $imap_stream imap connection resource
* @param bool $force force a reload and ignore cache
* @param bool $show_only_subscribed controls listing of visible or all folders
* @param bool $session_register controls registration of retrieved data in session.
* @return object boxesnew - array of mailboxes and their attributes
function sqimap_get_mailboxes($imap_stream,$force=
false,$show_only_subscribed=
true,$session_register=
true) {
$inbox_subscribed =
false;
if ($show_only_subscribed) { $show_only_subscribed=
$show_only_subscribed_folders; }
//require_once(SM_PATH . 'include/load_prefs.php');
* There are three main listing commands we can use in IMAP:
* LSUB shows just the list of subscribed folders
* may include flags, but these are not necessarily accurate or authoratative
* \NoSelect has special meaning: the folder does not exist -OR- it means this
* folder is not subscribed but children may be
* LIST this shows every mailbox on the system
* flags are always included and are accurate and authoratative
* \NoSelect means folder should not be selected
* LIST (SUBSCRIBED) implemented with LIST-SUBSCRIBED extension
* this is like list but returns only subscribed folders
* flag meanings are like LIST, not LSUB
* \NonExistent means mailbox doesn't exist
* \PlaceHolder means parent is not valid (selectable), but one or more children are
* \NoSelect indeed means that the folder should not be selected
* IMAPEXT-LIST-EXTENSIONS-04 August 2003 B. Leiba
if (!$show_only_subscribed) {
$sub_cache_name=
'list_cache';
} elseif ($listsubscribed) {
$lsub =
'LIST (SUBSCRIBED)';
$sub_cache_name=
'listsub_cache';
$sub_cache_name=
'lsub_cache';
// Some IMAP servers allow subfolders to exist even if the parent folders do not
// This fixes some problems with the folder list when this is the case, causing the
// NoSelect folders to be displayed
if ($noselect_fix_enable) {
$lsub_args =
"$lsub \"$folder_prefix\" \"*%\"";
$list_args =
"LIST \"$folder_prefix\" \"*%\"";
$lsub_args =
"$lsub \"$folder_prefix\" \"*\"";
$list_args =
"LIST \"$folder_prefix\" \"*\"";
// get subscribed mailbox list from cache (session)
// if not there, then get it from the imap server and store in cache
if (!empty($lsub_cache)) {
$lsub_assoc_ary=
$lsub_cache;
foreach ($lsub_ary as $rawline) {
$lsub_assoc_ary[$temp_mailbox_name]=
$rawline;
// Now to get the mailbox flags
// The LSUB response may return \NoSelect flags, etc. but it is optional
// according to RFC3501, and even when returned it may not be accurate
// or authoratative. LIST will always return accurate results.
if (($lsub ==
'LIST') ||
($lsub ==
'LIST (SUBSCRIBED)')) {
// we've already done a LIST or LIST (SUBSCRIBED)
// and NOT a LSUB, so no need to do it again
$list_assoc_ary =
$lsub_assoc_ary;
// we did a LSUB so now we need to do a LIST
// first see if it is in cache
$list_cache_name=
'list_cache';
if (!empty($list_cache)) {
$list_assoc_ary=
$list_cache;
// we could store this in list_cache_name but not necessary
// not in cache so we need to go get it from the imap server
$list_assoc_ary =
array();
true, $response, $message);
foreach ($list_ary as $rawline) {
$list_assoc_ary[$temp_mailbox_name]=
$rawline;
// If they aren't subscribed to the inbox, then add it anyway (if its in LIST)
if (!empty($lsub_assoc_ary)) {
foreach ($lsub_assoc_ary as $temp_mailbox_name=>
$rawline) {
if (!$inbox_subscribed) {
if (!empty($list_assoc_ary)) {
foreach ($list_assoc_ary as $temp_mailbox_name=>
$rawline) {
$lsub_assoc_ary[$temp_mailbox_name]=
$rawline;
// Now we have the raw output, we need to create an array of mailbox names we will return
if (!$show_only_subscribed) {
$final_folders_assoc_ary=
$list_assoc_ary;
* only show subscribed folders
* we need to merge the folders here... we can't trust the flags, etc. from the lsub_assoc_array
* so we use the lsub_assoc_array as the list of folders and the values come from list_assoc_array
if (!empty($lsub_assoc_ary)) {
foreach ($lsub_assoc_ary as $temp_mailbox_name=>
$rawline) {
if (!empty($list_assoc_ary[$temp_mailbox_name])) {
$final_folders_assoc_ary[$temp_mailbox_name]=
$list_assoc_ary[$temp_mailbox_name];
// Now produce a flat, sorted list
if (!empty($final_folders_assoc_ary)) {
uksort($final_folders_assoc_ary,'strnatcasecmp');
foreach ($final_folders_assoc_ary as $temp_mailbox_name=>
$rawline) {
$final_folders_ary[]=
$rawline;
// this will put it into an array we can use later
// raw - Raw LIST/LSUB response from the IMAP server
// formatted - formatted folder name
// unformatted - unformatted, but with the delimiter at the end removed
// unformated-dm - folder name as it appears in raw response
// unformatted-disp - unformatted without $folder_prefix
// id - the array element number (0, 1, 2, etc.)
if (!empty($final_folders_ary)) {
// they have no mailboxes
/* Now, lets sort for special folders */
$boxesnew =
$used =
array();
for($k =
0; $k <
$cnt; ++
$k) {
if (strtoupper($boxesall[$k]['unformatted']) ==
'INBOX') {
$boxesnew[] =
$boxesall[$k];
if ($has_inbox ==
false) {
// do a list request for inbox because we should always show
// inbox even if the user isn't subscribed to it.
true, $response, $message);
// add it on top of the list
$boxesnew[]=
$inbox_entry[0];
/* array_unshift($used,true); */
/* List special folders and their subfolders, if requested. */
if ($list_special_folders_first) {
for($k =
0; $k <
$cnt; ++
$k) {
$boxesnew[] =
$boxesall[$k];
/* Find INBOX's children */
for($k =
0; $k <
$cnt; ++
$k) {
if (strtoupper($boxesall[$k]['unformatted']) ==
'INBOX') {
if (!$used[$k] &&
$isboxbelow &&
$is_inbox) {
$boxesnew[] =
$boxesall[$k];
/* Rest of the folders */
for($k =
0; $k <
$cnt; $k++
) {
$boxesnew[] =
$boxesall[$k];
* Don't register boxes in session, if $session_register is set to false
* Prevents registration of sqimap_mailbox_list_all() results.
* this is passed the mailbox array by left_main.php
* who has previously obtained it from sqimap_get_mailboxes
* that way, the raw mailbox list is available in left_main to other
* things besides just sqimap_mailbox_tree
* imap_stream is just used now to get status info
* most of the functionality is moved to sqimap_get_mailboxes
* also takes care of TODO items:
* config setting for UW imap section (not needed now)
* Some code fragments are present in 1.3.0 - 1.4.4.
* @param stream $imap_stream imap connection resource
* @param array $lsub_ary output array from sqimap_get_mailboxes (contains mailboxes and flags)
* @return object see mailboxes class.
$sorted_lsub_ary =
array();
for ($i =
0; $i <
$cnt; $i++
) {
$mbx=
$lsub_ary[$i]['unformatted'];
$flags=
$lsub_ary[$i]['flags'];
if (in_array('\Noinferiors',$flags)) { $noinferiors=
1; }
if (in_array('\NoInferiors',$flags)) { $noinferiors=
1; }
if (in_array('\HasNoChildren',$flags)) { $noinferiors=
1; }
if (in_array('\NoSelect',$flags)) { $noselect=
1; }
* LIST (SUBSCRIBED) has two new flags, \NonExistent which means the mailbox is subscribed to
* but doesn't exist, and \PlaceHolder which is similar (but not the same) as \NoSelect
* For right now, we'll treat these the same as \NoSelect and this behavior can be changed
if (in_array('\NonExistent',$flags)) { $noselect=
1; }
if (in_array('\PlaceHolder',$flags)) { $noselect=
1; }
$sorted_lsub_ary[] =
array ('mbx' =>
$mbx, 'noselect' =>
$noselect, 'noinferiors' =>
$noinferiors);
usort($sorted_lsub_ary, 'mbxSort');
* Callback function used for sorting mailboxes in sqimap_mailbox_tree
* @return integer see php strnatcasecmp()
* Some code fragments are present in 1.3.0 - 1.4.4.
* @param stream $imap_stream imap connection resource
* @return object see mailboxes class
$folder_prefix, $trash_folder, $sent_folder, $draft_folder,
$move_to_trash, $move_to_sent, $save_as_draft,
// $special_folders = array ('INBOX', $sent_folder, $draft_folder, $trash_folder);
/* create virtual root node */
if (isset
($folder_prefix) &&
($folder_prefix !=
'')) {
if (strrpos($folder_prefix, $delimiter) ==
(strlen($folder_prefix)-
1)) {
for ($i=
0; $i <
$cnt; $i++
) {
if ($mbx_ary[$i]['mbx'] !=
'' ) {
$mailbox =
$mbx_ary[$i]['mbx'];
* Set the is_special flag if it concerned a special mailbox.
* Used for displaying the special folders on top in the mailbox
if (isset
($mbx_ary[$i]['unseen'])) {
$mbx->unseen =
$mbx_ary[$i]['unseen'];
if (isset
($mbx_ary[$i]['nummessages'])) {
$mbx->total =
$mbx_ary[$i]['nummessages'];
$r_del_pos =
strrpos($mbx_ary[$i]['mbx'], $delimiter);
} else { /* mailbox is root folder */
$mailboxes->addMbx($mbx, $delimiter, $start, $list_special_folders_first);
* @param object $mbx_tree
global $draft_folder, $sent_folder, $trash_folder, $translate_special_folders;
/* decode folder name and set mailboxname_sub */
} elseif ($translate_special_folders &&
$mbx_tree->mailboxname_full ==
$draft_folder) {
} elseif ($translate_special_folders &&
$mbx_tree->mailboxname_full ==
$sent_folder) {
} elseif ($translate_special_folders &&
$mbx_tree->mailboxname_full ==
$trash_folder) {
for ($i=
0;$i<
$iCnt;++
$i) {
* @param object $mbx_tree
for ($i=
0;$i<
$iCnt;++
$i) {
* @param stream $imap_stream imap connection resource
* @param object $mbx_tree
global $unseen_notify, $unseen_type, $trash_folder,$move_to_trash;
$aMbxs =
$aQuery =
array();
if($unseen_notify ==
3) {
// execute all the queries at once
if ($tag &&
$aServerResponse[$tag] ==
'OK') {
$sResponse =
implode('', $aResponse[$tag]);
if (preg_match('/UNSEEN\s+([0-9]+)/i', $sResponse, $regs)) {
if (preg_match('/MESSAGES\s+([0-9]+)/i', $sResponse, $regs)) {
if (preg_match('/RECENT\s+([0-9]+)/i', $sResponse, $regs)) {
} else if ($unseen_notify ==
2) { // INBOX only
$oMbx->unseen =
$aStatus['UNSEEN'];
$oMbx->total =
$aStatus['MESSAGES'];
$oMbx->recent =
$aStatus['RECENT'];
if (!$move_to_trash &&
$trash_folder) {
// trash comes after INBOX
if (!empty($oMbx->unseen)) { $hook_status['UNSEEN']=
$oMbx->unseen; }
if (!empty($oMbx->total)) { $hook_status['MESSAGES']=
$oMbx->total; }
if (!empty($oMbx->recent)) { $hook_status['RECENT']=
$oMbx->recent; }
if (!empty($hook_status))
$hook_status['CALLER']=
'sqimap_get_status_mbx_tree'; // helps w/ debugging
* Checks if folder is noselect (can't store messages)
* Function does not check if folder subscribed.
* @param stream $oImapStream imap connection resource
* @param string $sImapFolder imap folder name
* @param object $oBoxes mailboxes class object.
* @return boolean true, when folder has noselect flag. false in any other case.
// build mailbox object if it is not available
foreach($oBoxes as $box) {
if ($box['unformatted']==
$sImapFolder) {
* Checks if folder is noinferiors (can't store other folders)
* Function does not check if folder subscribed.
* @param stream $oImapStream imap connection resource
* @param string $sImapFolder imap folder name
* @param object $oBoxes mailboxes class object.
* @return boolean true, when folder has noinferiors flag. false in any other case.
// build mailbox object if it is not available
foreach($oBoxes as $box) {
if ($box['unformatted']==
$sImapFolder) {
Documentation generated on Sat, 07 Oct 2006 16:11:45 +0300 by phpDocumentor 1.3.0RC6