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.172.2.28 2006/10/07 12:58:41 tokul Exp $
require_once(SM_PATH .
'functions/imap_utf7_local.php');
$acmp =
'0'.
$a->mailboxname_full;
} else if ($a->is_special) {
$acmp =
'1'.
$a->mailboxname_full;
$acmp =
'2' .
$a->mailboxname_full;
$bcmp =
'0'.
$b->mailboxname_full;
}else if ($b->is_special) {
$bcmp =
'1' .
$b->mailboxname_full;
$bcmp =
'2' .
$b->mailboxname_full;
if ($acmp ==
$bcmp) return 0;
return ($acmp >
$bcmp) ?
1: -
1;
if (preg_match('/\*.+\"([^\r\n\"]*)\"[\s\r\n]*$/', $mailbox, $regs))
if (ereg(" *\"([^\r\n\"]*)\"[ \r\n]*$", $mailbox, $regs))
ereg(" *([^ \r\n\"]*)[ \r\n]*$",$mailbox,$regs);
* @return bool whether this is a Noselect mailbox.
return preg_match("/^\* (LSUB|LIST) \([^\)]*\\\\Noselect[^\)]*\)/i", $lsub_line);
* 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)
$parts =
explode($needle, $haystack);
while ($elem ==
'' &&
count($parts)) {
$ret =
join($needle, $parts);
* Check if $subbox is below the specified $parentbox
* Eliminate the obvious mismatch, where the
* subfolder path is shorter than that of the potential parent
/* check for delimiter */
if (substr($parentbox,-
1) !=
$delimiter) {
* 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 and 1.4.9) 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 and 1.4.9) 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 and 1.4.9) 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 and 1.4.9) 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)) );
* Expunges a mailbox, ie. delete all contents.
$response, $message, $uid);
if (preg_match('/^\*\s[0-9]+\sEXPUNGE/AUi',$r,$regs)) {
* Checks whether or not the specified mailbox exists
if (!isset
($mailbox) ||
empty($mailbox)) {
true, $response, $message);
if ($mailbox ==
'None') {
* 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) ==
'/') {
include_once(SM_PATH .
'functions/display_messages.php');
// cleanup $mailbox in order to prevent IMAP injection attacks
$mailbox =
str_replace(array("\r","\n"), array("",""),$mailbox);
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)) {
$result['PERMANENTFLAGS'] =
$regs[1];
} else if (preg_match("/FLAGS(.*)/i",$read[$i], $regs)) {
$result['FLAGS'] =
$regs[1];
$result['RIGHTS']=
$regs[1];
$create_mailbox =
$mailbox .
$delimiter;
$create_mailbox =
$mailbox;
true, $response, $message);
* Subscribes to an existing folder.
true, $response, $message);
* Unsubscribes from an existing folder
false, $response, $message);
* Deletes the given folder
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
foreach ($boxesall as $ref) {
if ($ref['unformatted'] ==
$folder) {
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 );
$cmd =
'RENAME "' .
$old_name .
'" "' .
$new_name .
'"';
$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
* raw - Raw LIST/LSUB response from the IMAP server
* formatted - nicely formatted folder name
* unformatted - unformatted, but with delimiter at end removed
* unformatted-dm - folder name as it appears in raw response
* unformatted-disp - unformatted without $folder_prefix
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 */
$mailbox =
$line_lsub[$g];
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);
$boxesall[$g]['flags'] =
explode(' ', $flags);
* Sorting function used to sort mailbox names.
* + Original patch from dave_michmerhuizen@yahoo.com
* + Allows case insensitivity when sorting folders
* + Takes care of the delimiter being sorted to the end, causing
* subfolders to be listed in below folders that are prefixed
* with their parent folders name.
* For example: INBOX.foo, INBOX.foobar, and INBOX.foo.bar
* Without special sort function: foobar between foo and foo.bar
* With special sort function: foobar AFTER foo and foo.bar :)
* Returns list of options (to be echoed into select statement
* based on available mailboxes and separators
* Caller should surround options with <select ...> </select> and
* $imap_stream - $imapConnection to query for mailboxes
* $show_selected - array containing list of mailboxes to pre-select (0 if none)
* $folder_skip - array of folders to keep out of option list (compared in lower)
* $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).
* $flag - 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.
* $use_long_format - override folder display preference and always show full folder name.
$flag =
'noselect', $use_long_format =
false ) {
if ( $use_long_format ) {
$shorten_box_names =
getPref($data_dir, $username, 'mailbox_select_style', SMPREF_OFF);
foreach ($boxes as $boxes_part) {
if ($flag ==
NULL ||
!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 */
$box2 =
str_replace(' ', '. ', $boxes_part['formatted']);
case 1:
/* indent, style = 1 */
$box2 =
$boxes_part['formatted'];
default:
/* default, long names, style = 0 */
$box2 =
str_replace(array('<','>'), array('<','>') , $box2);
if ($show_selected !=
0 &&
in_array($lowerbox, $show_selected) ) {
$mbox_options .=
'<option value="' .
htmlspecialchars($box) .
'" selected="selected">'.
$box2.
'</option>' .
"\n";
$mbox_options .=
'<option value="' .
htmlspecialchars($box) .
'">'.
$box2.
'</option>' .
"\n";
* Mailboxes with some chars (like -) can mess up the order, this fixes it
foreach($lsub as $index =>
$mailbox)
$lsub[$index] =
str_replace('.',' -#- ',$lsub[$index]);
usort($lsub, 'user_strcasecmp');
foreach($lsub as $index =>
$mailbox)
$lsub[$index] =
str_replace(' -#- ','.',$lsub[$index]);
* Returns sorted mailbox lists in several different ways.
* See comment on sqimap_mailbox_parse() for info about the returned array.
$folder_prefix, $trash_folder, $sent_folder, $draft_folder,
$move_to_trash, $move_to_sent, $save_as_draft,
$inbox_subscribed =
false;
require_once(SM_PATH .
'include/load_prefs.php');
if ($noselect_fix_enable) {
$lsub_args =
"LSUB \"$folder_prefix\" \"*%\"";
$lsub_args =
"LSUB \"$folder_prefix\" \"*\"";
true, $response, $message);
$sorted_lsub_ary =
array();
for ($i =
0, $cnt =
count($lsub_ary);$i <
$cnt; $i++
) {
* Workaround for mailboxes returned as literal
* Doesn't work if the mailbox name is multiple lines
* (larger then fgets buffer)
if (isset
($lsub_ary[$i +
1]) &&
substr($lsub_ary[$i],-
3) ==
"}\r\n") {
if (ereg("^(\\* [A-Z]+.*)\\{[0-9]+\\}([ \n\r\t]*)$",
$lsub_ary[$i] =
$regs[1] .
'"' .
addslashes(trim($lsub_ary[$i])) .
'"' .
$regs[2];
$sorted_lsub_ary[] =
$temp_mailbox_name;
if (!$inbox_subscribed &&
strtoupper($temp_mailbox_name) ==
'INBOX') {
$inbox_subscribed =
true;
/* natural sort mailboxes */
if (isset
($sorted_lsub_ary)) {
* The LSUB response doesn't provide us information about \Noselect
* mail boxes. The LIST response does, that's why we need to do a LIST
* call to retrieve the flags for the mailbox
* Note: according RFC2060 an imap server may provide \NoSelect flags in the LSUB response.
* in other words, we cannot rely on it.
$sorted_list_ary =
array();
for ($i=
0; $i <
count($sorted_lsub_ary); $i++
) {
if (substr($sorted_lsub_ary[$i], -
1) ==
$delimiter) {
$mbx =
substr($sorted_lsub_ary[$i], 0, strlen($sorted_lsub_ary[$i])-
1);
$mbx =
$sorted_lsub_ary[$i];
true, $response, $message);
/* Another workaround for literals */
if (isset
($read[1]) &&
substr($read[1],-
3) ==
"}\r\n") {
if (ereg("^(\\* [A-Z]+.*)\\{[0-9]+\\}([ \n\r\t]*)$",
$read[0] =
$regs[1] .
'"' .
addslashes(trim($read[1])) .
'"' .
$regs[2];
$sorted_list_ary[$i] =
$read[0];
$sorted_list_ary[$i] =
'';
* Just in case they're not subscribed to their inbox,
* we'll get it for them anyway
if (!$inbox_subscribed) {
true, $response, $message);
/* Another workaround for literals */
if (isset
($inbox_ary[1]) &&
substr($inbox_ary[0],-
3) ==
"}\r\n") {
if (ereg("^(\\* [A-Z]+.*)\\{[0-9]+\\}([ \n\r\t]*)$",
$sorted_list_ary[] =
$inbox_ary[0];
/* Now, lets sort for special folders */
$boxesnew =
$used =
array();
for($k =
0; $k <
$cnt; ++
$k) {
if (strtolower($boxesall[$k]['unformatted']) ==
'inbox') {
$boxesnew[] =
$boxesall[$k];
/* 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) {
strtolower($boxesall[$k]['unformatted']) !=
'inbox') {
$boxesnew[] =
$boxesall[$k];
/* Rest of the folders */
for($k =
0; $k <
$cnt; $k++
) {
$boxesnew[] =
$boxesall[$k];
* Returns a list of all folders, subscribed or not
fputs ($imap_stream, $ssid .
" LIST \"$folder_prefix\" *\r\n");
$fld_pre_length =
strlen($folder_prefix);
for ($i =
0, $cnt =
count($read_ary); $i <
$cnt; $i++
) {
/* Another workaround for EIMS */
if (isset
($read_ary[$i +
1]) &&
ereg("^(\\* [A-Z]+.*)\\{[0-9]+\\}([ \n\r\t]*)$",
$read_ary[$i] =
$regs[1] .
'"' .
addslashes(trim($read_ary[$i])) .
'"' .
$regs[2];
if (substr($read_ary[$i], 0, $lsid) !=
$ssid ) {
/* Store the raw IMAP reply */
$boxes[$g]['raw'] =
$read_ary[$i];
/* 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;
(ereg('^'.
$folder_prefix, $mailbox)) ||
( isset
($boxesallbyname[$parentfolder]) &&
(strlen($parentfolder) >
0) ) ) {
$boxes[$g]['formatted'] =
str_repeat(' ', $dm_count);
$boxes[$g]['formatted'] =
'';
$boxes[$g]['unformatted-dm'] =
$mailbox;
if (substr($mailbox, -
1) ==
$delimiter) {
$boxes[$g]['unformatted'] =
$mailbox;
$boxes[$g]['unformatted-disp'] =
substr($mailbox,$fld_pre_length);
/* Now lets get the flags for this mailbox */
$read_mlbx =
$read_ary[$i];
// $read_mlbx = sqimap_run_command ($imap_stream, "LIST \"\" \"$mailbox\"",
// true, $response, $message);
/* Another workaround for EIMS */
// if (isset($read_mlbx[1]) &&
// ereg("^(\\* [A-Z]+.*)\\{[0-9]+\\}([ \n\r\t]*)$", $read_mlbx[0], $regs)) {
// $read_mlbx[0] = $regs[1] . '"' . addslashes(trim($read_mlbx[1])) . '"' . $regs[2];
// echo $read_mlbx[0] .' raw 2 <br>';
$boxes[$g]['flags'] =
explode(' ', $flags);
$boxes[$g]['flags'] =
array();
Documentation generated on Sat, 07 Oct 2006 16:31:43 +0300 by phpDocumentor 1.3.0RC6