X-Git-Url: https://vcs.fsf.org/?p=squirrelmail.git;a=blobdiff_plain;f=functions%2Fimap_mailbox.php;h=56f814aeae8544fbe503c7d8ce84642f3b94e318;hp=921ec31b2099ff2e5ef4cf77ba6750eb3ee38b3e;hb=426815a31523da074c7ee9d31be791f2f67a7d7a;hpb=202bcbcc2b67c7c153db1b09b608b62beeba0496 diff --git a/functions/imap_mailbox.php b/functions/imap_mailbox.php index 921ec31b..56f814ae 100755 --- a/functions/imap_mailbox.php +++ b/functions/imap_mailbox.php @@ -5,7 +5,7 @@ * * This implements all functions that manipulate mailboxes * - * @copyright © 1999-2006 The SquirrelMail Project Team + * @copyright © 1999-2007 The SquirrelMail Project Team * @license http://opensource.org/licenses/gpl-license.php GNU Public License * @version $Id$ * @package squirrelmail @@ -220,15 +220,20 @@ function isBoxBelow( $subbox, $parentbox ) { * Since 1.2.5 function includes special_mailbox hook.
* 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. * @return boolean * @since 1.2.3 */ -function isSpecialMailbox( $box ) { +function isSpecialMailbox($box,$include_subs=true) { $ret = ( (strtolower($box) == 'inbox') || - isTrashMailbox($box) || isSentMailbox($box) || isDraftMailbox($box) ); + isTrashMailbox($box,$include_subs) || + isSentMailbox($box,$include_subs) || + isDraftMailbox($box,$include_subs) ); if ( !$ret ) { - $ret = boolean_hook_function('special_mailbox',$box,1); + $ret = boolean_hook_function('special_mailbox', $box, 1); } return $ret; } @@ -236,37 +241,46 @@ function isSpecialMailbox( $box ) { /** * 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 * @since 1.4.0 */ -function isTrashMailbox ($box) { +function isTrashMailbox ($box,$include_subs=true) { global $trash_folder, $move_to_trash; return $move_to_trash && $trash_folder && - ( $box == $trash_folder || isBoxBelow($box, $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 * @since 1.4.0 */ -function isSentMailbox($box) { +function isSentMailbox($box,$include_subs=true) { global $sent_folder, $move_to_sent; return $move_to_sent && $sent_folder && - ( $box == $sent_folder || isBoxBelow($box, $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 * @since 1.4.0 */ -function isDraftMailbox($box) { +function isDraftMailbox($box,$include_subs=true) { global $draft_folder, $save_as_draft; return $save_as_draft && - ( $box == $draft_folder || isBoxBelow($box, $draft_folder) ); + ( $box == $draft_folder || + ($include_subs && isBoxBelow($box, $draft_folder)) ); } /** @@ -339,19 +353,37 @@ function sqimap_mailbox_exists ($imap_stream, $mailbox, $mailboxlist=null) { /** * Selects a mailbox - * Before 1.3.0 used more arguments and returned data depended on those argumements. + * 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) * @since 1.0 or older */ function sqimap_mailbox_select ($imap_stream, $mailbox) { - // FIX ME: WHAAAA DO NOT USE "None" for something that does not exist. Use false or NULL instead - if ($mailbox == 'None') { + if (empty($mailbox)) { return; } + // 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) == '/') { + global $oTemplate; + error_box(sprintf(_("Invalid mailbox name: %s"),htmlspecialchars($mailbox))); + sqimap_logout($imap_stream); + $oTemplate->display('footer.tpl'); + die(); + } + $read = sqimap_run_command($imap_stream, 'SELECT ' . sqimap_encode_mailbox_name($mailbox), true, $response, $message); $result = array(); @@ -453,7 +485,8 @@ function sqimap_mailbox_delete ($imap_stream, $mailbox) { // subscribe again sqimap_subscribe ($imap_stream, $mailbox); } else { - do_hook_function('rename_or_delete_folder', $args = array($mailbox, 'delete', '')); + $temp = array(&$mailbox, 'delete', ''); + do_hook('rename_or_delete_folder', $temp); removePref($data_dir, $username, "thread_$mailbox"); removePref($data_dir, $username, "collapse_folder_$mailbox"); } @@ -508,7 +541,8 @@ function sqimap_mailbox_rename( $imap_stream, $old_name, $new_name ) { sqimap_subscribe($imap_stream, $new_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)); + $temp = array(&$old_name, 'rename', &$new_name); + do_hook('rename_or_delete_folder', $temp); $l = strlen( $old_name ) + 1; $p = 'unformatted'; @@ -534,8 +568,8 @@ function sqimap_mailbox_rename( $imap_stream, $old_name, $new_name ) { } setPref($data_dir, $username, 'thread_'.$new_sub, $oldpref_thread); setPref($data_dir, $username, 'collapse_folder_'.$new_sub, $oldpref_collapse); - do_hook_function('rename_or_delete_folder', - $args = array($box[$p], 'rename', $new_sub)); + $temp = array(&$box[$p], 'rename', &$new_sub); + do_hook('rename_or_delete_folder', $temp); } } } @@ -637,39 +671,31 @@ function sqimap_mailbox_parse ($line) { } /** - * Returns list of options (to be echoed into select statement - * based on available mailboxes and separators - * Caller should surround options with and - * any formatting. - * @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 - * @since 1.3.2 + * Returns an array of mailboxes available. Separated from sqimap_mailbox_option_list() + * below for template development. + * + * @author Steve Brown + * @since 1.5.2 */ -function sqimap_mailbox_option_list($imap_stream, $show_selected = 0, $folder_skip = 0, $boxes = 0, +function sqimap_mailbox_option_array($imap_stream, $folder_skip = 0, $boxes = 0, $flag = 'noselect', $use_long_format = false ) { - global $username, $data_dir; + global $username, $data_dir, $translate_special_folders, $sent_folder, + $trash_folder, $draft_folder; + + $delimiter = sqimap_get_delimiter($imap_stream); + $mbox_options = ''; if ( $use_long_format ) { $shorten_box_names = 0; } else { - $shorten_box_names = getPref($data_dir, $username, 'mailbox_select_style', SMPREF_OFF); + $shorten_box_names = getPref($data_dir, $username, 'mailbox_select_style', SMPREF_MAILBOX_SELECT_INDENTED); } if ($boxes == 0) { $boxes = sqimap_mailbox_list($imap_stream); } + $a = array(); foreach ($boxes as $boxes_part) { if ($flag == NULL || (is_array($boxes_part['flags']) && !in_array($flag, $boxes_part['flags']))) { @@ -687,25 +713,98 @@ function sqimap_mailbox_option_list($imap_stream, $show_selected = 0, $folder_sk } else { switch ($shorten_box_names) { - case 2: /* delimited, style = 2 */ - $box2 = str_replace('&nbsp;&nbsp;', '. ', htmlspecialchars($boxes_part['formatted'])); + case SMPREF_MAILBOX_SELECT_DELIMITED: + 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. + */ + $pad = str_pad('',7 * (count(explode($delimiter,$boxes_part['unformatted-dm']))-1),'. '); + // i18n: Name of Sent folder + $box2 = $pad . _("Sent"); + } elseif ($translate_special_folders && $boxes_part['unformatted-dm']==$trash_folder) { + $pad = str_pad('',7 * (count(explode($delimiter,$boxes_part['unformatted-dm']))-1),'. '); + // i18n: Name of Trash folder + $box2 = $pad . _("Trash"); + } elseif ($translate_special_folders && $boxes_part['unformatted-dm']==$draft_folder) { + $pad = str_pad('',7 * (count(explode($delimiter,$boxes_part['unformatted-dm']))-1),'. '); + // i18n: Name of Drafts folder + $box2 = $pad . _("Drafts"); + } else { + $box2 = str_replace('&nbsp;&nbsp;', '. ', htmlspecialchars($boxes_part['formatted'])); + } break; - case 1: /* indent, style = 1 */ - $box2 = str_replace('&nbsp;&nbsp;', '  ', htmlspecialchars($boxes_part['formatted'])); + case SMPREF_MAILBOX_SELECT_INDENTED: + 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"); + } else { + $box2 = str_replace('&nbsp;&nbsp;', '  ', htmlspecialchars($boxes_part['formatted'])); + } break; default: /* default, long names, style = 0 */ $box2 = str_replace(' ', ' ', htmlspecialchars(imap_utf7_decode_local($boxes_part['unformatted-disp']))); break; } } - if ($show_selected != 0 && in_array($lowerbox, $show_selected) ) { - $mbox_options .= '' . "\n"; - } else { - $mbox_options .= '' . "\n"; + + $a[htmlspecialchars($box)] = $box2; + } + } + + return $a; +} + +/** + * Returns list of options (to be echoed into select statement + * based on available mailboxes and separators + * Caller should surround options with and + * any formatting. + * @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 + * @since 1.3.2 + */ +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, $translate_special_folders, $sent_folder, + $trash_folder, $draft_folder; + + $boxes = sqimap_mailbox_option_array($imap_stream, $folder_skip, $boxes, $flag, $use_long_format); + + $str = ''; + foreach ($boxes as $value=>$option) { + $lowerbox = strtolower(htmlspecialchars($value)); + $sel = false; + if ($show_selected != 0) { + reset($show_selected); + while (!$sel && (list($x, $val) = each($show_selected))) { + if (strtolower($value) == strtolower(htmlspecialchars($val))) { + $sel = true; + } } } + + $str .= '\n"; } - return $mbox_options; + + return $str; } /** @@ -1152,17 +1251,27 @@ function sqimap_fill_mailbox_tree($mbx_ary, $mbxs=false,$imap_stream) { * @since 1.5.0 */ function sqimap_utf7_decode_mbx_tree(&$mbx_tree) { + global $draft_folder, $sent_folder, $trash_folder, $translate_special_folders; + + /* decode folder name and set mailboxname_sub */ + if ($translate_special_folders && strtoupper($mbx_tree->mailboxname_full) == 'INBOX') { + $mbx_tree->mailboxname_sub = _("INBOX"); + } elseif ($translate_special_folders && $mbx_tree->mailboxname_full == $draft_folder) { + $mbx_tree->mailboxname_sub = _("Drafts"); + } elseif ($translate_special_folders && $mbx_tree->mailboxname_full == $sent_folder) { + $mbx_tree->mailboxname_sub = _("Sent"); + } elseif ($translate_special_folders && $mbx_tree->mailboxname_full == $trash_folder) { + $mbx_tree->mailboxname_sub = _("Trash"); + } else { + $mbx_tree->mailboxname_sub = imap_utf7_decode_local($mbx_tree->mailboxname_sub); + } - if (strtoupper($mbx_tree->mailboxname_full) == 'INBOX') - $mbx_tree->mailboxname_sub = _("INBOX"); - else - $mbx_tree->mailboxname_sub = imap_utf7_decode_local($mbx_tree->mailboxname_sub); - if ($mbx_tree->mbxs) { - $iCnt = count($mbx_tree->mbxs); - for ($i=0;$i<$iCnt;++$i) { + if ($mbx_tree->mbxs) { + $iCnt = count($mbx_tree->mbxs); + for ($i=0;$i<$iCnt;++$i) { sqimap_utf7_decode_mbx_tree($mbx_tree->mbxs[$i]); - } - } + } + } } /** @@ -1273,7 +1382,7 @@ function sqimap_get_status_mbx_tree($imap_stream,&$mbx_tree) { { $hook_status['MAILBOX']=$oMbx->mailboxname_full; $hook_status['CALLER']='sqimap_get_status_mbx_tree'; // helps w/ debugging - do_hook_function('folder_status',$hook_status); + do_hook('folder_status', $hook_status); } } } @@ -1319,5 +1428,3 @@ function sqimap_mailbox_is_noinferiors($oImapStream,$sImapFolder,&$oBoxes) { } return false; } - -?>