X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=functions%2Fimap_mailbox.php;h=2bb6468b9d8e676cc5c33360f71fe03aa2c431d4;hb=22476f18b2ff4ae81fd4a52e9f335691e31b7750;hp=ede0e4935a688039c705a0fcd5b8c0874f524aca;hpb=259faa3992c7aa2910c0d71d61959ff81659ea67;p=squirrelmail.git diff --git a/functions/imap_mailbox.php b/functions/imap_mailbox.php index ede0e493..2bb6468b 100755 --- a/functions/imap_mailbox.php +++ b/functions/imap_mailbox.php @@ -105,30 +105,27 @@ function readMailboxParent($haystack, $needle) { return( $ret ); } - -function isBoxBelow( $box2, $box1 ) { -global $delimiter, $folder_prefix, $imap_server_type; - if ( $imap_server_type == 'uw' ) { - $boxs = $box2; - $i = strpos( $box1, $delimiter, strlen( $folder_prefix ) ); - if ( $i === false ) { - $i = strlen( $box2 ); - } - } else { - if (substr($box2,0,strlen($box1)) == $box1) { - return true; - } - $boxs = $box2 . $delimiter; - /* Skip next second delimiter */ - $i = strpos( $box1, $delimiter ); - $i = strpos( $box1, $delimiter, $i + 1 ); - if ( $i === false ) { - $i = strlen( $box2 ); - } else { - $i++; - } - } - return ( substr( $box1, 0, $i ) == substr( $boxs, 0, $i ) ); +/** + * Check if $subbox is below the specified $parentbox + */ +function isBoxBelow( $subbox, $parentbox ) { + global $delimiter; + /* + * Eliminate the obvious mismatch, where the + * subfolder path is shorter than that of the potential parent + */ + if ( strlen($subbox) < strlen($parentbox) ) { + return false; + } + /* check for delimiter */ + if (!substr($parentbox,-1) == $delimiter) { + $parentbox.=$delimiter; + } + if (substr($subbox,0,strlen($parentbox)) == $parentbox) { + return true; + } else { + return false; + } } /* Defines special mailboxes */ @@ -137,9 +134,7 @@ function isSpecialMailbox( $box ) { $move_to_trash, $move_to_sent, $save_as_draft; $ret = ( (strtolower($box) == 'inbox') || - ( $move_to_trash && $trash_folder && isBoxBelow( $box, $trash_folder )) || - ( $move_to_sent && $sent_folder && isBoxBelow( $box, $sent_folder )) || - ($save_as_draft && $box == $draft_folder ) ); + isTrashMailbox($box) || isSentMailbox($box) || isDraftMailbox($box) ); if ( !$ret ) { $ret = do_hook_function( 'special_mailbox', $box ); @@ -147,6 +142,24 @@ function isSpecialMailbox( $box ) { return $ret; } +function isTrashMailbox ($box) { + global $trash_folder, $move_to_trash; + return $move_to_trash && $trash_folder && + ( $box == $trash_folder || isBoxBelow($box, $trash_folder) ); +} + +function isSentMailbox($box) { + global $sent_folder, $move_to_sent; + return $move_to_sent && $sent_folder && + ( $box == $sent_folder || isBoxBelow($box, $sent_folder) ); +} + +function isDraftMailbox($box) { + global $draft_folder, $save_as_draft; + return $save_as_draft && + ( $box == $draft_folder || isBoxBelow($box, $draft_folder) ); +} + /* Expunges a mailbox */ function sqimap_mailbox_expunge ($imap_stream, $mailbox, $handle_errors = true, $id='') { global $uid_support; @@ -175,7 +188,7 @@ function sqimap_mailbox_expunge ($imap_stream, $mailbox, $handle_errors = true, /* Checks whether or not the specified mailbox exists */ function sqimap_mailbox_exists ($imap_stream, $mailbox) { - if (!isset($mailbox)) { + if (!isset($mailbox) || empty($mailbox)) { return false; } $mbx = sqimap_run_command($imap_stream, "LIST \"\" \"$mailbox\"", @@ -323,7 +336,7 @@ function sqimap_mailbox_parse ($line, $line_lsub) { global $folder_prefix, $delimiter; /* Process each folder line */ - for ($g = 0, $cnt = count($line); $g < $cnt; $g++) { + for ($g = 0, $cnt = count($line); $g < $cnt; ++$g) { /* Store the raw IMAP reply */ if (isset($line[$g])) { $boxesall[$g]['raw'] = $line[$g]; @@ -393,48 +406,7 @@ function sqimap_mailbox_parse ($line, $line_lsub) { * With special sort function: foobar AFTER foo and foo.bar :) */ function user_strcasecmp($a, $b) { - global $delimiter; - return strnatcasecmp($a, $b); - - /* Calculate the length of some strings. */ - $a_length = strlen($a); - $b_length = strlen($b); - $min_length = min($a_length, $b_length); - $delimiter_length = strlen($delimiter); - - /* Set the initial result value. */ - $result = 0; - /* Check the strings... */ - for ($c = 0; $c < $min_length; ++$c) { - $a_del = substr($a, $c, $delimiter_length); - $b_del = substr($b, $c, $delimiter_length); - - if (($a_del == $delimiter) && ($b_del == $delimiter)) { - $result = 0; - } else if (($a_del == $delimiter) && ($b_del != $delimiter)) { - $result = -1; - } else if (($a_del != $delimiter) && ($b_del == $delimiter)) { - $result = 1; - } else { - $result = strcasecmp($a{$c}, $b{$c}); - } - - if ($result != 0) { - break; - } - } - - /* If one string is a prefix of the other... */ - if ($result == 0) { - if ($a_length < $b_length) { - $result = -1; - } else if ($a_length > $b_length) { - $result = 1; - } - } - - return $result; } /* @@ -447,18 +419,29 @@ function user_strcasecmp($a, $b) { * $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. */ -function sqimap_mailbox_option_list($imap_stream, $show_selected = 0, $folder_skip = 0, $boxes = 0 ) { +function sqimap_mailbox_option_list($imap_stream, $show_selected = 0, $folder_skip = 0, $boxes = 0, + $flag = 'noselect', $use_long_format = false ) { global $username, $data_dir; $mbox_options = ''; - $shorten_box_names = getPref($data_dir, $username, 'mailbox_select_style', SMPREF_OFF); + if ( $use_long_format ) { + $shorten_box_names = 0; + } else { + $shorten_box_names = getPref($data_dir, $username, 'mailbox_select_style', SMPREF_OFF); + } if ($boxes == 0) { $boxes = sqimap_mailbox_list($imap_stream); } + foreach ($boxes as $boxes_part) { - if (!in_array('noselect', $boxes_part['flags'])) { + if ($flag == NULL || !in_array($flag, $boxes_part['flags'])) { $box = $boxes_part['unformatted']; $lowerbox = strtolower($box); @@ -511,45 +494,42 @@ function sqimap_mailbox_list($imap_stream) { $lsub_ary = sqimap_run_command ($imap_stream, $lsub_args, true, $response, $message); - - /* - * Section about removing the last element was removed - * We don't return "* OK" anymore from sqimap_read_data - */ - $sorted_lsub_ary = array(); for ($i = 0, $cnt = count($lsub_ary);$i < $cnt; $i++) { /* - * Workaround for EIMS - * Doesn't work if the mailbox name is multiple lines + * 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]) && - ereg("^(\\* [A-Z]+.*)\\{[0-9]+\\}([ \n\r\t]*)$", + 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)) { - $i++; - $lsub_ary[$i] = $regs[1] . '"' . addslashes(trim($lsub_ary[$i])) . '"' . $regs[2]; + $i++; + $lsub_ary[$i] = $regs[1] . '"' . addslashes(trim($lsub_ary[$i])) . '"' . $regs[2]; + } } $temp_mailbox_name = find_mailbox_name($lsub_ary[$i]); $sorted_lsub_ary[] = $temp_mailbox_name; - if (strtoupper($temp_mailbox_name) == 'INBOX') { + if (!$inbox_subscribed && strtoupper($temp_mailbox_name) == 'INBOX') { $inbox_subscribed = true; } } - $new_ary = array(); - for ($i = 0, $cnt = count($sorted_lsub_ary); $i < $cnt; $i++) { - if (!in_array($sorted_lsub_ary[$i], $new_ary)) { - $new_ary[] = $sorted_lsub_ary[$i]; - } - } - $sorted_lsub_ary = $new_ary; + /* remove duplicates */ + $sorted_lsub_ary = array_unique($sorted_lsub_ary); + + /* natural sort mailboxes */ if (isset($sorted_lsub_ary)) { usort($sorted_lsub_ary, 'user_strcasecmp'); } - $sorted_list_ary = $sorted_lsub_ary; - /* LIST array */ -/* $sorted_list_ary = array(); + /* + * 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 (false) { if (substr($sorted_lsub_ary[$i], -1) == $delimiter) { $mbx = substr($sorted_lsub_ary[$i], 0, strlen($sorted_lsub_ary[$i])-1); } @@ -559,48 +539,38 @@ function sqimap_mailbox_list($imap_stream) { $read = sqimap_run_command ($imap_stream, "LIST \"\" \"$mbx\"", true, $response, $message); -*/ - /* Another workaround for EIMS */ -/* - if (isset($read[1]) && - ereg("^(\\* [A-Z]+.*)\\{[0-9]+\\}([ \n\r\t]*)$", - $read[0], $regs)) { - $read[0] = $regs[1] . '"' . addslashes(trim($read[1])) . '"' . $regs[2]; - } - if (isset($sorted_list_ary[$i])) { - $sorted_list_ary[$i] = ''; + /* 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)) { + $read[0] = $regs[1] . '"' . addslashes(trim($read[1])) . '"' . $regs[2]; + } } if (isset($read[0])) { $sorted_list_ary[$i] = $read[0]; - } - else { + } else { $sorted_list_ary[$i] = ''; } - - if (isset($sorted_list_ary[$i]) && - strtoupper(find_mailbox_name($sorted_list_ary[$i])) == 'INBOX') { - $inbox_in_list = true; - } } -*/ -/* $inbox_in_list = true; */ + /* * Just in case they're not subscribed to their inbox, * we'll get it for them anyway */ - if (!$inbox_subscribed) {/* || !$inbox_in_list) { */ + if (!$inbox_subscribed) { $inbox_ary = sqimap_run_command ($imap_stream, "LIST \"\" \"INBOX\"", true, $response, $message); - /* Another workaround for EIMS */ - if (isset($inbox_ary[1]) && - ereg("^(\\* [A-Z]+.*)\\{[0-9]+\\}([ \n\r\t]*)$", + /* 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]*)$", $inbox_ary[0], $regs)) { - $inbox_ary[0] = $regs[1] . '"' . addslashes(trim($inbox_ary[1])) . + $inbox_ary[0] = $regs[1] . '"' . addslashes(trim($inbox_ary[1])) . '"' . $regs[2]; + } } - $sorted_list_ary[] = $inbox_ary[0]; $sorted_lsub_ary[] = find_mailbox_name($inbox_ary[0]); } @@ -612,36 +582,24 @@ function sqimap_mailbox_list($imap_stream) { /* Find INBOX */ $cnt = count($boxesall); - for($k = 0; $k < $cnt; $k++) { + $used = array_pad($used,$cnt,false); + for($k = 0; $k < $cnt; ++$k) { if (strtolower($boxesall[$k]['unformatted']) == 'inbox') { $boxesnew[] = $boxesall[$k]; $used[$k] = true; - } else { - $used[$k] = false; + break; } } /* List special folders and their subfolders, if requested. */ if ($list_special_folders_first) { - for($k = 0; $k < $cnt; $k++) { + for($k = 0; $k < $cnt; ++$k) { if (!$used[$k] && isSpecialMailbox($boxesall[$k]['unformatted'])) { $boxesnew[] = $boxesall[$k]; $used[$k] = true; } - $spec_sub = str_replace(' ', '', $boxesall[$k]['formatted']); - $spec_sub = preg_replace("/(\*|\[|\]|\(|\)|\?|\+|\{|\}|\^|\\$)/", '\\\\'.'\\1', $spec_sub); - - /* In case of problems with preg - here is a ereg version - if (!$used[$k] && ereg("^$default_folder_prefix(Sent|Drafts|Trash).{1}$spec_sub$", $box['unformatted']) ) { - */ - $match = "?^$default_folder_prefix(Sent|Drafts|Trash).{1}$spec_sub$?"; - if (!$used[$k] && preg_match($match, $boxesall[$k]['unformatted']) ) { - $boxesnew[] = $boxesall[$k]; - $used[$k] = true; - } - } + } + } - } /* Rest of the folders */ for($k = 0; $k < $cnt; $k++) { if (!$used[$k]) { @@ -937,35 +895,4 @@ function sqimap_fill_mailbox_tree($mbx_ary, $mbxs=false) { return $mailboxes; } -function sqimap_mailbox_has_children($mailbox='INBOX',$stream=false) { - if (!$stream) { - /* We weren't provided an IMAP stream - make one */ - global $username,$imapServerAddress, $imapPort; - $password=$_COOKIE['key']; - $stream=sqimap_login($username,$password,$imapServerAddress,$imapPort,false); - $log_this_out=true; - } - $query = 'LIST "" "' . $mailbox . '"'; - $results=sqimap_run_command($stream,$query,true,$response,$message,false); - if (isset($log_this_out)) { - /* It's our stream, and since we're done with it... */ - sqimap_logout($stream); - } - if (isset($results[0])) { - /* We got something back, let's parse the results */ - $pos = strpos($results[0], '\HasChildren'); - if ($pos === false) { - /* Folder has no children */ - return false; - } else { - /* Folder has children */ - return true; - } - } else { - /* Didn't get anything back, probably bad mailbox name */ - return false; - } - return true; -} - ?>