| | |
| | | // reset some session parameters when changing task |
| | | if ($this->task != 'utils') { |
| | | // we reset list page when switching to another task |
| | | // but only to the main task interface - empty action (#1489076) |
| | | // but only to the main task interface - empty action (#1489076, #1490116) |
| | | // this will prevent from unintentional page reset on cross-task requests |
| | | if ($this->session && $_SESSION['task'] != $this->task && empty($this->action)) { |
| | | $this->session->remove('page'); |
| | | } |
| | | |
| | | // set current task to session |
| | | $_SESSION['task'] = $this->task; |
| | | // set current task to session |
| | | $_SESSION['task'] = $this->task; |
| | | } |
| | | } |
| | | |
| | | // init output class |
| | | if (!empty($_REQUEST['_remote'])) |
| | | // init output class (not in CLI mode) |
| | | if (!empty($_REQUEST['_remote'])) { |
| | | $GLOBALS['OUTPUT'] = $this->json_init(); |
| | | else |
| | | } |
| | | else if ($_SERVER['REMOTE_ADDR']) { |
| | | $GLOBALS['OUTPUT'] = $this->load_gui(!empty($_REQUEST['_framed'])); |
| | | } |
| | | |
| | | // load plugins |
| | | $this->plugins->init($this, $this->task); |
| | |
| | | $this->task = $task; |
| | | $this->comm_path = $this->url(array('task' => $this->task)); |
| | | |
| | | if (!empty($_REQUEST['_framed'])) { |
| | | $this->comm_path .= '&_framed=1'; |
| | | } |
| | | |
| | | if ($this->output) { |
| | | $this->output->set_env('task', $this->task); |
| | | $this->output->set_env('comm_path', $this->comm_path); |
| | | } |
| | | } |
| | | |
| | |
| | | setlocale(LC_ALL, $lang . '.utf8', $lang . '.UTF-8', 'en_US.utf8', 'en_US.UTF-8'); |
| | | |
| | | // workaround for http://bugs.php.net/bug.php?id=18556 |
| | | if (version_compare(PHP_VERSION, '5.5.0', '<') && in_array($lang, array('tr_TR', 'ku', 'az_AZ'))) { |
| | | if (PHP_VERSION_ID < 50500 && in_array($lang, array('tr_TR', 'ku', 'az_AZ'))) { |
| | | setlocale(LC_CTYPE, 'en_US.utf8', 'en_US.UTF-8'); |
| | | } |
| | | } |
| | |
| | | $this->output->set_env('user_id', $this->user->get_hash()); |
| | | } |
| | | |
| | | // set compose mode for all tasks (message compose step can be triggered from everywhere) |
| | | $this->output->set_env('compose_extwin', $this->config->get('compose_extwin',false)); |
| | | |
| | | // add some basic labels to client |
| | | $this->output->add_label('loading', 'servererror', 'connerror', 'requesttimedout', 'refreshing'); |
| | | $this->output->add_label('loading', 'servererror', 'connerror', 'requesttimedout', |
| | | 'refreshing', 'windowopenerror', 'uploadingmany'); |
| | | |
| | | return $this->output; |
| | | } |
| | |
| | | */ |
| | | public function logout_actions() |
| | | { |
| | | $config = $this->config->all(); |
| | | $storage = $this->get_storage(); |
| | | $storage = $this->get_storage(); |
| | | $logout_expunge = $this->config->get('logout_expunge'); |
| | | $logout_purge = $this->config->get('logout_purge'); |
| | | $trash_mbox = $this->config->get('trash_mbox'); |
| | | |
| | | if ($config['logout_purge'] && !empty($config['trash_mbox'])) { |
| | | $storage->clear_folder($config['trash_mbox']); |
| | | if ($logout_purge && !empty($trash_mbox)) { |
| | | $storage->clear_folder($trash_mbox); |
| | | } |
| | | |
| | | if ($config['logout_expunge']) { |
| | | if ($logout_expunge) { |
| | | $storage->expunge_folder('INBOX'); |
| | | } |
| | | |
| | |
| | | /** |
| | | * Build a valid URL to this instance of Roundcube |
| | | * |
| | | * @param mixed Either a string with the action or url parameters as key-value pairs |
| | | * @param mixed Either a string with the action or url parameters as key-value pairs |
| | | * @param boolean Build an URL absolute to document root |
| | | * @param boolean Create fully qualified URL including http(s):// and hostname |
| | | * |
| | | * @return string Valid application URL |
| | | */ |
| | | public function url($p) |
| | | public function url($p, $absolute = false, $full = false) |
| | | { |
| | | if (!is_array($p)) { |
| | | if (strpos($p, 'http') === 0) { |
| | |
| | | $p = array('_action' => @func_get_arg(0)); |
| | | } |
| | | |
| | | $task = $p['_task'] ? $p['_task'] : ($p['task'] ? $p['task'] : $this->task); |
| | | $p['_task'] = $task; |
| | | unset($p['task']); |
| | | $pre = array(); |
| | | $task = $p['_task'] ?: ($p['task'] ?: $this->task); |
| | | $pre['_task'] = $task; |
| | | unset($p['task'], $p['_task']); |
| | | |
| | | $url = './' . $this->filename; |
| | | $url = $this->filename; |
| | | $delm = '?'; |
| | | |
| | | foreach (array_reverse($p) as $key => $val) { |
| | | foreach (array_merge($pre, $p) as $key => $val) { |
| | | if ($val !== '' && $val !== null) { |
| | | $par = $key[0] == '_' ? $key : '_'.$key; |
| | | $url .= $delm.urlencode($par).'='.urlencode($val); |
| | |
| | | } |
| | | } |
| | | |
| | | return $url; |
| | | if ($absolute || $full) { |
| | | // add base path to this Roundcube installation |
| | | $base_path = preg_replace('![^/]+$!', '', strval($_SERVER['SCRIPT_NAME'])); |
| | | if ($base_path == '') $base_path = '/'; |
| | | $prefix = $base_path; |
| | | |
| | | // prepend protocol://hostname:port |
| | | if ($full) { |
| | | $prefix = rcube_utils::resolve_url($prefix); |
| | | } |
| | | |
| | | $prefix = rtrim($prefix, '/') . '/'; |
| | | } |
| | | else { |
| | | $prefix = './'; |
| | | } |
| | | |
| | | return $prefix . $url; |
| | | } |
| | | |
| | | /** |
| | |
| | | $prefix = $this->storage->get_namespace('prefix'); |
| | | $prefix_len = strlen($prefix); |
| | | |
| | | if (!$prefix_len) |
| | | if (!$prefix_len) { |
| | | return; |
| | | } |
| | | |
| | | $prefs = $this->config->all(); |
| | | if (!empty($prefs['namespace_fixed'])) |
| | | if ($this->config->get('namespace_fixed')) { |
| | | return; |
| | | } |
| | | |
| | | $prefs = array(); |
| | | |
| | | // Build namespace prefix regexp |
| | | $ns = $this->storage->get_namespace(); |
| | |
| | | // Fix preferences |
| | | $opts = array('drafts_mbox', 'junk_mbox', 'sent_mbox', 'trash_mbox', 'archive_mbox'); |
| | | foreach ($opts as $opt) { |
| | | if ($value = $prefs[$opt]) { |
| | | if ($value = $this->config->get($opt)) { |
| | | if ($value != 'INBOX' && !preg_match($regexp, $value)) { |
| | | $prefs[$opt] = $prefix.$value; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!empty($prefs['search_mods'])) { |
| | | if (($search_mods = $this->config->get('search_mods')) && !empty($search_mods)) { |
| | | $folders = array(); |
| | | foreach ($prefs['search_mods'] as $idx => $value) { |
| | | foreach ($search_mods as $idx => $value) { |
| | | if ($idx != 'INBOX' && $idx != '*' && !preg_match($regexp, $idx)) { |
| | | $idx = $prefix.$idx; |
| | | } |
| | |
| | | $prefs['search_mods'] = $folders; |
| | | } |
| | | |
| | | if (!empty($prefs['message_threading'])) { |
| | | if (($threading = $this->config->get('message_threading')) && !empty($threading)) { |
| | | $folders = array(); |
| | | foreach ($prefs['message_threading'] as $idx => $value) { |
| | | foreach ($threading as $idx => $value) { |
| | | if ($idx != 'INBOX' && !preg_match($regexp, $idx)) { |
| | | $idx = $prefix.$idx; |
| | | } |
| | |
| | | $prefs['message_threading'] = $folders; |
| | | } |
| | | |
| | | if (!empty($prefs['collapsed_folders'])) { |
| | | $folders = explode('&&', $prefs['collapsed_folders']); |
| | | if ($collapsed = $this->config->get('collapsed_folders')) { |
| | | $folders = explode('&&', $collapsed); |
| | | $count = count($folders); |
| | | $folders_str = ''; |
| | | |
| | |
| | | } |
| | | else { |
| | | foreach ($table_data as $row_data) { |
| | | $class = !empty($row_data['class']) ? $row_data['class'] : ''; |
| | | $class = !empty($row_data['class']) ? $row_data['class'] : null; |
| | | if (!empty($attrib['rowclass'])) |
| | | $class = trim($class . ' ' . $attrib['rowclass']); |
| | | $rowid = 'rcmrow' . rcube_utils::html_identifier($row_data[$id_col]); |
| | | |
| | | $table->add_row(array('id' => $rowid, 'class' => $class)); |
| | | |
| | | // format each col |
| | | foreach ($a_show_cols as $col) { |
| | | $table->add($col, $this->Q(is_array($row_data[$col]) ? $row_data[$col][0] : $row_data[$col])); |
| | | $val = is_array($row_data[$col]) ? $row_data[$col][0] : $row_data[$col]; |
| | | $table->add($col, empty($attrib['ishtml']) ? $this->Q($val) : $val); |
| | | } |
| | | } |
| | | } |
| | |
| | | */ |
| | | public function folder_selector($p = array()) |
| | | { |
| | | $p += array('maxlength' => 100, 'realnames' => false, 'is_escaped' => true); |
| | | $realnames = $this->config->get('show_real_foldernames'); |
| | | $p += array('maxlength' => 100, 'realnames' => $realnames, 'is_escaped' => true); |
| | | $a_mailboxes = array(); |
| | | $storage = $this->get_storage(); |
| | | |
| | |
| | | $html_name = $this->Q($foldername) . ($unread ? html::span('unreadcount', sprintf($attrib['unreadwrap'], $unread)) : ''); |
| | | $link_attrib = $folder['virtual'] ? array() : array( |
| | | 'href' => $this->url(array('_mbox' => $folder['id'])), |
| | | 'onclick' => sprintf("return %s.command('list','%s',this)", rcmail_output::JS_OBJECT_NAME, $js_name), |
| | | 'onclick' => sprintf("return %s.command('list','%s',this,event)", rcmail_output::JS_OBJECT_NAME, $js_name), |
| | | 'rel' => $folder['id'], |
| | | 'title' => $title, |
| | | ); |
| | |
| | | } |
| | | |
| | | |
| | | public function quota_content($attrib = null) |
| | | public function quota_content($attrib = null, $folder = null) |
| | | { |
| | | $quota = $this->storage->get_quota(); |
| | | $quota = $this->storage->get_quota($folder); |
| | | $quota = $this->plugins->exec_hook('quota', $quota); |
| | | |
| | | $quota_result = (array) $quota; |
| | | $quota_result['type'] = isset($_SESSION['quota_display']) ? $_SESSION['quota_display'] : ''; |
| | | $quota_result['type'] = isset($_SESSION['quota_display']) ? $_SESSION['quota_display'] : ''; |
| | | $quota_result['folder'] = $folder !== null && $folder !== '' ? $folder : 'INBOX'; |
| | | |
| | | if ($quota['total'] > 0) { |
| | | if (!isset($quota['percent'])) { |
| | |
| | | $quota_result['width'] = $attrib['width']; |
| | | } |
| | | if ($attrib['height']) { |
| | | $quota_result['height'] = $attrib['height']; |
| | | $quota_result['height'] = $attrib['height']; |
| | | } |
| | | |
| | | // build a table of quota types/roots info |
| | | if (($root_cnt = count($quota_result['all'])) > 1 || count($quota_result['all'][key($quota_result['all'])]) > 1) { |
| | | $table = new html_table(array('cols' => 3, 'class' => 'quota-info')); |
| | | |
| | | $table->add_header(null, self::Q($this->gettext('quotatype'))); |
| | | $table->add_header(null, self::Q($this->gettext('quotatotal'))); |
| | | $table->add_header(null, self::Q($this->gettext('quotaused'))); |
| | | |
| | | foreach ($quota_result['all'] as $root => $data) { |
| | | if ($root_cnt > 1 && $root) { |
| | | $table->add(array('colspan' => 3, 'class' => 'root'), self::Q($root)); |
| | | } |
| | | |
| | | if ($storage = $data['storage']) { |
| | | $percent = min(100, round(($storage['used']/max(1,$storage['total']))*100)); |
| | | |
| | | $table->add('name', self::Q($this->gettext('quotastorage'))); |
| | | $table->add(null, $this->show_bytes($storage['total'] * 1024)); |
| | | $table->add(null, sprintf('%s (%.0f%%)', $this->show_bytes($storage['used'] * 1024), $percent)); |
| | | } |
| | | if ($message = $data['message']) { |
| | | $percent = min(100, round(($message['used']/max(1,$message['total']))*100)); |
| | | |
| | | $table->add('name', self::Q($this->gettext('quotamessage'))); |
| | | $table->add(null, intval($message['total'])); |
| | | $table->add(null, sprintf('%d (%.0f%%)', $message['used'], $percent)); |
| | | } |
| | | } |
| | | |
| | | $quota_result['table'] = $table->show(); |
| | | } |
| | | } |
| | | else { |
| | | $unlimited = $this->config->get('quota_zero_as_unlimited'); |
| | | $quota_result['title'] = $this->gettext($unlimited ? 'unlimited' : 'unknown'); |
| | | $quota_result['percent'] = 0; |
| | | } |
| | | |
| | | // cleanup |
| | | unset($quota_result['abort']); |
| | | if (empty($quota_result['table'])) { |
| | | unset($quota_result['all']); |
| | | } |
| | | |
| | | return $quota_result; |
| | |
| | | $error = 'errorreadonly'; |
| | | } |
| | | else if ($res_code == rcube_storage::OVERQUOTA) { |
| | | $error = 'errorroverquota'; |
| | | $error = 'erroroverquota'; |
| | | } |
| | | else if ($err_code && ($err_str = $this->storage->get_error_str())) { |
| | | // try to detect access rights problem and display appropriate message |
| | |
| | | return; |
| | | } |
| | | |
| | | $lang = strtolower($_SESSION['language']); |
| | | $lang_codes = array($_SESSION['language']); |
| | | |
| | | // TinyMCE uses two-letter lang codes, with exception of Chinese |
| | | if (strpos($lang, 'zh_') === 0) { |
| | | $lang = str_replace('_', '-', $lang); |
| | | } |
| | | else { |
| | | $lang = substr($lang, 0, 2); |
| | | if ($pos = strpos($_SESSION['language'], '_')) { |
| | | $lang_codes[] = substr($_SESSION['language'], 0, $pos); |
| | | } |
| | | |
| | | if (!file_exists(INSTALL_PATH . 'program/js/tiny_mce/langs/'.$lang.'.js')) { |
| | | foreach ($lang_codes as $code) { |
| | | if (file_exists(INSTALL_PATH . 'program/js/tinymce/langs/'.$code.'.js')) { |
| | | $lang = $code; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (empty($lang)) { |
| | | $lang = 'en'; |
| | | } |
| | | |
| | | $script = json_encode(array( |
| | | $config = array( |
| | | 'mode' => $mode, |
| | | 'lang' => $lang, |
| | | 'skin_path' => $this->output->get_skin_path(), |
| | | 'spellcheck' => intval($this->config->get('enable_spellcheck')), |
| | | 'spelldict' => intval($this->config->get('spellcheck_dictionary')) |
| | | )); |
| | | ); |
| | | |
| | | $this->output->include_script('tiny_mce/tiny_mce.js'); |
| | | $this->output->add_label('selectimage', 'addimage', 'selectmedia', 'addmedia'); |
| | | $this->output->set_env('editor_config', $config); |
| | | $this->output->include_css('program/js/tinymce/roundcube/browser.css'); |
| | | $this->output->include_script('tinymce/tinymce.min.js'); |
| | | $this->output->include_script('editor.js'); |
| | | $this->output->add_script("rcmail_editor_init($script)", 'docready'); |
| | | } |
| | | |
| | | /** |
| | |
| | | ); |
| | | |
| | | foreach ($emoticons as $idx => $file) { |
| | | // <img title="Cry" src="http://.../program/js/tiny_mce/plugins/emotions/img/smiley-cry.gif" border="0" alt="Cry" /> |
| | | $search[] = '/<img title="[a-z ]+" src="https?:\/\/[a-z0-9_.\/-]+\/tiny_mce\/plugins\/emotions\/img\/'.$file.'.gif"[^>]+\/>/i'; |
| | | // <img title="Cry" src="http://.../program/js/tinymce/plugins/emoticons/img/smiley-cry.gif" border="0" alt="Cry" /> |
| | | $search[] = '/<img title="[a-z ]+" src="https?:\/\/[a-z0-9_.\/-]+\/tinymce\/plugins\/emoticons\/img\/'.$file.'.gif"[^>]+\/>/i'; |
| | | $replace[] = $idx; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | if (!empty($params['total'])) { |
| | | $params['percent'] = round($status['current']/$status['total']*100); |
| | | $total = $this->show_bytes($params['total'], $unit); |
| | | switch ($unit) { |
| | | case 'GB': |
| | | $gb = $params['current']/1073741824; |
| | | $current = sprintf($gb >= 10 ? "%d" : "%.1f", $gb); |
| | | break; |
| | | case 'MB': |
| | | $mb = $params['current']/1048576; |
| | | $current = sprintf($mb >= 10 ? "%d" : "%.1f", $mb); |
| | | break; |
| | | case 'KB': |
| | | $current = round($params['current']/1024); |
| | | break; |
| | | case 'B': |
| | | default: |
| | | $current = $params['current']; |
| | | break; |
| | | } |
| | | |
| | | $params['percent'] = round($params['current']/$params['total']*100); |
| | | $params['text'] = $this->gettext(array( |
| | | 'name' => 'uploadprogress', |
| | | 'vars' => array( |
| | | 'percent' => $params['percent'] . '%', |
| | | 'current' => $this->show_bytes($params['current']), |
| | | 'total' => $this->show_bytes($params['total']) |
| | | 'current' => $current, |
| | | 'total' => $total |
| | | ) |
| | | )); |
| | | } |
| | |
| | | |
| | | /** |
| | | * Initializes file uploading interface. |
| | | * |
| | | * @param $int Optional maximum file size in bytes |
| | | */ |
| | | public function upload_init() |
| | | public function upload_init($max_size = null) |
| | | { |
| | | // Enable upload progress bar |
| | | if ($seconds = $this->config->get('upload_progress')) { |
| | |
| | | $max_filesize = $max_postsize; |
| | | } |
| | | |
| | | if ($max_size && $max_size < $max_filesize) { |
| | | $max_filesize = $max_size; |
| | | } |
| | | |
| | | $this->output->set_env('max_filesize', $max_filesize); |
| | | $max_filesize = $this->show_bytes($max_filesize); |
| | | $this->output->set_env('filesizeerror', $this->gettext(array( |
| | | 'name' => 'filesizeerror', 'vars' => array('size' => $max_filesize)))); |
| | | |
| | | return $max_filesize; |
| | | } |
| | | |
| | | /** |
| | | * Outputs uploaded file content (with image thumbnails support |
| | | * |
| | | * @param array $file Upload file data |
| | | */ |
| | | public function display_uploaded_file($file) |
| | | { |
| | | if (empty($file)) { |
| | | return; |
| | | } |
| | | |
| | | $file = $this->plugins->exec_hook('attachment_display', $file); |
| | | |
| | | if ($file['status']) { |
| | | if (empty($file['size'])) { |
| | | $file['size'] = $file['data'] ? strlen($file['data']) : @filesize($file['path']); |
| | | } |
| | | |
| | | // generate image thumbnail for file browser in HTML editor |
| | | if (!empty($_GET['_thumbnail'])) { |
| | | $temp_dir = $this->config->get('temp_dir'); |
| | | $thumbnail_size = 80; |
| | | list(,$ext) = explode('/', $file['mimetype']); |
| | | $mimetype = $file['mimetype']; |
| | | $file_ident = $file['id'] . ':' . $file['mimetype'] . ':' . $file['size']; |
| | | $cache_basename = $temp_dir . '/' . md5($file_ident . ':' . $this->user->ID . ':' . $thumbnail_size); |
| | | $cache_file = $cache_basename . '.' . $ext; |
| | | |
| | | // render thumbnail image if not done yet |
| | | if (!is_file($cache_file)) { |
| | | if (!$file['path']) { |
| | | $orig_name = $filename = $cache_basename . '.orig.' . $ext; |
| | | file_put_contents($orig_name, $file['data']); |
| | | } |
| | | else { |
| | | $filename = $file['path']; |
| | | } |
| | | |
| | | $image = new rcube_image($filename); |
| | | if ($imgtype = $image->resize($thumbnail_size, $cache_file, true)) { |
| | | $mimetype = 'image/' . $imgtype; |
| | | |
| | | if ($orig_name) { |
| | | unlink($orig_name); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (is_file($cache_file)) { |
| | | // cache for 1h |
| | | $this->output->future_expire_header(3600); |
| | | header('Content-Type: ' . $mimetype); |
| | | header('Content-Length: ' . filesize($cache_file)); |
| | | |
| | | readfile($cache_file); |
| | | exit; |
| | | } |
| | | } |
| | | |
| | | header('Content-Type: ' . $file['mimetype']); |
| | | header('Content-Length: ' . $file['size']); |
| | | |
| | | if ($file['data']) { |
| | | echo $file['data']; |
| | | } |
| | | else if ($file['path']) { |
| | | readfile($file['path']); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | /** |
| | | * Create a human readable string for a number of bytes |
| | | * |
| | | * @param int Number of bytes |
| | | * @param int Number of bytes |
| | | * @param string Size unit |
| | | * |
| | | * @return string Byte string |
| | | */ |
| | | public function show_bytes($bytes) |
| | | public function show_bytes($bytes, &$unit = null) |
| | | { |
| | | if ($bytes >= 1073741824) { |
| | | $gb = $bytes/1073741824; |
| | | $str = sprintf($gb>=10 ? "%d " : "%.1f ", $gb) . $this->gettext('GB'); |
| | | $unit = 'GB'; |
| | | $gb = $bytes/1073741824; |
| | | $str = sprintf($gb >= 10 ? "%d " : "%.1f ", $gb) . $this->gettext($unit); |
| | | } |
| | | else if ($bytes >= 1048576) { |
| | | $mb = $bytes/1048576; |
| | | $str = sprintf($mb>=10 ? "%d " : "%.1f ", $mb) . $this->gettext('MB'); |
| | | $unit = 'MB'; |
| | | $mb = $bytes/1048576; |
| | | $str = sprintf($mb >= 10 ? "%d " : "%.1f ", $mb) . $this->gettext($unit); |
| | | } |
| | | else if ($bytes >= 1024) { |
| | | $str = sprintf("%d ", round($bytes/1024)) . $this->gettext('KB'); |
| | | $unit = 'KB'; |
| | | $str = sprintf("%d ", round($bytes/1024)) . $this->gettext($unit); |
| | | } |
| | | else { |
| | | $str = sprintf('%d ', $bytes) . $this->gettext('B'); |
| | | $unit = 'B'; |
| | | $str = sprintf('%d ', $bytes) . $this->gettext(); |
| | | } |
| | | |
| | | return $str; |
| | |
| | | /** |
| | | * Returns message UID(s) and IMAP folder(s) from GET/POST data |
| | | * |
| | | * @param string UID value to decode |
| | | * @param string Default mailbox value (if not encoded in UIDs) |
| | | * @param string UID value to decode |
| | | * @param string Default mailbox value (if not encoded in UIDs) |
| | | * @param bool Will be set to True if multi-folder request |
| | | * |
| | | * @return array List of message UIDs per folder |
| | | */ |
| | | public static function get_uids($uids = null, $mbox = null) |
| | | public static function get_uids($uids = null, $mbox = null, &$is_multifolder = false) |
| | | { |
| | | // message UID (or comma-separated list of IDs) is provided in |
| | | // the form of <ID>-<MBOX>[,<ID>-<MBOX>]* |
| | |
| | | |
| | | // special case: * |
| | | if ($_uid == '*' && is_object($_SESSION['search'][1]) && $_SESSION['search'][1]->multi) { |
| | | $is_multifolder = true; |
| | | // extract the full list of UIDs per folder from the search set |
| | | foreach ($_SESSION['search'][1]->sets as $subset) { |
| | | $mbox = $subset->get_parameters('MAILBOX'); |
| | |
| | | // create a per-folder UIDs array |
| | | foreach ((array)$_uid as $uid) { |
| | | list($uid, $mbox) = explode('-', $uid, 2); |
| | | if (!strlen($mbox)) |
| | | if (!strlen($mbox)) { |
| | | $mbox = $_mbox; |
| | | if ($uid == '*') |
| | | } |
| | | else { |
| | | $is_multifolder = true; |
| | | } |
| | | |
| | | if ($uid == '*') { |
| | | $result[$mbox] = $uid; |
| | | else |
| | | } |
| | | else { |
| | | $result[$mbox][] = $uid; |
| | | } |
| | | } |
| | | } |
| | | |