Merged devel-framework branch (r5746:5779) back into trunk
2 files added
1 files deleted
37 files modified
| | |
| | | { |
| | | global $IMAP; |
| | | |
| | | $IMAP->set_mailbox($mbox); |
| | | $IMAP->set_folder($mbox); |
| | | |
| | | $index = $IMAP->index($mbox, null, 'ASC'); |
| | | $count = $index->countMessages(); |
| | | $index = $index->get(); |
| | | |
| | | vputs("Getting message list of {$mbox}..."); |
| | | vputs($IMAP->messagecount()." messages\n"); |
| | | vputs("$count messages\n"); |
| | | |
| | | if ($filename) |
| | | { |
| | |
| | | else |
| | | $out = STDOUT; |
| | | |
| | | for ($count = $IMAP->messagecount(), $i=1; $i <= $count; $i++) |
| | | for ($i = 0; $i < $count; $i++) |
| | | { |
| | | $headers = $IMAP->get_headers($i, null, false); |
| | | $headers = $IMAP->get_message_headers($index[$i]); |
| | | $from = current(rcube_mime::decode_address_list($headers->from, 1, false)); |
| | | |
| | | fwrite($out, sprintf("From %s %s UID %d\n", $from['mailto'], $headers->date, $headers->uid)); |
| | | fwrite($out, $IMAP->conn->fetchPartHeader($mbox, $i)); |
| | | fwrite($out, $IMAP->conn->handlePartBody($mbox, $i)); |
| | | fwrite($out, $IMAP->print_raw_body($headers->uid)); |
| | | fwrite($out, "\n\n\n"); |
| | | |
| | | progress_update($i, $count); |
| | | progress_update($i+1, $count); |
| | | } |
| | | vputs("\ncomplete.\n"); |
| | | |
| | |
| | | vputs("IMAP login successful.\n"); |
| | | |
| | | $filename = null; |
| | | $mailboxes = $args['mbox'] == '*' ? $IMAP->list_mailboxes(null) : array($args['mbox']); |
| | | $mailboxes = $args['mbox'] == '*' ? $IMAP->list_folders(null) : array($args['mbox']); |
| | | |
| | | foreach ($mailboxes as $mbox) |
| | | { |
| | |
| | | } |
| | | |
| | | // check DB connections and exit on failure |
| | | if ($err_str = $DB->is_error()) { |
| | | if ($err_str = $RCMAIL->db->is_error()) { |
| | | raise_error(array( |
| | | 'code' => 603, |
| | | 'type' => 'db', |
| | |
| | | $OUTPUT->redirect($redir); |
| | | } |
| | | else { |
| | | $error_code = (isset($RCMAIL->imap) && is_object($RCMAIL->imap)) ? $RCMAIL->imap->get_error_code() : 1; |
| | | $error_code = is_object($RCMAIL->storage) ? $RCMAIL->storage->get_error_code() : 1; |
| | | |
| | | $OUTPUT->show_message($error_code < -1 ? 'imaperror' : (!$auth['valid'] ? 'invalidrequest' : 'loginfailed'), 'warning'); |
| | | $OUTPUT->show_message($error_code < -1 ? 'storageerror' : (!$auth['valid'] ? 'invalidrequest' : 'loginfailed'), 'warning'); |
| | | $RCMAIL->plugins->exec_hook('login_failed', array( |
| | | 'code' => $error_code, 'host' => $auth['host'], 'user' => $auth['user'])); |
| | | $RCMAIL->kill_session(); |
| | |
| | | |
| | | // end session (after optional referer check) |
| | | else if ($RCMAIL->task == 'logout' && isset($_SESSION['user_id']) && (!$RCMAIL->config->get('referer_check') || rcube_check_referer())) { |
| | | $userdata = array('user' => $_SESSION['username'], 'host' => $_SESSION['imap_host'], 'lang' => $RCMAIL->user->language); |
| | | $userdata = array( |
| | | 'user' => $_SESSION['username'], |
| | | 'host' => $_SESSION['storage_host'], |
| | | 'lang' => $RCMAIL->user->language, |
| | | ); |
| | | $OUTPUT->show_message('loggedout'); |
| | | $RCMAIL->logout_actions(); |
| | | $RCMAIL->kill_session(); |
| | |
| | | 'addrbook_show_images' => 'show_images', |
| | | 'imap_root' => 'imap_ns_personal', |
| | | 'pagesize' => 'mail_pagesize', |
| | | 'default_imap_folders' => 'default_folders', |
| | | ); |
| | | |
| | | // these config options are required for a working system |
| | |
| | | else if ($prop == 'smtp_pass' && !empty($_POST['_smtp_user_u'])) { |
| | | $value = '%p'; |
| | | } |
| | | else if ($prop == 'default_imap_folders') { |
| | | else if ($prop == 'default_folders') { |
| | | $value = array(); |
| | | foreach ($this->config['default_imap_folders'] as $_folder) { |
| | | foreach ($this->config['default_folders'] as $_folder) { |
| | | switch ($_folder) { |
| | | case 'Drafts': $_folder = $this->config['drafts_mbox']; break; |
| | | case 'Sent': $_folder = $this->config['sent_mbox']; break; |
old mode 100755
new mode 100644
| | |
| | | * @author Thomas Bruederli <roundcube@gmail.com> |
| | | */ |
| | | |
| | | require_once 'utf7.inc'; |
| | | require_once INSTALL_PATH . 'program/include/rcube_shared.inc'; |
| | | |
| | | // define constannts for input reading |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Catch an error and throw an exception. |
| | | * |
| | | * @param int Level of the error |
| | | * @param string Error message |
| | | */ |
| | | function rcube_error_handler($errno, $errstr) |
| | | { |
| | | throw new ErrorException($errstr, 0, $errno); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Convert a string from one charset to another. |
| | | * Uses mbstring and iconv functions if possible |
| | | * |
| | | * @param string Input string |
| | | * @param string Suspected charset of the input string |
| | | * @param string Target charset to convert to; defaults to RCMAIL_CHARSET |
| | | * @return string Converted string |
| | | */ |
| | | // Deprecated |
| | | function rcube_charset_convert($str, $from, $to=NULL) |
| | | { |
| | | static $iconv_options = null; |
| | | static $mbstring_loaded = null; |
| | | static $mbstring_list = null; |
| | | static $conv = null; |
| | | return rcube_charset::convert($str, $from, $to); |
| | | } |
| | | |
| | | $error = false; |
| | | |
| | | $to = empty($to) ? strtoupper(RCMAIL_CHARSET) : rcube_parse_charset($to); |
| | | $from = rcube_parse_charset($from); |
| | | // Deprecated |
| | | function rc_detect_encoding($string, $failover='') |
| | | { |
| | | return rcube_charset::detect($string, $failover); |
| | | } |
| | | |
| | | if ($from == $to || empty($str) || empty($from)) |
| | | return $str; |
| | | |
| | | // convert charset using iconv module |
| | | if (function_exists('iconv') && $from != 'UTF7-IMAP' && $to != 'UTF7-IMAP') { |
| | | if ($iconv_options === null) { |
| | | // ignore characters not available in output charset |
| | | $iconv_options = '//IGNORE'; |
| | | if (iconv('', $iconv_options, '') === false) { |
| | | // iconv implementation does not support options |
| | | $iconv_options = ''; |
| | | } |
| | | } |
| | | |
| | | // throw an exception if iconv reports an illegal character in input |
| | | // it means that input string has been truncated |
| | | set_error_handler('rcube_error_handler', E_NOTICE); |
| | | try { |
| | | $_iconv = iconv($from, $to . $iconv_options, $str); |
| | | } catch (ErrorException $e) { |
| | | $_iconv = false; |
| | | } |
| | | restore_error_handler(); |
| | | if ($_iconv !== false) { |
| | | return $_iconv; |
| | | } |
| | | } |
| | | |
| | | if ($mbstring_loaded === null) |
| | | $mbstring_loaded = extension_loaded('mbstring'); |
| | | |
| | | // convert charset using mbstring module |
| | | if ($mbstring_loaded) { |
| | | $aliases['WINDOWS-1257'] = 'ISO-8859-13'; |
| | | |
| | | if ($mbstring_list === null) { |
| | | $mbstring_list = mb_list_encodings(); |
| | | $mbstring_list = array_map('strtoupper', $mbstring_list); |
| | | } |
| | | |
| | | $mb_from = $aliases[$from] ? $aliases[$from] : $from; |
| | | $mb_to = $aliases[$to] ? $aliases[$to] : $to; |
| | | |
| | | // return if encoding found, string matches encoding and convert succeeded |
| | | if (in_array($mb_from, $mbstring_list) && in_array($mb_to, $mbstring_list)) { |
| | | if (mb_check_encoding($str, $mb_from) && ($out = mb_convert_encoding($str, $mb_to, $mb_from))) |
| | | return $out; |
| | | } |
| | | } |
| | | |
| | | // convert charset using bundled classes/functions |
| | | if ($to == 'UTF-8') { |
| | | if ($from == 'UTF7-IMAP') { |
| | | if ($_str = utf7_to_utf8($str)) |
| | | return $_str; |
| | | } |
| | | else if ($from == 'UTF-7') { |
| | | if ($_str = rcube_utf7_to_utf8($str)) |
| | | return $_str; |
| | | } |
| | | else if (($from == 'ISO-8859-1') && function_exists('utf8_encode')) { |
| | | return utf8_encode($str); |
| | | } |
| | | else if (class_exists('utf8')) { |
| | | if (!$conv) |
| | | $conv = new utf8($from); |
| | | else |
| | | $conv->loadCharset($from); |
| | | |
| | | if($_str = $conv->strToUtf8($str)) |
| | | return $_str; |
| | | } |
| | | $error = true; |
| | | } |
| | | |
| | | // encode string for output |
| | | if ($from == 'UTF-8') { |
| | | // @TODO: we need a function for UTF-7 (RFC2152) conversion |
| | | if ($to == 'UTF7-IMAP' || $to == 'UTF-7') { |
| | | if ($_str = utf8_to_utf7($str)) |
| | | return $_str; |
| | | } |
| | | else if ($to == 'ISO-8859-1' && function_exists('utf8_decode')) { |
| | | return utf8_decode($str); |
| | | } |
| | | else if (class_exists('utf8')) { |
| | | if (!$conv) |
| | | $conv = new utf8($to); |
| | | else |
| | | $conv->loadCharset($from); |
| | | |
| | | if ($_str = $conv->strToUtf8($str)) |
| | | return $_str; |
| | | } |
| | | $error = true; |
| | | } |
| | | |
| | | // return UTF-8 or original string |
| | | return $str; |
| | | // Deprecated |
| | | function rc_utf8_clean($input) |
| | | { |
| | | return rcube_charset::clean($input); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Parse and validate charset name string (see #1485758). |
| | | * Sometimes charset string is malformed, there are also charset aliases |
| | | * but we need strict names for charset conversion (specially utf8 class) |
| | | * Convert a variable into a javascript object notation |
| | | * |
| | | * @param string Input charset name |
| | | * @return string The validated charset name |
| | | * @param mixed Input value |
| | | * @return string Serialized JSON string |
| | | */ |
| | | function rcube_parse_charset($input) |
| | | function json_serialize($input) |
| | | { |
| | | static $charsets = array(); |
| | | $charset = strtoupper($input); |
| | | $input = rcube_charset::clean($input); |
| | | |
| | | if (isset($charsets[$input])) |
| | | return $charsets[$input]; |
| | | |
| | | $charset = preg_replace(array( |
| | | '/^[^0-9A-Z]+/', // e.g. _ISO-8859-JP$SIO |
| | | '/\$.*$/', // e.g. _ISO-8859-JP$SIO |
| | | '/UNICODE-1-1-*/', // RFC1641/1642 |
| | | '/^X-/', // X- prefix (e.g. X-ROMAN8 => ROMAN8) |
| | | ), '', $charset); |
| | | |
| | | if ($charset == 'BINARY') |
| | | return $charsets[$input] = null; |
| | | |
| | | # Aliases: some of them from HTML5 spec. |
| | | $aliases = array( |
| | | 'USASCII' => 'WINDOWS-1252', |
| | | 'ANSIX31101983' => 'WINDOWS-1252', |
| | | 'ANSIX341968' => 'WINDOWS-1252', |
| | | 'UNKNOWN8BIT' => 'ISO-8859-15', |
| | | 'UNKNOWN' => 'ISO-8859-15', |
| | | 'USERDEFINED' => 'ISO-8859-15', |
| | | 'KSC56011987' => 'EUC-KR', |
| | | 'GB2312' => 'GBK', |
| | | 'GB231280' => 'GBK', |
| | | 'UNICODE' => 'UTF-8', |
| | | 'UTF7IMAP' => 'UTF7-IMAP', |
| | | 'TIS620' => 'WINDOWS-874', |
| | | 'ISO88599' => 'WINDOWS-1254', |
| | | 'ISO885911' => 'WINDOWS-874', |
| | | 'MACROMAN' => 'MACINTOSH', |
| | | '77' => 'MAC', |
| | | '128' => 'SHIFT-JIS', |
| | | '129' => 'CP949', |
| | | '130' => 'CP1361', |
| | | '134' => 'GBK', |
| | | '136' => 'BIG5', |
| | | '161' => 'WINDOWS-1253', |
| | | '162' => 'WINDOWS-1254', |
| | | '163' => 'WINDOWS-1258', |
| | | '177' => 'WINDOWS-1255', |
| | | '178' => 'WINDOWS-1256', |
| | | '186' => 'WINDOWS-1257', |
| | | '204' => 'WINDOWS-1251', |
| | | '222' => 'WINDOWS-874', |
| | | '238' => 'WINDOWS-1250', |
| | | 'MS950' => 'CP950', |
| | | 'WINDOWS949' => 'UHC', |
| | | ); |
| | | |
| | | // allow A-Z and 0-9 only |
| | | $str = preg_replace('/[^A-Z0-9]/', '', $charset); |
| | | |
| | | if (isset($aliases[$str])) |
| | | $result = $aliases[$str]; |
| | | // UTF |
| | | else if (preg_match('/U[A-Z][A-Z](7|8|16|32)(BE|LE)*/', $str, $m)) |
| | | $result = 'UTF-' . $m[1] . $m[2]; |
| | | // ISO-8859 |
| | | else if (preg_match('/ISO8859([0-9]{0,2})/', $str, $m)) { |
| | | $iso = 'ISO-8859-' . ($m[1] ? $m[1] : 1); |
| | | // some clients sends windows-1252 text as latin1, |
| | | // it is safe to use windows-1252 for all latin1 |
| | | $result = $iso == 'ISO-8859-1' ? 'WINDOWS-1252' : $iso; |
| | | } |
| | | // handle broken charset names e.g. WINDOWS-1250HTTP-EQUIVCONTENT-TYPE |
| | | else if (preg_match('/(WIN|WINDOWS)([0-9]+)/', $str, $m)) { |
| | | $result = 'WINDOWS-' . $m[2]; |
| | | } |
| | | // LATIN |
| | | else if (preg_match('/LATIN(.*)/', $str, $m)) { |
| | | $aliases = array('2' => 2, '3' => 3, '4' => 4, '5' => 9, '6' => 10, |
| | | '7' => 13, '8' => 14, '9' => 15, '10' => 16, |
| | | 'ARABIC' => 6, 'CYRILLIC' => 5, 'GREEK' => 7, 'GREEK1' => 7, 'HEBREW' => 8); |
| | | |
| | | // some clients sends windows-1252 text as latin1, |
| | | // it is safe to use windows-1252 for all latin1 |
| | | if ($m[1] == 1) { |
| | | $result = 'WINDOWS-1252'; |
| | | } |
| | | // if iconv is not supported we need ISO labels, it's also safe for iconv |
| | | else if (!empty($aliases[$m[1]])) { |
| | | $result = 'ISO-8859-'.$aliases[$m[1]]; |
| | | } |
| | | // iconv requires convertion of e.g. LATIN-1 to LATIN1 |
| | | else { |
| | | $result = $str; |
| | | } |
| | | } |
| | | else { |
| | | $result = $charset; |
| | | } |
| | | |
| | | $charsets[$input] = $result; |
| | | |
| | | return $result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Converts string from standard UTF-7 (RFC 2152) to UTF-8. |
| | | * |
| | | * @param string Input string |
| | | * @return string The converted string |
| | | */ |
| | | function rcube_utf7_to_utf8($str) |
| | | { |
| | | $Index_64 = array( |
| | | 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, |
| | | 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, |
| | | 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0, |
| | | 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, |
| | | 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, |
| | | 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, |
| | | 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, |
| | | 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, |
| | | ); |
| | | |
| | | $u7len = strlen($str); |
| | | $str = strval($str); |
| | | $res = ''; |
| | | |
| | | for ($i=0; $u7len > 0; $i++, $u7len--) |
| | | { |
| | | $u7 = $str[$i]; |
| | | if ($u7 == '+') |
| | | { |
| | | $i++; |
| | | $u7len--; |
| | | $ch = ''; |
| | | |
| | | for (; $u7len > 0; $i++, $u7len--) |
| | | { |
| | | $u7 = $str[$i]; |
| | | |
| | | if (!$Index_64[ord($u7)]) |
| | | break; |
| | | |
| | | $ch .= $u7; |
| | | } |
| | | |
| | | if ($ch == '') { |
| | | if ($u7 == '-') |
| | | $res .= '+'; |
| | | continue; |
| | | } |
| | | |
| | | $res .= rcube_utf16_to_utf8(base64_decode($ch)); |
| | | } |
| | | else |
| | | { |
| | | $res .= $u7; |
| | | } |
| | | } |
| | | |
| | | return $res; |
| | | } |
| | | |
| | | /** |
| | | * Converts string from UTF-16 to UTF-8 (helper for utf-7 to utf-8 conversion) |
| | | * |
| | | * @param string Input string |
| | | * @return string The converted string |
| | | */ |
| | | function rcube_utf16_to_utf8($str) |
| | | { |
| | | $len = strlen($str); |
| | | $dec = ''; |
| | | |
| | | for ($i = 0; $i < $len; $i += 2) { |
| | | $c = ord($str[$i]) << 8 | ord($str[$i + 1]); |
| | | if ($c >= 0x0001 && $c <= 0x007F) { |
| | | $dec .= chr($c); |
| | | } else if ($c > 0x07FF) { |
| | | $dec .= chr(0xE0 | (($c >> 12) & 0x0F)); |
| | | $dec .= chr(0x80 | (($c >> 6) & 0x3F)); |
| | | $dec .= chr(0x80 | (($c >> 0) & 0x3F)); |
| | | } else { |
| | | $dec .= chr(0xC0 | (($c >> 6) & 0x1F)); |
| | | $dec .= chr(0x80 | (($c >> 0) & 0x3F)); |
| | | } |
| | | } |
| | | return $dec; |
| | | // sometimes even using rcube_charset::clean() the input contains invalid UTF-8 sequences |
| | | // that's why we have @ here |
| | | return @json_encode($input); |
| | | } |
| | | |
| | | |
| | |
| | | $attrib['folder_name'] = '*'; |
| | | |
| | | // get mailbox list |
| | | $mbox_name = $RCMAIL->imap->get_mailbox_name(); |
| | | $mbox_name = $RCMAIL->storage->get_folder(); |
| | | |
| | | // build the folders tree |
| | | if (empty($a_mailboxes)) { |
| | | // get mailbox list |
| | | $a_folders = $RCMAIL->imap->list_mailboxes('', $attrib['folder_name'], $attrib['folder_filter']); |
| | | $delimiter = $RCMAIL->imap->get_hierarchy_delimiter(); |
| | | $a_folders = $RCMAIL->storage->list_folders_subscribed('', $attrib['folder_name'], $attrib['folder_filter']); |
| | | $delimiter = $RCMAIL->storage->get_hierarchy_delimiter(); |
| | | $a_mailboxes = array(); |
| | | |
| | | foreach ($a_folders as $folder) |
| | |
| | | |
| | | $p += array('maxlength' => 100, 'realnames' => false); |
| | | $a_mailboxes = array(); |
| | | $storage = $RCMAIL->get_storage(); |
| | | |
| | | if (empty($p['folder_name'])) |
| | | if (empty($p['folder_name'])) { |
| | | $p['folder_name'] = '*'; |
| | | } |
| | | |
| | | if ($p['unsubscribed']) |
| | | $list = $RCMAIL->imap->list_unsubscribed('', $p['folder_name'], $p['folder_filter'], $p['folder_rights']); |
| | | $list = $storage->list_folders('', $p['folder_name'], $p['folder_filter'], $p['folder_rights']); |
| | | else |
| | | $list = $RCMAIL->imap->list_mailboxes('', $p['folder_name'], $p['folder_filter'], $p['folder_rights']); |
| | | $list = $storage->list_folders_subscribed('', $p['folder_name'], $p['folder_filter'], $p['folder_rights']); |
| | | |
| | | $delimiter = $RCMAIL->imap->get_hierarchy_delimiter(); |
| | | $delimiter = $storage->get_hierarchy_delimiter(); |
| | | |
| | | foreach ($list as $folder) { |
| | | if (empty($p['exceptions']) || !in_array($folder, $p['exceptions'])) |
| | |
| | | $prefix = ''; |
| | | if (!$path) { |
| | | $n_folder = $folder; |
| | | $folder = $RCMAIL->imap->mod_mailbox($folder); |
| | | $folder = $RCMAIL->storage->mod_folder($folder); |
| | | |
| | | if ($n_folder != $folder) { |
| | | $prefix = substr($n_folder, 0, -strlen($folder)); |
| | |
| | | |
| | | $maxlength = intval($attrib['maxlength']); |
| | | $realnames = (bool)$attrib['realnames']; |
| | | $msgcounts = $RCMAIL->imap->get_cache('messagecount'); |
| | | $msgcounts = $RCMAIL->storage->get_cache('messagecount'); |
| | | |
| | | $out = ''; |
| | | foreach ($arrFolders as $key => $folder) { |
| | |
| | | } |
| | | |
| | | // skip folders in which it isn't possible to create subfolders |
| | | if (!empty($opts['skip_noinferiors']) && ($attrs = $RCMAIL->imap->mailbox_attributes($folder['id'])) |
| | | if (!empty($opts['skip_noinferiors']) && ($attrs = $RCMAIL->storage->folder_attributes($folder['id'])) |
| | | && in_array('\\Noinferiors', $attrs) |
| | | ) { |
| | | continue; |
| | |
| | | global $RCMAIL; |
| | | |
| | | $protect_folders = $RCMAIL->config->get('protect_default_folders'); |
| | | $default_folders = (array) $RCMAIL->config->get('default_imap_folders'); |
| | | $delimiter = $RCMAIL->imap->get_hierarchy_delimiter(); |
| | | $default_folders = (array) $RCMAIL->config->get('default_folders'); |
| | | $delimiter = $RCMAIL->storage->get_hierarchy_delimiter(); |
| | | $path = explode($delimiter, $path); |
| | | $result = array(); |
| | | |
| | |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | $quota = $RCMAIL->imap->get_quota(); |
| | | $quota = $RCMAIL->storage->get_quota(); |
| | | $quota = $RCMAIL->plugins->exec_hook('quota', $quota); |
| | | |
| | | $quota_result = (array) $quota; |
| | |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | $err_code = $RCMAIL->imap->get_error_code(); |
| | | $res_code = $RCMAIL->imap->get_response_code(); |
| | | $err_code = $RCMAIL->storage->get_error_code(); |
| | | $res_code = $RCMAIL->storage->get_response_code(); |
| | | |
| | | if ($res_code == rcube_imap::NOPERM) { |
| | | if ($err_code < 0) { |
| | | $RCMAIL->output->show_message('storageerror', 'error'); |
| | | } |
| | | else if ($res_code == rcube_storage::NOPERM) { |
| | | $RCMAIL->output->show_message('errornoperm', 'error'); |
| | | } |
| | | else if ($res_code == rcube_imap::READONLY) { |
| | | else if ($res_code == rcube_storage::READONLY) { |
| | | $RCMAIL->output->show_message('errorreadonly', 'error'); |
| | | } |
| | | else if ($err_code && ($err_str = $RCMAIL->imap->get_error_str())) { |
| | | else if ($err_code && ($err_str = $RCMAIL->storage->get_error_str())) { |
| | | // try to detect access rights problem and display appropriate message |
| | | if (stripos($err_str, 'Permission denied') !== false) |
| | | $RCMAIL->output->show_message('errornoperm', 'error'); |
| | |
| | | // %d - domain name without first part, e.g. %n=mail.domain.tld, %d=domain.tld |
| | | $d = preg_replace('/^[^\.]+\./', '', $n); |
| | | // %h - IMAP host |
| | | $h = $_SESSION['imap_host'] ? $_SESSION['imap_host'] : $host; |
| | | $h = $_SESSION['storage_host'] ? $_SESSION['storage_host'] : $host; |
| | | // %z - IMAP domain without first part, e.g. %h=imap.domain.tld, %z=domain.tld |
| | | $z = preg_replace('/^[^\.]+\./', '', $h); |
| | | // %s - domain name after the '@' from e-mail address provided at login screen. Returns FALSE if an invalid email is provided |
| | |
| | | public $smtp; |
| | | |
| | | /** |
| | | * Instance of rcube_imap class. |
| | | * Instance of rcube_storage class. |
| | | * |
| | | * @var rcube_imap |
| | | * @var rcube_storage |
| | | */ |
| | | public $imap; |
| | | public $storage; |
| | | |
| | | /** |
| | | * Instance of rcube_template class. |
| | |
| | | // connect to database |
| | | $this->get_dbh(); |
| | | |
| | | // set global object for backward compatibility |
| | | $GLOBALS['DB'] = $this->db; |
| | | |
| | | // start session |
| | | $this->session_init(); |
| | | |
| | |
| | | { |
| | | if (is_object($user)) { |
| | | $this->user = $user; |
| | | |
| | | // set global object for backward compatibility |
| | | $GLOBALS['USER'] = $this->user; |
| | | |
| | | // overwrite config with user preferences |
| | | $this->config->set_user_prefs((array)$this->user->get_prefs()); |
| | |
| | | $contacts = $this->address_books[$id]; |
| | | } |
| | | else if ($id && $ldap_config[$id]) { |
| | | $contacts = new rcube_ldap($ldap_config[$id], $this->config->get('ldap_debug'), $this->config->mail_domain($_SESSION['imap_host'])); |
| | | $contacts = new rcube_ldap($ldap_config[$id], $this->config->get('ldap_debug'), $this->config->mail_domain($_SESSION['storage_host'])); |
| | | } |
| | | else if ($id === '0') { |
| | | $contacts = new rcube_contacts($this->db, $this->user->ID); |
| | |
| | | |
| | | |
| | | /** |
| | | * Create global IMAP object and connect to server |
| | | * Initialize and get storage object |
| | | * |
| | | * @param boolean True if connection should be established |
| | | * @return rcube_storage Storage object |
| | | */ |
| | | public function imap_init($connect = false) |
| | | public function get_storage() |
| | | { |
| | | // already initialized |
| | | if (is_object($this->imap)) |
| | | if (!is_object($this->storage)) { |
| | | $this->storage_init(); |
| | | } |
| | | |
| | | return $this->storage; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Connect to the IMAP server with stored session data. |
| | | * |
| | | * @return bool True on success, False on error |
| | | * @deprecated |
| | | */ |
| | | public function imap_connect() |
| | | { |
| | | return $this->storage_connect(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Initialize IMAP object. |
| | | * |
| | | * @deprecated |
| | | */ |
| | | public function imap_init() |
| | | { |
| | | $this->storage_init(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Initialize storage object |
| | | */ |
| | | public function storage_init() |
| | | { |
| | | // already initialized |
| | | if (is_object($this->storage)) { |
| | | return; |
| | | } |
| | | |
| | | $this->imap = new rcube_imap(); |
| | | $this->imap->skip_deleted = $this->config->get('skip_deleted'); |
| | | $driver = $this->config->get('storage_driver', 'imap'); |
| | | $driver_class = "rcube_{$driver}"; |
| | | |
| | | // enable caching of imap data |
| | | $imap_cache = $this->config->get('imap_cache'); |
| | | if (!class_exists($driver_class)) { |
| | | raise_error(array( |
| | | 'code' => 700, 'type' => 'php', |
| | | 'file' => __FILE__, 'line' => __LINE__, |
| | | 'message' => "Storage driver class ($driver) not found!"), |
| | | true, true); |
| | | } |
| | | |
| | | // Initialize storage object |
| | | $this->storage = new $driver_class; |
| | | |
| | | // for backward compat. (deprecated, will be removed) |
| | | $this->imap = $this->storage; |
| | | |
| | | // enable caching of mail data |
| | | $storage_cache = $this->config->get("{$driver}_cache"); |
| | | $messages_cache = $this->config->get('messages_cache'); |
| | | // for backward compatybility |
| | | if ($imap_cache === null && $messages_cache === null && $this->config->get('enable_caching')) { |
| | | $imap_cache = 'db'; |
| | | if ($storage_cache === null && $messages_cache === null && $this->config->get('enable_caching')) { |
| | | $storage_cache = 'db'; |
| | | $messages_cache = true; |
| | | } |
| | | |
| | | if ($imap_cache) |
| | | $this->imap->set_caching($imap_cache); |
| | | if ($storage_cache) |
| | | $this->storage->set_caching($storage_cache); |
| | | if ($messages_cache) |
| | | $this->imap->set_messages_caching(true); |
| | | $this->storage->set_messages_caching(true); |
| | | |
| | | // set pagesize from config |
| | | $pagesize = $this->config->get('mail_pagesize'); |
| | | if (!$pagesize) { |
| | | $pagesize = $this->config->get('pagesize', 50); |
| | | } |
| | | $this->imap->set_pagesize($pagesize); |
| | | $this->storage->set_pagesize($pagesize); |
| | | |
| | | // set connection options |
| | | // set class options |
| | | $options = array( |
| | | 'auth_type' => $this->config->get('imap_auth_type', 'check'), |
| | | 'auth_cid' => $this->config->get('imap_auth_cid'), |
| | | 'auth_pw' => $this->config->get('imap_auth_pw'), |
| | | 'debug' => (bool) $this->config->get('imap_debug', 0), |
| | | 'force_caps' => (bool) $this->config->get('imap_force_caps'), |
| | | 'timeout' => (int) $this->config->get('imap_timeout', 0), |
| | | 'auth_type' => $this->config->get("{$driver}_auth_type", 'check'), |
| | | 'auth_cid' => $this->config->get("{$driver}_auth_cid"), |
| | | 'auth_pw' => $this->config->get("{$driver}_auth_pw"), |
| | | 'debug' => (bool) $this->config->get("{$driver}_debug"), |
| | | 'force_caps' => (bool) $this->config->get("{$driver}_force_caps"), |
| | | 'timeout' => (int) $this->config->get("{$driver}_timeout"), |
| | | 'skip_deleted' => (bool) $this->config->get('skip_deleted'), |
| | | 'driver' => $driver, |
| | | ); |
| | | |
| | | $this->imap->set_options($options); |
| | | |
| | | // set global object for backward compatibility |
| | | $GLOBALS['IMAP'] = $this->imap; |
| | | |
| | | $hook = $this->plugins->exec_hook('imap_init', array('fetch_headers' => $this->imap->fetch_add_headers)); |
| | | if ($hook['fetch_headers']) |
| | | $this->imap->fetch_add_headers = $hook['fetch_headers']; |
| | | |
| | | // support this parameter for backward compatibility but log warning |
| | | if ($connect) { |
| | | $this->imap_connect(); |
| | | raise_error(array( |
| | | 'code' => 800, 'type' => 'imap', |
| | | 'file' => __FILE__, 'line' => __LINE__, |
| | | 'message' => "rcube::imap_init(true) is deprecated, use rcube::imap_connect() instead"), |
| | | true, false); |
| | | if (!empty($_SESSION['storage_host'])) { |
| | | $options['host'] = $_SESSION['storage_host']; |
| | | $options['user'] = $_SESSION['username']; |
| | | $options['port'] = $_SESSION['storage_port']; |
| | | $options['ssl'] = $_SESSION['storage_ssl']; |
| | | $options['password'] = $this->decrypt($_SESSION['password']); |
| | | } |
| | | |
| | | $options = $this->plugins->exec_hook("storage_init", $options); |
| | | |
| | | // for backward compat. (deprecated, to be removed) |
| | | $options = $this->plugins->exec_hook("imap_init", $options); |
| | | |
| | | $this->storage->set_options($options); |
| | | $this->set_storage_prop(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Connect to IMAP server with stored session data |
| | | * Connect to the mail storage server with stored session data |
| | | * |
| | | * @return bool True on success, false on error |
| | | * @return bool True on success, False on error |
| | | */ |
| | | public function imap_connect() |
| | | public function storage_connect() |
| | | { |
| | | if (!$this->imap) |
| | | $this->imap_init(); |
| | | $storage = $this->get_storage(); |
| | | |
| | | if ($_SESSION['imap_host'] && !$this->imap->conn->connected()) { |
| | | if (!$this->imap->connect($_SESSION['imap_host'], $_SESSION['username'], $this->decrypt($_SESSION['password']), $_SESSION['imap_port'], $_SESSION['imap_ssl'])) { |
| | | if ($_SESSION['storage_host'] && !$storage->is_connected()) { |
| | | $host = $_SESSION['storage_host']; |
| | | $user = $_SESSION['username']; |
| | | $port = $_SESSION['storage_port']; |
| | | $ssl = $_SESSION['storage_ssl']; |
| | | $pass = $this->decrypt($_SESSION['password']); |
| | | |
| | | if (!$storage->connect($host, $user, $pass, $port, $ssl)) { |
| | | if ($this->output) |
| | | $this->output->show_message($this->imap->get_error_code() == -1 ? 'imaperror' : 'sessionerror', 'error'); |
| | | $this->output->show_message($storage->get_error_code() == -1 ? 'storageerror' : 'sessionerror', 'error'); |
| | | } |
| | | else { |
| | | $this->set_imap_prop(); |
| | | return $this->imap->conn; |
| | | $this->set_storage_prop(); |
| | | return $storage->is_connected(); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Perfom login to the IMAP server and to the webmail service. |
| | | * Perfom login to the mail server and to the webmail service. |
| | | * This will also create a new user entry if auto_create_user is configured. |
| | | * |
| | | * @param string IMAP user name |
| | | * @param string IMAP password |
| | | * @param string IMAP host |
| | | * @param string Mail storage (IMAP) user name |
| | | * @param string Mail storage (IMAP) password |
| | | * @param string Mail storage (IMAP) host |
| | | * |
| | | * @return boolean True on success, False on failure |
| | | */ |
| | |
| | | $a_host = parse_url($host); |
| | | if ($a_host['host']) { |
| | | $host = $a_host['host']; |
| | | $imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? $a_host['scheme'] : null; |
| | | $ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? $a_host['scheme'] : null; |
| | | if (!empty($a_host['port'])) |
| | | $imap_port = $a_host['port']; |
| | | else if ($imap_ssl && $imap_ssl != 'tls' && (!$config['default_port'] || $config['default_port'] == 143)) |
| | | $imap_port = 993; |
| | | $port = $a_host['port']; |
| | | else if ($ssl && $ssl != 'tls' && (!$config['default_port'] || $config['default_port'] == 143)) |
| | | $port = 993; |
| | | } |
| | | |
| | | $imap_port = $imap_port ? $imap_port : $config['default_port']; |
| | | if (!$port) { |
| | | $port = $config['default_port']; |
| | | } |
| | | |
| | | /* Modify username with domain if required |
| | | Inspired by Marco <P0L0_notspam_binware.org> |
| | |
| | | $username .= '@'.rcube_parse_host($config['username_domain'], $host); |
| | | } |
| | | |
| | | // Convert username to lowercase. If IMAP backend |
| | | // Convert username to lowercase. If storage backend |
| | | // is case-insensitive we need to store always the same username (#1487113) |
| | | if ($config['login_lc']) { |
| | | $username = mb_strtolower($username); |
| | |
| | | if ($user = rcube_user::query($username, $host)) |
| | | $username = $user->data['username']; |
| | | |
| | | if (!$this->imap) |
| | | $this->imap_init(); |
| | | if (!$this->storage) |
| | | $this->storage_init(); |
| | | |
| | | // try IMAP login |
| | | if (!($imap_login = $this->imap->connect($host, $username, $pass, $imap_port, $imap_ssl))) { |
| | | // try to log in |
| | | if (!($login = $this->storage->connect($host, $username, $pass, $port, $ssl))) { |
| | | // try with lowercase |
| | | $username_lc = mb_strtolower($username); |
| | | if ($username_lc != $username) { |
| | |
| | | if (!$user && ($user = rcube_user::query($username_lc, $host))) |
| | | $username_lc = $user->data['username']; |
| | | |
| | | if ($imap_login = $this->imap->connect($host, $username_lc, $pass, $imap_port, $imap_ssl)) |
| | | if ($login = $this->storage->connect($host, $username_lc, $pass, $port, $ssl)) |
| | | $username = $username_lc; |
| | | } |
| | | } |
| | | |
| | | // exit if IMAP login failed |
| | | if (!$imap_login) |
| | | // exit if login failed |
| | | if (!$login) { |
| | | return false; |
| | | } |
| | | |
| | | // user already registered -> update user's record |
| | | if (is_object($user)) { |
| | |
| | | if (is_object($user) && $user->ID) { |
| | | // Configure environment |
| | | $this->set_user($user); |
| | | $this->set_imap_prop(); |
| | | $this->set_storage_prop(); |
| | | $this->session_configure(); |
| | | |
| | | // fix some old settings according to namespace prefix |
| | |
| | | |
| | | // create default folders on first login |
| | | if ($config['create_default_folders'] && (!empty($created) || empty($user->data['last_login']))) { |
| | | $this->imap->create_default_folders(); |
| | | $this->storage->create_default_folders(); |
| | | } |
| | | |
| | | // set session vars |
| | | $_SESSION['user_id'] = $user->ID; |
| | | $_SESSION['username'] = $user->data['username']; |
| | | $_SESSION['imap_host'] = $host; |
| | | $_SESSION['imap_port'] = $imap_port; |
| | | $_SESSION['imap_ssl'] = $imap_ssl; |
| | | $_SESSION['password'] = $this->encrypt($pass); |
| | | $_SESSION['login_time'] = mktime(); |
| | | $_SESSION['user_id'] = $user->ID; |
| | | $_SESSION['username'] = $user->data['username']; |
| | | $_SESSION['storage_host'] = $host; |
| | | $_SESSION['storage_port'] = $port; |
| | | $_SESSION['storage_ssl'] = $ssl; |
| | | $_SESSION['password'] = $this->encrypt($pass); |
| | | $_SESSION['login_time'] = mktime(); |
| | | |
| | | if (isset($_REQUEST['_timezone']) && $_REQUEST['_timezone'] != '_default_') |
| | | $_SESSION['timezone'] = floatval($_REQUEST['_timezone']); |
| | |
| | | $_SESSION['dst_active'] = intval($_REQUEST['_dstactive']); |
| | | |
| | | // force reloading complete list of subscribed mailboxes |
| | | $this->imap->clear_cache('mailboxes', true); |
| | | $this->storage->clear_cache('mailboxes', true); |
| | | |
| | | return true; |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * Set root dir and last stored mailbox |
| | | * Set storage parameters. |
| | | * This must be done AFTER connecting to the server! |
| | | */ |
| | | public function set_imap_prop() |
| | | private function set_storage_prop() |
| | | { |
| | | $this->imap->set_charset($this->config->get('default_charset', RCMAIL_CHARSET)); |
| | | $storage = $this->get_storage(); |
| | | |
| | | if ($default_folders = $this->config->get('default_imap_folders')) { |
| | | $this->imap->set_default_mailboxes($default_folders); |
| | | $storage->set_charset($this->config->get('default_charset', RCMAIL_CHARSET)); |
| | | |
| | | if ($default_folders = $this->config->get('default_folders')) { |
| | | $storage->set_default_folders($default_folders); |
| | | } |
| | | if (isset($_SESSION['mbox'])) { |
| | | $this->imap->set_mailbox($_SESSION['mbox']); |
| | | $storage->set_folder($_SESSION['mbox']); |
| | | } |
| | | if (isset($_SESSION['page'])) { |
| | | $this->imap->set_page($_SESSION['page']); |
| | | $storage->set_page($_SESSION['page']); |
| | | } |
| | | } |
| | | |
| | |
| | | // try to select host by mail domain |
| | | list($user, $domain) = explode('@', get_input_value('_user', RCUBE_INPUT_POST)); |
| | | if (!empty($domain)) { |
| | | foreach ($default_host as $imap_host => $mail_domains) { |
| | | foreach ($default_host as $storage_host => $mail_domains) { |
| | | if (is_array($mail_domains) && in_array($domain, $mail_domains)) { |
| | | $host = $imap_host; |
| | | $host = $storage_host; |
| | | break; |
| | | } |
| | | } |
| | |
| | | if (!$this->session->check_auth()) |
| | | return; |
| | | |
| | | $this->imap_connect(); |
| | | $this->storage_connect(); |
| | | } |
| | | |
| | | if ($config['logout_purge'] && !empty($config['trash_mbox'])) { |
| | | $this->imap->clear_mailbox($config['trash_mbox']); |
| | | $this->storage->clear_folder($config['trash_mbox']); |
| | | } |
| | | |
| | | if ($config['logout_expunge']) { |
| | | $this->imap->expunge('INBOX'); |
| | | $this->storage->expunge_folder('INBOX'); |
| | | } |
| | | |
| | | // Try to save unsaved user preferences |
| | |
| | | $cache->close(); |
| | | } |
| | | |
| | | if (is_object($this->imap)) |
| | | $this->imap->close(); |
| | | if (is_object($this->storage)) |
| | | $this->storage->close(); |
| | | |
| | | // before closing the database connection, write session data |
| | | if ($_SERVER['REMOTE_ADDR'] && is_object($this->session)) { |
| | |
| | | */ |
| | | private function fix_namespace_settings($user) |
| | | { |
| | | $prefix = $this->imap->get_namespace('prefix'); |
| | | $prefix = $this->storage->get_namespace('prefix'); |
| | | $prefix_len = strlen($prefix); |
| | | |
| | | if (!$prefix_len) |
| | |
| | | return; |
| | | |
| | | // Build namespace prefix regexp |
| | | $ns = $this->imap->get_namespace(); |
| | | $ns = $this->storage->get_namespace(); |
| | | $regexp = array(); |
| | | |
| | | foreach ($ns as $entry) { |
| | |
| | | } |
| | | } |
| | | |
| | | if (!empty($prefs['default_imap_folders'])) { |
| | | foreach ($prefs['default_imap_folders'] as $idx => $name) { |
| | | if (!empty($prefs['default_folders'])) { |
| | | foreach ($prefs['default_folders'] as $idx => $name) { |
| | | if ($name != 'INBOX' && !preg_match($regexp, $name)) { |
| | | $prefs['default_imap_folders'][$idx] = $prefix.$name; |
| | | $prefs['default_folders'][$idx] = $prefix.$name; |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | // save updated preferences and reset imap settings (default folders) |
| | | $user->save_prefs($prefs); |
| | | $this->set_imap_prop(); |
| | | $this->set_storage_prop(); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | <?php |
| | | |
| | | /* |
| | | +-----------------------------------------------------------------------+ |
| | | | program/include/rcube_charset.php | |
| | | | | |
| | | | This file is part of the Roundcube Webmail client | |
| | | | Copyright (C) 2005-2012, The Roundcube Dev Team | |
| | | | Copyright (C) 2011-2012, Kolab Systems AG | |
| | | | Copyright (C) 2000 Edmund Grimley Evans <edmundo@rano.org> | |
| | | | Licensed under the GNU GPL | |
| | | | | |
| | | | PURPOSE: | |
| | | | Provide charset conversion functionality | |
| | | | | |
| | | +-----------------------------------------------------------------------+ |
| | | | Author: Thomas Bruederli <roundcube@gmail.com> | |
| | | | Author: Aleksander Machniak <alec@alec.pl> | |
| | | +-----------------------------------------------------------------------+ |
| | | |
| | | $Id$ |
| | | |
| | | */ |
| | | |
| | | /** |
| | | * Character sets conversion functionality |
| | | * |
| | | * @package Core |
| | | * @author Thomas Bruederli <roundcube@gmail.com> |
| | | * @author Aleksander Machniak <alec@alec.pl> |
| | | * @author Edmund Grimley Evans <edmundo@rano.org> |
| | | */ |
| | | class rcube_charset |
| | | { |
| | | // Aliases: some of them from HTML5 spec. |
| | | static public $aliases = array( |
| | | 'USASCII' => 'WINDOWS-1252', |
| | | 'ANSIX31101983' => 'WINDOWS-1252', |
| | | 'ANSIX341968' => 'WINDOWS-1252', |
| | | 'UNKNOWN8BIT' => 'ISO-8859-15', |
| | | 'UNKNOWN' => 'ISO-8859-15', |
| | | 'USERDEFINED' => 'ISO-8859-15', |
| | | 'KSC56011987' => 'EUC-KR', |
| | | 'GB2312' => 'GBK', |
| | | 'GB231280' => 'GBK', |
| | | 'UNICODE' => 'UTF-8', |
| | | 'UTF7IMAP' => 'UTF7-IMAP', |
| | | 'TIS620' => 'WINDOWS-874', |
| | | 'ISO88599' => 'WINDOWS-1254', |
| | | 'ISO885911' => 'WINDOWS-874', |
| | | 'MACROMAN' => 'MACINTOSH', |
| | | '77' => 'MAC', |
| | | '128' => 'SHIFT-JIS', |
| | | '129' => 'CP949', |
| | | '130' => 'CP1361', |
| | | '134' => 'GBK', |
| | | '136' => 'BIG5', |
| | | '161' => 'WINDOWS-1253', |
| | | '162' => 'WINDOWS-1254', |
| | | '163' => 'WINDOWS-1258', |
| | | '177' => 'WINDOWS-1255', |
| | | '178' => 'WINDOWS-1256', |
| | | '186' => 'WINDOWS-1257', |
| | | '204' => 'WINDOWS-1251', |
| | | '222' => 'WINDOWS-874', |
| | | '238' => 'WINDOWS-1250', |
| | | 'MS950' => 'CP950', |
| | | 'WINDOWS949' => 'UHC', |
| | | ); |
| | | |
| | | |
| | | /** |
| | | * Catch an error and throw an exception. |
| | | * |
| | | * @param int Level of the error |
| | | * @param string Error message |
| | | */ |
| | | public function error_handler($errno, $errstr) |
| | | { |
| | | throw new ErrorException($errstr, 0, $errno); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Parse and validate charset name string (see #1485758). |
| | | * Sometimes charset string is malformed, there are also charset aliases |
| | | * but we need strict names for charset conversion (specially utf8 class) |
| | | * |
| | | * @param string Input charset name |
| | | * |
| | | * @return string The validated charset name |
| | | */ |
| | | public static function parse($input) |
| | | { |
| | | static $charsets = array(); |
| | | $charset = strtoupper($input); |
| | | |
| | | if (isset($charsets[$input])) { |
| | | return $charsets[$input]; |
| | | } |
| | | |
| | | $charset = preg_replace(array( |
| | | '/^[^0-9A-Z]+/', // e.g. _ISO-8859-JP$SIO |
| | | '/\$.*$/', // e.g. _ISO-8859-JP$SIO |
| | | '/UNICODE-1-1-*/', // RFC1641/1642 |
| | | '/^X-/', // X- prefix (e.g. X-ROMAN8 => ROMAN8) |
| | | ), '', $charset); |
| | | |
| | | if ($charset == 'BINARY') { |
| | | return $charsets[$input] = null; |
| | | } |
| | | |
| | | // allow A-Z and 0-9 only |
| | | $str = preg_replace('/[^A-Z0-9]/', '', $charset); |
| | | |
| | | if (isset(self::$aliases[$str])) { |
| | | $result = self::$aliases[$str]; |
| | | } |
| | | // UTF |
| | | else if (preg_match('/U[A-Z][A-Z](7|8|16|32)(BE|LE)*/', $str, $m)) { |
| | | $result = 'UTF-' . $m[1] . $m[2]; |
| | | } |
| | | // ISO-8859 |
| | | else if (preg_match('/ISO8859([0-9]{0,2})/', $str, $m)) { |
| | | $iso = 'ISO-8859-' . ($m[1] ? $m[1] : 1); |
| | | // some clients sends windows-1252 text as latin1, |
| | | // it is safe to use windows-1252 for all latin1 |
| | | $result = $iso == 'ISO-8859-1' ? 'WINDOWS-1252' : $iso; |
| | | } |
| | | // handle broken charset names e.g. WINDOWS-1250HTTP-EQUIVCONTENT-TYPE |
| | | else if (preg_match('/(WIN|WINDOWS)([0-9]+)/', $str, $m)) { |
| | | $result = 'WINDOWS-' . $m[2]; |
| | | } |
| | | // LATIN |
| | | else if (preg_match('/LATIN(.*)/', $str, $m)) { |
| | | $aliases = array('2' => 2, '3' => 3, '4' => 4, '5' => 9, '6' => 10, |
| | | '7' => 13, '8' => 14, '9' => 15, '10' => 16, |
| | | 'ARABIC' => 6, 'CYRILLIC' => 5, 'GREEK' => 7, 'GREEK1' => 7, 'HEBREW' => 8 |
| | | ); |
| | | |
| | | // some clients sends windows-1252 text as latin1, |
| | | // it is safe to use windows-1252 for all latin1 |
| | | if ($m[1] == 1) { |
| | | $result = 'WINDOWS-1252'; |
| | | } |
| | | // if iconv is not supported we need ISO labels, it's also safe for iconv |
| | | else if (!empty($aliases[$m[1]])) { |
| | | $result = 'ISO-8859-'.$aliases[$m[1]]; |
| | | } |
| | | // iconv requires convertion of e.g. LATIN-1 to LATIN1 |
| | | else { |
| | | $result = $str; |
| | | } |
| | | } |
| | | else { |
| | | $result = $charset; |
| | | } |
| | | |
| | | $charsets[$input] = $result; |
| | | |
| | | return $result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Convert a string from one charset to another. |
| | | * Uses mbstring and iconv functions if possible |
| | | * |
| | | * @param string Input string |
| | | * @param string Suspected charset of the input string |
| | | * @param string Target charset to convert to; defaults to RCMAIL_CHARSET |
| | | * |
| | | * @return string Converted string |
| | | */ |
| | | public static function convert($str, $from, $to = null) |
| | | { |
| | | static $iconv_options = null; |
| | | static $mbstring_loaded = null; |
| | | static $mbstring_list = null; |
| | | static $conv = null; |
| | | |
| | | $to = empty($to) ? strtoupper(RCMAIL_CHARSET) : self::parse($to); |
| | | $from = self::parse($from); |
| | | |
| | | if ($from == $to || empty($str) || empty($from)) { |
| | | return $str; |
| | | } |
| | | |
| | | // convert charset using iconv module |
| | | if (function_exists('iconv') && $from != 'UTF7-IMAP' && $to != 'UTF7-IMAP') { |
| | | if ($iconv_options === null) { |
| | | // ignore characters not available in output charset |
| | | $iconv_options = '//IGNORE'; |
| | | if (iconv('', $iconv_options, '') === false) { |
| | | // iconv implementation does not support options |
| | | $iconv_options = ''; |
| | | } |
| | | } |
| | | |
| | | // throw an exception if iconv reports an illegal character in input |
| | | // it means that input string has been truncated |
| | | set_error_handler(array('rcube_charset', 'error_handler'), E_NOTICE); |
| | | try { |
| | | $_iconv = iconv($from, $to . $iconv_options, $str); |
| | | } catch (ErrorException $e) { |
| | | $_iconv = false; |
| | | } |
| | | restore_error_handler(); |
| | | |
| | | if ($_iconv !== false) { |
| | | return $_iconv; |
| | | } |
| | | } |
| | | |
| | | if ($mbstring_loaded === null) { |
| | | $mbstring_loaded = extension_loaded('mbstring'); |
| | | } |
| | | |
| | | // convert charset using mbstring module |
| | | if ($mbstring_loaded) { |
| | | $aliases['WINDOWS-1257'] = 'ISO-8859-13'; |
| | | |
| | | if ($mbstring_list === null) { |
| | | $mbstring_list = mb_list_encodings(); |
| | | $mbstring_list = array_map('strtoupper', $mbstring_list); |
| | | } |
| | | |
| | | $mb_from = $aliases[$from] ? $aliases[$from] : $from; |
| | | $mb_to = $aliases[$to] ? $aliases[$to] : $to; |
| | | |
| | | // return if encoding found, string matches encoding and convert succeeded |
| | | if (in_array($mb_from, $mbstring_list) && in_array($mb_to, $mbstring_list)) { |
| | | if (mb_check_encoding($str, $mb_from) && ($out = mb_convert_encoding($str, $mb_to, $mb_from))) { |
| | | return $out; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // convert charset using bundled classes/functions |
| | | if ($to == 'UTF-8') { |
| | | if ($from == 'UTF7-IMAP') { |
| | | if ($_str = self::utf7imap_to_utf8($str)) { |
| | | return $_str; |
| | | } |
| | | } |
| | | else if ($from == 'UTF-7') { |
| | | if ($_str = self::utf7_to_utf8($str)) { |
| | | return $_str; |
| | | } |
| | | } |
| | | else if ($from == 'ISO-8859-1' && function_exists('utf8_encode')) { |
| | | return utf8_encode($str); |
| | | } |
| | | else if (class_exists('utf8')) { |
| | | if (!$conv) { |
| | | $conv = new utf8($from); |
| | | } |
| | | else { |
| | | $conv->loadCharset($from); |
| | | } |
| | | |
| | | if ($_str = $conv->strToUtf8($str)) { |
| | | return $_str; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // encode string for output |
| | | if ($from == 'UTF-8') { |
| | | // @TODO: we need a function for UTF-7 (RFC2152) conversion |
| | | if ($to == 'UTF7-IMAP' || $to == 'UTF-7') { |
| | | if ($_str = utf8_to_utf7imap($str)) { |
| | | return $_str; |
| | | } |
| | | } |
| | | else if ($to == 'ISO-8859-1' && function_exists('utf8_decode')) { |
| | | return utf8_decode($str); |
| | | } |
| | | else if (class_exists('utf8')) { |
| | | if (!$conv) { |
| | | $conv = new utf8($to); |
| | | } |
| | | else { |
| | | $conv->loadCharset($from); |
| | | } |
| | | |
| | | if ($_str = $conv->strToUtf8($str)) { |
| | | return $_str; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // return original string |
| | | return $str; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Converts string from standard UTF-7 (RFC 2152) to UTF-8. |
| | | * |
| | | * @param string Input string (UTF-7) |
| | | * |
| | | * @return string Converted string (UTF-8) |
| | | */ |
| | | public static function utf7_to_utf8($str) |
| | | { |
| | | $Index_64 = array( |
| | | 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, |
| | | 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, |
| | | 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0, |
| | | 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, |
| | | 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, |
| | | 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, |
| | | 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, |
| | | 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, |
| | | ); |
| | | |
| | | $u7len = strlen($str); |
| | | $str = strval($str); |
| | | $res = ''; |
| | | |
| | | for ($i=0; $u7len > 0; $i++, $u7len--) { |
| | | $u7 = $str[$i]; |
| | | if ($u7 == '+') { |
| | | $i++; |
| | | $u7len--; |
| | | $ch = ''; |
| | | |
| | | for (; $u7len > 0; $i++, $u7len--) { |
| | | $u7 = $str[$i]; |
| | | |
| | | if (!$Index_64[ord($u7)]) { |
| | | break; |
| | | } |
| | | |
| | | $ch .= $u7; |
| | | } |
| | | |
| | | if ($ch == '') { |
| | | if ($u7 == '-') { |
| | | $res .= '+'; |
| | | } |
| | | |
| | | continue; |
| | | } |
| | | |
| | | $res .= self::utf16_to_utf8(base64_decode($ch)); |
| | | } |
| | | else { |
| | | $res .= $u7; |
| | | } |
| | | } |
| | | |
| | | return $res; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Converts string from UTF-16 to UTF-8 (helper for utf-7 to utf-8 conversion) |
| | | * |
| | | * @param string Input string |
| | | * |
| | | * @return string The converted string |
| | | */ |
| | | public static function utf16_to_utf8($str) |
| | | { |
| | | $len = strlen($str); |
| | | $dec = ''; |
| | | |
| | | for ($i = 0; $i < $len; $i += 2) { |
| | | $c = ord($str[$i]) << 8 | ord($str[$i + 1]); |
| | | if ($c >= 0x0001 && $c <= 0x007F) { |
| | | $dec .= chr($c); |
| | | } |
| | | else if ($c > 0x07FF) { |
| | | $dec .= chr(0xE0 | (($c >> 12) & 0x0F)); |
| | | $dec .= chr(0x80 | (($c >> 6) & 0x3F)); |
| | | $dec .= chr(0x80 | (($c >> 0) & 0x3F)); |
| | | } |
| | | else { |
| | | $dec .= chr(0xC0 | (($c >> 6) & 0x1F)); |
| | | $dec .= chr(0x80 | (($c >> 0) & 0x3F)); |
| | | } |
| | | } |
| | | |
| | | return $dec; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Convert the data ($str) from RFC 2060's UTF-7 to UTF-8. |
| | | * If input data is invalid, return the original input string. |
| | | * RFC 2060 obviously intends the encoding to be unique (see |
| | | * point 5 in section 5.1.3), so we reject any non-canonical |
| | | * form, such as &ACY- (instead of &-) or &AMA-&AMA- (instead |
| | | * of &AMAAwA-). |
| | | * |
| | | * Translated from C to PHP by Thomas Bruederli <roundcube@gmail.com> |
| | | * |
| | | * @param string $str Input string (UTF7-IMAP) |
| | | * |
| | | * @return string Output string (UTF-8) |
| | | */ |
| | | public static function utf7imap_to_utf8($str) |
| | | { |
| | | $Index_64 = array( |
| | | -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, |
| | | -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, |
| | | -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, 63,-1,-1,-1, |
| | | 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, |
| | | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, |
| | | 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, |
| | | -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, |
| | | 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 |
| | | ); |
| | | |
| | | $u7len = strlen($str); |
| | | $str = strval($str); |
| | | $p = ''; |
| | | $err = ''; |
| | | |
| | | for ($i=0; $u7len > 0; $i++, $u7len--) { |
| | | $u7 = $str[$i]; |
| | | if ($u7 == '&') { |
| | | $i++; |
| | | $u7len--; |
| | | $u7 = $str[$i]; |
| | | |
| | | if ($u7len && $u7 == '-') { |
| | | $p .= '&'; |
| | | continue; |
| | | } |
| | | |
| | | $ch = 0; |
| | | $k = 10; |
| | | for (; $u7len > 0; $i++, $u7len--) { |
| | | $u7 = $str[$i]; |
| | | |
| | | if ((ord($u7) & 0x80) || ($b = $Index_64[ord($u7)]) == -1) { |
| | | break; |
| | | } |
| | | |
| | | if ($k > 0) { |
| | | $ch |= $b << $k; |
| | | $k -= 6; |
| | | } |
| | | else { |
| | | $ch |= $b >> (-$k); |
| | | if ($ch < 0x80) { |
| | | // Printable US-ASCII |
| | | if (0x20 <= $ch && $ch < 0x7f) { |
| | | return $err; |
| | | } |
| | | $p .= chr($ch); |
| | | } |
| | | else if ($ch < 0x800) { |
| | | $p .= chr(0xc0 | ($ch >> 6)); |
| | | $p .= chr(0x80 | ($ch & 0x3f)); |
| | | } |
| | | else { |
| | | $p .= chr(0xe0 | ($ch >> 12)); |
| | | $p .= chr(0x80 | (($ch >> 6) & 0x3f)); |
| | | $p .= chr(0x80 | ($ch & 0x3f)); |
| | | } |
| | | |
| | | $ch = ($b << (16 + $k)) & 0xffff; |
| | | $k += 10; |
| | | } |
| | | } |
| | | |
| | | // Non-zero or too many extra bits |
| | | if ($ch || $k < 6) { |
| | | return $err; |
| | | } |
| | | |
| | | // BASE64 not properly terminated |
| | | if (!$u7len || $u7 != '-') { |
| | | return $err; |
| | | } |
| | | |
| | | // Adjacent BASE64 sections |
| | | if ($u7len > 2 && $str[$i+1] == '&' && $str[$i+2] != '-') { |
| | | return $err; |
| | | } |
| | | } |
| | | // Not printable US-ASCII |
| | | else if (ord($u7) < 0x20 || ord($u7) >= 0x7f) { |
| | | return $err; |
| | | } |
| | | else { |
| | | $p .= $u7; |
| | | } |
| | | } |
| | | |
| | | return $p; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Convert the data ($str) from UTF-8 to RFC 2060's UTF-7. |
| | | * Unicode characters above U+FFFF are replaced by U+FFFE. |
| | | * If input data is invalid, return an empty string. |
| | | * |
| | | * Translated from C to PHP by Thomas Bruederli <roundcube@gmail.com> |
| | | * |
| | | * @param string $str Input string (UTF-8) |
| | | * |
| | | * @return string Output string (UTF7-IMAP) |
| | | */ |
| | | public static function utf8_to_utf7imap($str) |
| | | { |
| | | $B64Chars = array( |
| | | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', |
| | | 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', |
| | | 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', |
| | | 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', |
| | | '8', '9', '+', ',' |
| | | ); |
| | | |
| | | $u8len = strlen($str); |
| | | $base64 = 0; |
| | | $i = 0; |
| | | $p = ''; |
| | | $err = ''; |
| | | |
| | | while ($u8len) { |
| | | $u8 = $str[$i]; |
| | | $c = ord($u8); |
| | | |
| | | if ($c < 0x80) { |
| | | $ch = $c; |
| | | $n = 0; |
| | | } |
| | | else if ($c < 0xc2) { |
| | | return $err; |
| | | } |
| | | else if ($c < 0xe0) { |
| | | $ch = $c & 0x1f; |
| | | $n = 1; |
| | | } |
| | | else if ($c < 0xf0) { |
| | | $ch = $c & 0x0f; |
| | | $n = 2; |
| | | } |
| | | else if ($c < 0xf8) { |
| | | $ch = $c & 0x07; |
| | | $n = 3; |
| | | } |
| | | else if ($c < 0xfc) { |
| | | $ch = $c & 0x03; |
| | | $n = 4; |
| | | } |
| | | else if ($c < 0xfe) { |
| | | $ch = $c & 0x01; |
| | | $n = 5; |
| | | } |
| | | else { |
| | | return $err; |
| | | } |
| | | |
| | | $i++; |
| | | $u8len--; |
| | | |
| | | if ($n > $u8len) { |
| | | return $err; |
| | | } |
| | | |
| | | for ($j=0; $j < $n; $j++) { |
| | | $o = ord($str[$i+$j]); |
| | | if (($o & 0xc0) != 0x80) { |
| | | return $err; |
| | | } |
| | | $ch = ($ch << 6) | ($o & 0x3f); |
| | | } |
| | | |
| | | if ($n > 1 && !($ch >> ($n * 5 + 1))) { |
| | | return $err; |
| | | } |
| | | |
| | | $i += $n; |
| | | $u8len -= $n; |
| | | |
| | | if ($ch < 0x20 || $ch >= 0x7f) { |
| | | if (!$base64) { |
| | | $p .= '&'; |
| | | $base64 = 1; |
| | | $b = 0; |
| | | $k = 10; |
| | | } |
| | | if ($ch & ~0xffff) { |
| | | $ch = 0xfffe; |
| | | } |
| | | |
| | | $p .= $B64Chars[($b | $ch >> $k)]; |
| | | $k -= 6; |
| | | for (; $k >= 0; $k -= 6) { |
| | | $p .= $B64Chars[(($ch >> $k) & 0x3f)]; |
| | | } |
| | | |
| | | $b = ($ch << (-$k)) & 0x3f; |
| | | $k += 16; |
| | | } |
| | | else { |
| | | if ($base64) { |
| | | if ($k > 10) { |
| | | $p .= $B64Chars[$b]; |
| | | } |
| | | $p .= '-'; |
| | | $base64 = 0; |
| | | } |
| | | |
| | | $p .= chr($ch); |
| | | if (chr($ch) == '&') { |
| | | $p .= '-'; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if ($base64) { |
| | | if ($k > 10) { |
| | | $p .= $B64Chars[$b]; |
| | | } |
| | | $p .= '-'; |
| | | } |
| | | |
| | | return $p; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * A method to guess character set of a string. |
| | | * |
| | | * @param string $string String. |
| | | * @param string $failover Default result for failover. |
| | | * |
| | | * @return string Charset name |
| | | */ |
| | | public static function detect($string, $failover='') |
| | | { |
| | | if (!function_exists('mb_detect_encoding')) { |
| | | return $failover; |
| | | } |
| | | |
| | | // FIXME: the order is important, because sometimes |
| | | // iso string is detected as euc-jp and etc. |
| | | $enc = array( |
| | | 'UTF-8', 'SJIS', 'BIG5', 'GB2312', |
| | | 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', |
| | | 'ISO-8859-5', 'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8', 'ISO-8859-9', |
| | | 'ISO-8859-10', 'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'ISO-8859-16', |
| | | 'WINDOWS-1252', 'WINDOWS-1251', 'EUC-JP', 'EUC-TW', 'KOI8-R', |
| | | 'ISO-2022-KR', 'ISO-2022-JP' |
| | | ); |
| | | |
| | | $result = mb_detect_encoding($string, join(',', $enc)); |
| | | |
| | | return $result ? $result : $failover; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Removes non-unicode characters from input. |
| | | * |
| | | * @param mixed $input String or array. |
| | | * |
| | | * @return mixed String or array |
| | | */ |
| | | public static function clean($input) |
| | | { |
| | | // handle input of type array |
| | | if (is_array($input)) { |
| | | foreach ($input as $idx => $val) { |
| | | $input[$idx] = self::clean($val); |
| | | } |
| | | return $input; |
| | | } |
| | | |
| | | if (!is_string($input) || $input == '') { |
| | | return $input; |
| | | } |
| | | |
| | | // iconv/mbstring are much faster (especially with long strings) |
| | | if (function_exists('mb_convert_encoding')) { |
| | | if (($res = mb_convert_encoding($input, 'UTF-8', 'UTF-8')) !== false) { |
| | | return $res; |
| | | } |
| | | } |
| | | |
| | | if (function_exists('iconv')) { |
| | | if (($res = @iconv('UTF-8', 'UTF-8//IGNORE', $input)) !== false) { |
| | | return $res; |
| | | } |
| | | } |
| | | |
| | | $seq = ''; |
| | | $out = ''; |
| | | $regexp = '/^('. |
| | | // '[\x00-\x7F]'. // UTF8-1 |
| | | '|[\xC2-\xDF][\x80-\xBF]'. // UTF8-2 |
| | | '|\xE0[\xA0-\xBF][\x80-\xBF]'. // UTF8-3 |
| | | '|[\xE1-\xEC][\x80-\xBF][\x80-\xBF]'. // UTF8-3 |
| | | '|\xED[\x80-\x9F][\x80-\xBF]'. // UTF8-3 |
| | | '|[\xEE-\xEF][\x80-\xBF][\x80-\xBF]'. // UTF8-3 |
| | | '|\xF0[\x90-\xBF][\x80-\xBF][\x80-\xBF]'. // UTF8-4 |
| | | '|[\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF]'.// UTF8-4 |
| | | '|\xF4[\x80-\x8F][\x80-\xBF][\x80-\xBF]'. // UTF8-4 |
| | | ')$/'; |
| | | |
| | | for ($i = 0, $len = strlen($input); $i < $len; $i++) { |
| | | $chr = $input[$i]; |
| | | $ord = ord($chr); |
| | | |
| | | // 1-byte character |
| | | if ($ord <= 0x7F) { |
| | | if ($seq) { |
| | | $out .= preg_match($regexp, $seq) ? $seq : ''; |
| | | } |
| | | $seq = ''; |
| | | $out .= $chr; |
| | | // first (or second) byte of multibyte sequence |
| | | } |
| | | else if ($ord >= 0xC0) { |
| | | if (strlen($seq) > 1) { |
| | | $out .= preg_match($regexp, $seq) ? $seq : ''; |
| | | $seq = ''; |
| | | } |
| | | else if ($seq && ord($seq) < 0xC0) { |
| | | $seq = ''; |
| | | } |
| | | $seq .= $chr; |
| | | // next byte of multibyte sequence |
| | | } |
| | | else if ($seq) { |
| | | $seq .= $chr; |
| | | } |
| | | } |
| | | |
| | | if ($seq) { |
| | | $out .= preg_match($regexp, $seq) ? $seq : ''; |
| | | } |
| | | |
| | | return $out; |
| | | } |
| | | |
| | | } |
| | |
| | | foreach (array('drafts_mbox', 'junk_mbox', 'sent_mbox', 'trash_mbox') as $folder) |
| | | $this->prop[$folder] = rcube_charset_convert($this->prop[$folder], RCMAIL_CHARSET, 'UTF7-IMAP'); |
| | | |
| | | if (!empty($this->prop['default_imap_folders'])) |
| | | foreach ($this->prop['default_imap_folders'] as $n => $folder) |
| | | $this->prop['default_imap_folders'][$n] = rcube_charset_convert($folder, RCMAIL_CHARSET, 'UTF7-IMAP'); |
| | | if (!empty($this->prop['default_folders'])) |
| | | foreach ($this->prop['default_folders'] as $n => $folder) |
| | | $this->prop['default_folders'][$n] = rcube_charset_convert($folder, RCMAIL_CHARSET, 'UTF7-IMAP'); |
| | | |
| | | // set PHP error logging according to config |
| | | if ($this->prop['debug_level'] & 1) { |
| | |
| | | // We've got a valid index |
| | | else if ($sort_field == 'ANY' || $this->icache[$mailbox]['index']['sort_field'] == $sort_field) { |
| | | $result = $this->icache[$mailbox]['index']['object']; |
| | | if ($result->getParameters('ORDER') != $sort_order) { |
| | | if ($result->get_parameters('ORDER') != $sort_order) { |
| | | $result->revert(); |
| | | } |
| | | return $result; |
| | |
| | | if ($is_valid) { |
| | | $data = $index['object']; |
| | | // revert the order if needed |
| | | if ($data->getParameters('ORDER') != $sort_order) { |
| | | if ($data->get_parameters('ORDER') != $sort_order) { |
| | | $data->revert(); |
| | | } |
| | | } |
| | |
| | | // Index not found, not valid or sort field changed, get index from IMAP server |
| | | if ($data === null) { |
| | | // Get mailbox data (UIDVALIDITY, counters, etc.) for status check |
| | | $mbox_data = $this->imap->mailbox_data($mailbox); |
| | | $mbox_data = $this->imap->folder_data($mailbox); |
| | | $data = $this->get_index_data($mailbox, $sort_field, $sort_order, $mbox_data); |
| | | |
| | | // insert/update |
| | |
| | | // Index not found or not valid, get index from IMAP server |
| | | if ($index === null) { |
| | | // Get mailbox data (UIDVALIDITY, counters, etc.) for status check |
| | | $mbox_data = $this->imap->mailbox_data($mailbox); |
| | | $mbox_data = $this->imap->folder_data($mailbox); |
| | | |
| | | if ($mbox_data['EXISTS']) { |
| | | // get all threads (default sort order) |
| | |
| | | |
| | | // Get the message from IMAP server |
| | | if (empty($message) && $update) { |
| | | $message = $this->imap->get_headers($uid, $mailbox, true); |
| | | $message = $this->imap->get_message_headers($uid, $mailbox, true); |
| | | // cache will be updated in close(), see below |
| | | } |
| | | |
| | |
| | | $is_thread = is_a($object, 'rcube_result_thread'); |
| | | |
| | | // Get mailbox data (UIDVALIDITY, counters, etc.) for status check |
| | | $mbox_data = $this->imap->mailbox_data($mailbox); |
| | | $mbox_data = $this->imap->folder_data($mailbox); |
| | | |
| | | // @TODO: Think about skipping validation checks. |
| | | // If we could check only every 10 minutes, we would be able to skip |
| | |
| | | |
| | | // Folder is empty but cache isn't |
| | | if (empty($mbox_data['EXISTS'])) { |
| | | if (!$object->isEmpty()) { |
| | | if (!$object->is_empty()) { |
| | | $this->clear($mailbox); |
| | | $exists = false; |
| | | return false; |
| | | } |
| | | } |
| | | // Folder is not empty but cache is |
| | | else if ($object->isEmpty()) { |
| | | else if ($object->is_empty()) { |
| | | unset($this->icache[$mailbox][$is_thread ? 'thread' : 'index']); |
| | | return false; |
| | | } |
| | |
| | | // @TODO: find better validity check for threaded index |
| | | if ($is_thread) { |
| | | // check messages number... |
| | | if (!$this->skip_deleted && $mbox_data['EXISTS'] != $object->countMessages()) { |
| | | if (!$this->skip_deleted && $mbox_data['EXISTS'] != $object->count_messages()) { |
| | | return false; |
| | | } |
| | | return true; |
| | |
| | | $ids = $this->imap->search_once($mailbox, 'ALL UNDELETED NOT UID '. |
| | | rcube_imap_generic::compressMessageSet($object->get())); |
| | | |
| | | if (!$ids->isEmpty()) { |
| | | if (!$ids->is_empty()) { |
| | | return false; |
| | | } |
| | | } |
| | |
| | | return; |
| | | } |
| | | |
| | | if (!$this->imap->check_connection()) { |
| | | return; |
| | | } |
| | | |
| | | // NOTE: make sure the mailbox isn't selected, before |
| | | // enabling QRESYNC and invoking SELECT |
| | | if ($this->imap->conn->selected !== null) { |
| | |
| | | } |
| | | |
| | | // Get mailbox data (UIDVALIDITY, HIGHESTMODSEQ, counters, etc.) |
| | | $mbox_data = $this->imap->mailbox_data($mailbox); |
| | | $mbox_data = $this->imap->folder_data($mailbox); |
| | | |
| | | if (empty($mbox_data)) { |
| | | return; |
| | |
| | | |
| | | // Get VANISHED |
| | | if ($qresync) { |
| | | $mbox_data = $this->imap->mailbox_data($mailbox); |
| | | $mbox_data = $this->imap->folder_data($mailbox); |
| | | |
| | | // Removed messages |
| | | if (!empty($mbox_data['VANISHED'])) { |
| | |
| | | } |
| | | |
| | | $sort_field = $index['sort_field']; |
| | | $sort_order = $index['object']->getParameters('ORDER'); |
| | | $sort_order = $index['object']->get_parameters('ORDER'); |
| | | $exists = true; |
| | | |
| | | // Validate index |
| | |
| | | private function get_index_data($mailbox, $sort_field, $sort_order, $mbox_data = array()) |
| | | { |
| | | if (empty($mbox_data)) { |
| | | $mbox_data = $this->imap->mailbox_data($mailbox); |
| | | $mbox_data = $this->imap->folder_data($mailbox); |
| | | } |
| | | |
| | | if ($mbox_data['EXISTS']) { |
| | | // fetch sorted sequence numbers |
| | | $index = $this->imap->message_index_direct($mailbox, $sort_field, $sort_order); |
| | | $index = $this->imap->index_direct($mailbox, $sort_field, $sort_order); |
| | | } |
| | | else { |
| | | $index = new rcube_result_index($mailbox, '* SORT'); |
| | |
| | | { |
| | | $this->uid = $uid; |
| | | $this->app = rcmail::get_instance(); |
| | | $this->imap = $this->app->imap; |
| | | $this->imap->get_all_headers = true; |
| | | $this->storage = $this->app->get_storage(); |
| | | $this->storage->set_options(array('all_headers' => true)); |
| | | |
| | | $this->headers = $this->imap->get_message($uid); |
| | | $this->headers = $this->storage->get_message($uid); |
| | | |
| | | if (!$this->headers) |
| | | return; |
| | |
| | | 'safe' => $this->is_safe, |
| | | 'prefer_html' => $this->app->config->get('prefer_html'), |
| | | 'get_url' => rcmail_url('get', array( |
| | | '_mbox' => $this->imap->get_mailbox_name(), '_uid' => $uid)) |
| | | '_mbox' => $this->storage->get_folder(), '_uid' => $uid)) |
| | | ); |
| | | |
| | | if (!empty($this->headers->structure)) { |
| | |
| | | $this->parse_structure($this->headers->structure); |
| | | } |
| | | else { |
| | | $this->body = $this->imap->get_body($uid); |
| | | $this->body = $this->storage->get_body($uid); |
| | | } |
| | | |
| | | // notify plugins and let them analyze this structured message object |
| | |
| | | return $fp ? true : $part->body; |
| | | } |
| | | // get from IMAP |
| | | return $this->imap->get_message_part($this->uid, $mime_id, $part, NULL, $fp); |
| | | return $this->storage->get_message_part($this->uid, $mime_id, $part, NULL, $fp); |
| | | } else |
| | | return null; |
| | | } |
| | |
| | | foreach ($this->mime_parts as $mime_id => $part) { |
| | | $mimetype = strtolower($part->ctype_primary . '/' . $part->ctype_secondary); |
| | | if ($mimetype == 'text/html') { |
| | | return $this->imap->get_message_part($this->uid, $mime_id, $part); |
| | | return $this->storage->get_message_part($this->uid, $mime_id, $part); |
| | | } |
| | | } |
| | | } |
| | |
| | | $mimetype = $part->ctype_primary . '/' . $part->ctype_secondary; |
| | | |
| | | if ($mimetype == 'text/plain') { |
| | | return $this->imap->get_message_part($this->uid, $mime_id, $part); |
| | | return $this->storage->get_message_part($this->uid, $mime_id, $part); |
| | | } |
| | | else if ($mimetype == 'text/html') { |
| | | $out = $this->imap->get_message_part($this->uid, $mime_id, $part); |
| | | $out = $this->storage->get_message_part($this->uid, $mime_id, $part); |
| | | |
| | | // remove special chars encoding |
| | | $trans = array_flip(get_html_translation_table(HTML_ENTITIES)); |
| | |
| | | { |
| | | // @TODO: attachment may be huge, hadle it via file |
| | | if (!isset($part->body)) |
| | | $part->body = $this->imap->get_message_part($this->uid, $part->mime_id, $part); |
| | | $part->body = $this->storage->get_message_part($this->uid, $part->mime_id, $part); |
| | | |
| | | $parts = array(); |
| | | $tnef = new tnef_decoder; |
| | |
| | | { |
| | | // @TODO: messages may be huge, hadle body via file |
| | | if (!isset($part->body)) |
| | | $part->body = $this->imap->get_message_part($this->uid, $part->mime_id, $part); |
| | | $part->body = $this->storage->get_message_part($this->uid, $part->mime_id, $part); |
| | | |
| | | $parts = array(); |
| | | // FIXME: line length is max.65? |
| | |
| | | */ |
| | | class rcube_result_index |
| | | { |
| | | private $raw_data; |
| | | private $mailbox; |
| | | private $meta = array(); |
| | | private $params = array(); |
| | | private $order = 'ASC'; |
| | | protected $raw_data; |
| | | protected $mailbox; |
| | | protected $meta = array(); |
| | | protected $params = array(); |
| | | protected $order = 'ASC'; |
| | | |
| | | const SEPARATOR_ELEMENT = ' '; |
| | | |
| | |
| | | * |
| | | * @return bool True if the result is an error, False otherwise |
| | | */ |
| | | public function isError() |
| | | public function is_error() |
| | | { |
| | | return $this->raw_data === null ? true : false; |
| | | } |
| | |
| | | * |
| | | * @return bool True if the result is empty, False otherwise |
| | | */ |
| | | public function isEmpty() |
| | | public function is_empty() |
| | | { |
| | | return empty($this->raw_data) ? true : false; |
| | | } |
| | |
| | | * |
| | | * @return int Number of elements |
| | | */ |
| | | public function countMessages() |
| | | public function count_messages() |
| | | { |
| | | return $this->count(); |
| | | } |
| | |
| | | if ($m[0][1]) { |
| | | $idx = 1 + substr_count($this->raw_data, self::SEPARATOR_ELEMENT, 0, $m[0][1]); |
| | | } |
| | | // cache position of this element, so we can use it in getElement() |
| | | // cache position of this element, so we can use it in get_element() |
| | | $this->meta['pos'][$idx] = (int)$m[0][1]; |
| | | |
| | | return $idx; |
| | |
| | | * |
| | | * @return array List of message IDs |
| | | */ |
| | | public function getCompressed() |
| | | public function get_compressed() |
| | | { |
| | | if (empty($this->raw_data)) { |
| | | return ''; |
| | |
| | | * |
| | | * @return int Element value |
| | | */ |
| | | public function getElement($index) |
| | | public function get_element($index) |
| | | { |
| | | $count = $this->count(); |
| | | |
| | |
| | | * |
| | | * @return array|string Response parameters or parameter value |
| | | */ |
| | | public function getParameters($param=null) |
| | | public function get_parameters($param=null) |
| | | { |
| | | $params = $this->params; |
| | | $params['MAILBOX'] = $this->mailbox; |
| | |
| | | * |
| | | * @return int Data length |
| | | */ |
| | | private function length() |
| | | protected function length() |
| | | { |
| | | if (!isset($this->meta['length'])) { |
| | | $this->meta['length'] = strlen($this->raw_data); |
| | |
| | | */ |
| | | class rcube_result_thread |
| | | { |
| | | private $raw_data; |
| | | private $mailbox; |
| | | private $meta = array(); |
| | | private $order = 'ASC'; |
| | | protected $raw_data; |
| | | protected $mailbox; |
| | | protected $meta = array(); |
| | | protected $order = 'ASC'; |
| | | |
| | | const SEPARATOR_ELEMENT = ' '; |
| | | const SEPARATOR_ITEM = '~'; |
| | |
| | | $data = preg_replace('/[\r\n]/', '', $data); |
| | | $data = preg_replace('/\s+/', ' ', $data); |
| | | |
| | | $this->raw_data = $this->parseThread($data); |
| | | $this->raw_data = $this->parse_thread($data); |
| | | } |
| | | |
| | | |
| | |
| | | * |
| | | * @return bool True if the result is an error, False otherwise |
| | | */ |
| | | public function isError() |
| | | public function is_error() |
| | | { |
| | | return $this->raw_data === null ? true : false; |
| | | } |
| | |
| | | * |
| | | * @return bool True if the result is empty, False otherwise |
| | | */ |
| | | public function isEmpty() |
| | | public function is_empty() |
| | | { |
| | | return empty($this->raw_data) ? true : false; |
| | | } |
| | |
| | | * |
| | | * @return int Number of elements |
| | | */ |
| | | public function countMessages() |
| | | public function count_messages() |
| | | { |
| | | if ($this->meta['messages'] !== null) |
| | | return $this->meta['messages']; |
| | |
| | | $idx = substr_count($this->raw_data, self::SEPARATOR_ELEMENT, 0, $m[0][1]+1) |
| | | + substr_count($this->raw_data, self::SEPARATOR_ITEM, 0, $m[0][1]+1); |
| | | } |
| | | // cache position of this element, so we can use it in getElement() |
| | | // cache position of this element, so we can use it in get_element() |
| | | $this->meta['pos'][$idx] = (int)$m[0][1]; |
| | | |
| | | return $idx; |
| | |
| | | * |
| | | * @return array List of message identifiers |
| | | */ |
| | | public function getCompressed() |
| | | public function get_compressed() |
| | | { |
| | | if (empty($this->raw_data)) { |
| | | return ''; |
| | |
| | | * |
| | | * @return int Element value |
| | | */ |
| | | public function getElement($index) |
| | | public function get_element($index) |
| | | { |
| | | $count = $this->count(); |
| | | |
| | |
| | | * |
| | | * @return array|string Response parameters or parameter value |
| | | */ |
| | | public function getParameters($param=null) |
| | | public function get_parameters($param=null) |
| | | { |
| | | $params = $this->params; |
| | | $params['MAILBOX'] = $this->mailbox; |
| | |
| | | */ |
| | | public function sort($index) |
| | | { |
| | | $this->sort_order = $index->getParameters('ORDER'); |
| | | $this->sort_order = $index->get_parameters('ORDER'); |
| | | |
| | | if (empty($this->raw_data)) { |
| | | return; |
| | | } |
| | | |
| | | // when sorting search result it's good to make the index smaller |
| | | if ($index->count() != $this->countMessages()) { |
| | | if ($index->count() != $this->count_messages()) { |
| | | $index->intersect($this->get()); |
| | | } |
| | | |
| | |
| | | * |
| | | * @return array Data tree |
| | | */ |
| | | public function getTree() |
| | | public function get_tree() |
| | | { |
| | | $datalen = strlen($this->raw_data); |
| | | $result = array(); |
| | |
| | | $len = $pos - $start; |
| | | $elem = substr($this->raw_data, $start, $len); |
| | | $items = explode(self::SEPARATOR_ITEM, $elem); |
| | | $result[array_shift($items)] = $this->buildThread($items); |
| | | $result[array_shift($items)] = $this->build_thread($items); |
| | | $start = $pos + 1; |
| | | } |
| | | |
| | |
| | | * |
| | | * @return array Thread data |
| | | */ |
| | | public function getThreadData() |
| | | public function get_thread_data() |
| | | { |
| | | $data = $this->getTree(); |
| | | $data = $this->get_tree(); |
| | | $depth = array(); |
| | | $children = array(); |
| | | |
| | | $this->buildThreadData($data, $depth, $children); |
| | | $this->build_thread_data($data, $depth, $children); |
| | | |
| | | return array($depth, $children); |
| | | } |
| | |
| | | /** |
| | | * Creates 'depth' and 'children' arrays from stored thread 'tree' data. |
| | | */ |
| | | private function buildThreadData($data, &$depth, &$children, $level = 0) |
| | | protected function build_thread_data($data, &$depth, &$children, $level = 0) |
| | | { |
| | | foreach ((array)$data as $key => $val) { |
| | | $empty = empty($val) || !is_array($val); |
| | | $children[$key] = !$empty; |
| | | $depth[$key] = $level; |
| | | if (!$empty) { |
| | | $this->buildThreadData($val, $depth, $children, $level + 1); |
| | | $this->build_thread_data($val, $depth, $children, $level + 1); |
| | | } |
| | | } |
| | | } |
| | |
| | | /** |
| | | * Converts part of the raw thread into an array |
| | | */ |
| | | private function buildThread($items, $level = 1, &$pos = 0) |
| | | protected function build_thread($items, $level = 1, &$pos = 0) |
| | | { |
| | | $result = array(); |
| | | |
| | |
| | | list($lv, $id) = explode(self::SEPARATOR_LEVEL, $items[$pos]); |
| | | if ($level == $lv) { |
| | | $pos++; |
| | | $result[$id] = $this->buildThread($items, $level+1, $pos); |
| | | $result[$id] = $this->build_thread($items, $level+1, $pos); |
| | | } |
| | | else { |
| | | $pos--; |
| | |
| | | /** |
| | | * IMAP THREAD response parser |
| | | */ |
| | | private function parseThread($str, $begin = 0, $end = 0, $depth = 0) |
| | | protected function parse_thread($str, $begin = 0, $end = 0, $depth = 0) |
| | | { |
| | | // Don't be tempted to change $str to pass by reference to speed this up - it will slow it down by about |
| | | // 7 times instead :-) See comments on http://uk2.php.net/references and this article: |
| | |
| | | $node .= ($depth ? self::SEPARATOR_ITEM.$depth.self::SEPARATOR_LEVEL : '').$msg; |
| | | |
| | | if ($stop + 1 < $end) { |
| | | $node .= $this->parseThread($str, $stop + 1, $end, $depth + 1); |
| | | $node .= $this->parse_thread($str, $stop + 1, $end, $depth + 1); |
| | | } |
| | | } else { |
| | | $off = $begin; |
| | |
| | | } |
| | | } |
| | | |
| | | $thread = $this->parseThread($str, $start + 1, $off - 1, $depth); |
| | | $thread = $this->parse_thread($str, $start + 1, $off - 1, $depth); |
| | | if ($thread) { |
| | | if (!$depth) { |
| | | if ($node) { |
| | |
| | | |
| | | |
| | | /** |
| | | * A method to guess encoding of a string. |
| | | * |
| | | * @param string $string String. |
| | | * @param string $failover Default result for failover. |
| | | * |
| | | * @return string |
| | | */ |
| | | function rc_detect_encoding($string, $failover='') |
| | | { |
| | | if (!function_exists('mb_detect_encoding')) { |
| | | return $failover; |
| | | } |
| | | |
| | | // FIXME: the order is important, because sometimes |
| | | // iso string is detected as euc-jp and etc. |
| | | $enc = array( |
| | | 'UTF-8', 'SJIS', 'BIG5', 'GB2312', |
| | | 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', |
| | | 'ISO-8859-5', 'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8', 'ISO-8859-9', |
| | | 'ISO-8859-10', 'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'ISO-8859-16', |
| | | 'WINDOWS-1252', 'WINDOWS-1251', 'EUC-JP', 'EUC-TW', 'KOI8-R', |
| | | 'ISO-2022-KR', 'ISO-2022-JP' |
| | | ); |
| | | |
| | | $result = mb_detect_encoding($string, join(',', $enc)); |
| | | |
| | | return $result ? $result : $failover; |
| | | } |
| | | |
| | | /** |
| | | * Removes non-unicode characters from input |
| | | * |
| | | * @param mixed $input String or array. |
| | | * @return string |
| | | */ |
| | | function rc_utf8_clean($input) |
| | | { |
| | | // handle input of type array |
| | | if (is_array($input)) { |
| | | foreach ($input as $idx => $val) |
| | | $input[$idx] = rc_utf8_clean($val); |
| | | return $input; |
| | | } |
| | | |
| | | if (!is_string($input) || $input == '') |
| | | return $input; |
| | | |
| | | // iconv/mbstring are much faster (especially with long strings) |
| | | if (function_exists('mb_convert_encoding') && ($res = mb_convert_encoding($input, 'UTF-8', 'UTF-8')) !== false) |
| | | return $res; |
| | | |
| | | if (function_exists('iconv') && ($res = @iconv('UTF-8', 'UTF-8//IGNORE', $input)) !== false) |
| | | return $res; |
| | | |
| | | $regexp = '/^('. |
| | | // '[\x00-\x7F]'. // UTF8-1 |
| | | '|[\xC2-\xDF][\x80-\xBF]'. // UTF8-2 |
| | | '|\xE0[\xA0-\xBF][\x80-\xBF]'. // UTF8-3 |
| | | '|[\xE1-\xEC][\x80-\xBF][\x80-\xBF]'. // UTF8-3 |
| | | '|\xED[\x80-\x9F][\x80-\xBF]'. // UTF8-3 |
| | | '|[\xEE-\xEF][\x80-\xBF][\x80-\xBF]'. // UTF8-3 |
| | | '|\xF0[\x90-\xBF][\x80-\xBF][\x80-\xBF]'. // UTF8-4 |
| | | '|[\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF]'.// UTF8-4 |
| | | '|\xF4[\x80-\x8F][\x80-\xBF][\x80-\xBF]'. // UTF8-4 |
| | | ')$/'; |
| | | |
| | | $seq = ''; |
| | | $out = ''; |
| | | |
| | | for ($i = 0, $len = strlen($input); $i < $len; $i++) { |
| | | $chr = $input[$i]; |
| | | $ord = ord($chr); |
| | | // 1-byte character |
| | | if ($ord <= 0x7F) { |
| | | if ($seq) |
| | | $out .= preg_match($regexp, $seq) ? $seq : ''; |
| | | $seq = ''; |
| | | $out .= $chr; |
| | | // first (or second) byte of multibyte sequence |
| | | } else if ($ord >= 0xC0) { |
| | | if (strlen($seq)>1) { |
| | | $out .= preg_match($regexp, $seq) ? $seq : ''; |
| | | $seq = ''; |
| | | } else if ($seq && ord($seq) < 0xC0) { |
| | | $seq = ''; |
| | | } |
| | | $seq .= $chr; |
| | | // next byte of multibyte sequence |
| | | } else if ($seq) { |
| | | $seq .= $chr; |
| | | } |
| | | } |
| | | |
| | | if ($seq) |
| | | $out .= preg_match($regexp, $seq) ? $seq : ''; |
| | | |
| | | return $out; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Convert a variable into a javascript object notation |
| | | * |
| | | * @param mixed Input value |
| | | * @return string Serialized JSON string |
| | | */ |
| | | function json_serialize($input) |
| | | { |
| | | $input = rc_utf8_clean($input); |
| | | |
| | | // sometimes even using rc_utf8_clean() the input contains invalid UTF-8 sequences |
| | | // that's why we have @ here |
| | | return @json_encode($input); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Explode quoted string |
| | | * |
| | | * @param string Delimiter expression string for preg_match() |
New file |
| | |
| | | <?php |
| | | |
| | | /* |
| | | +-----------------------------------------------------------------------+ |
| | | | program/include/rcube_storage.php | |
| | | | | |
| | | | This file is part of the Roundcube Webmail client | |
| | | | Copyright (C) 2005-2012, The Roundcube Dev Team | |
| | | | Copyright (C) 2012, Kolab Systems AG | |
| | | | Licensed under the GNU GPL | |
| | | | | |
| | | | PURPOSE: | |
| | | | Mail Storage Engine | |
| | | | | |
| | | +-----------------------------------------------------------------------+ |
| | | | Author: Thomas Bruederli <roundcube@gmail.com> | |
| | | | Author: Aleksander Machniak <alec@alec.pl> | |
| | | +-----------------------------------------------------------------------+ |
| | | |
| | | $Id$ |
| | | |
| | | */ |
| | | |
| | | |
| | | /** |
| | | * Abstract class for accessing mail messages storage server |
| | | * |
| | | * @package Mail |
| | | * @author Thomas Bruederli <roundcube@gmail.com> |
| | | * @author Aleksander Machniak <alec@alec.pl> |
| | | * @version 2.0 |
| | | */ |
| | | abstract class rcube_storage |
| | | { |
| | | /** |
| | | * Instance of connection object e.g. rcube_imap_generic |
| | | * |
| | | * @var mixed |
| | | */ |
| | | public $conn; |
| | | |
| | | protected $folder = 'INBOX'; |
| | | protected $default_charset = 'ISO-8859-1'; |
| | | protected $default_folders = array('INBOX'); |
| | | protected $search_set; |
| | | protected $options = array('auth_method' => 'check'); |
| | | protected $page_size = 10; |
| | | protected $threading = false; |
| | | |
| | | /** |
| | | * All (additional) headers used (in any way) by Roundcube |
| | | * Not listed here: DATE, FROM, TO, CC, REPLY-TO, SUBJECT, CONTENT-TYPE, LIST-POST |
| | | * (used for messages listing) are hardcoded in rcube_imap_generic::fetchHeaders() |
| | | * |
| | | * @var array |
| | | */ |
| | | protected $all_headers = array( |
| | | 'IN-REPLY-TO', |
| | | 'BCC', |
| | | 'MESSAGE-ID', |
| | | 'CONTENT-TRANSFER-ENCODING', |
| | | 'REFERENCES', |
| | | 'X-DRAFT-INFO', |
| | | 'MAIL-FOLLOWUP-TO', |
| | | 'MAIL-REPLY-TO', |
| | | 'RETURN-PATH', |
| | | ); |
| | | |
| | | const UNKNOWN = 0; |
| | | const NOPERM = 1; |
| | | const READONLY = 2; |
| | | const TRYCREATE = 3; |
| | | const INUSE = 4; |
| | | const OVERQUOTA = 5; |
| | | const ALREADYEXISTS = 6; |
| | | const NONEXISTENT = 7; |
| | | const CONTACTADMIN = 8; |
| | | |
| | | |
| | | /** |
| | | * Connect to the server |
| | | * |
| | | * @param string $host Host to connect |
| | | * @param string $user Username for IMAP account |
| | | * @param string $pass Password for IMAP account |
| | | * @param integer $port Port to connect to |
| | | * @param string $use_ssl SSL schema (either ssl or tls) or null if plain connection |
| | | * |
| | | * @return boolean TRUE on success, FALSE on failure |
| | | */ |
| | | abstract function connect($host, $user, $pass, $port = 143, $use_ssl = null); |
| | | |
| | | |
| | | /** |
| | | * Close connection. Usually done on script shutdown |
| | | */ |
| | | abstract function close(); |
| | | |
| | | |
| | | /** |
| | | * Checks connection state. |
| | | * |
| | | * @return boolean TRUE on success, FALSE on failure |
| | | */ |
| | | abstract function is_connected(); |
| | | |
| | | |
| | | /** |
| | | * Returns code of last error |
| | | * |
| | | * @return int Error code |
| | | */ |
| | | abstract function get_error_code(); |
| | | |
| | | |
| | | /** |
| | | * Returns message of last error |
| | | * |
| | | * @return string Error message |
| | | */ |
| | | abstract function get_error_str(); |
| | | |
| | | |
| | | /** |
| | | * Returns code of last command response |
| | | * |
| | | * @return int Response code (class constant) |
| | | */ |
| | | abstract function get_response_code(); |
| | | |
| | | |
| | | /** |
| | | * Set connection and class options |
| | | * |
| | | * @param array $opt Options array |
| | | */ |
| | | public function set_options($opt) |
| | | { |
| | | $this->options = array_merge($this->options, (array)$opt); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Activate/deactivate debug mode. |
| | | * |
| | | * @param boolean $dbg True if conversation with the server should be logged |
| | | */ |
| | | abstract function set_debug($dbg = true); |
| | | |
| | | |
| | | /** |
| | | * Set default message charset. |
| | | * |
| | | * This will be used for message decoding if a charset specification is not available |
| | | * |
| | | * @param string $cs Charset string |
| | | */ |
| | | public function set_charset($cs) |
| | | { |
| | | $this->default_charset = $cs; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * This list of folders will be listed above all other folders |
| | | * |
| | | * @param array $arr Indexed list of folder names |
| | | */ |
| | | public function set_default_folders($arr) |
| | | { |
| | | if (is_array($arr)) { |
| | | $this->default_folders = $arr; |
| | | |
| | | // add inbox if not included |
| | | if (!in_array('INBOX', $this->default_folders)) { |
| | | array_unshift($this->default_folders, 'INBOX'); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Set internal folder reference. |
| | | * All operations will be perfomed on this folder. |
| | | * |
| | | * @param string $folder Folder name |
| | | */ |
| | | public function set_folder($folder) |
| | | { |
| | | if ($this->folder == $folder) { |
| | | return; |
| | | } |
| | | |
| | | $this->folder = $folder; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns the currently used folder name |
| | | * |
| | | * @return string Name of the folder |
| | | */ |
| | | public function get_folder() |
| | | { |
| | | return $this->folder; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Set internal list page number. |
| | | * |
| | | * @param int $page Page number to list |
| | | */ |
| | | public function set_page($page) |
| | | { |
| | | $this->list_page = (int) $page; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Gets internal list page number. |
| | | * |
| | | * @return int Page number |
| | | */ |
| | | public function get_page() |
| | | { |
| | | return $this->list_page; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Set internal page size |
| | | * |
| | | * @param int $size Number of messages to display on one page |
| | | */ |
| | | public function set_pagesize($size) |
| | | { |
| | | $this->page_size = (int) $size; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Get internal page size |
| | | * |
| | | * @return int Number of messages to display on one page |
| | | */ |
| | | public function get_pagesize() |
| | | { |
| | | return $this->page_size; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Save a search result for future message listing methods. |
| | | * |
| | | * @param mixed $set Search set in driver specific format |
| | | */ |
| | | abstract function set_search_set($set); |
| | | |
| | | |
| | | /** |
| | | * Return the saved search set. |
| | | * |
| | | * @return array Search set in driver specific format, NULL if search wasn't initialized |
| | | */ |
| | | abstract function get_search_set(); |
| | | |
| | | |
| | | /** |
| | | * Returns the storage server's (IMAP) capability |
| | | * |
| | | * @param string $cap Capability name |
| | | * |
| | | * @return mixed Capability value or TRUE if supported, FALSE if not |
| | | */ |
| | | abstract function get_capability($cap); |
| | | |
| | | |
| | | /** |
| | | * Sets threading flag to the best supported THREAD algorithm. |
| | | * Enable/Disable threaded mode. |
| | | * |
| | | * @param boolean $enable TRUE to enable and FALSE |
| | | * |
| | | * @return mixed Threading algorithm or False if THREAD is not supported |
| | | */ |
| | | public function set_threading($enable = false) |
| | | { |
| | | $this->threading = false; |
| | | |
| | | if ($enable && ($caps = $this->get_capability('THREAD'))) { |
| | | $methods = array('REFS', 'REFERENCES', 'ORDEREDSUBJECT'); |
| | | $methods = array_intersect($methods, $caps); |
| | | |
| | | $this->threading = array_shift($methods); |
| | | } |
| | | |
| | | return $this->threading; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Get current threading flag. |
| | | * |
| | | * @return mixed Threading algorithm or False if THREAD is not supported or disabled |
| | | */ |
| | | public function get_threading() |
| | | { |
| | | return $this->threading; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Checks the PERMANENTFLAGS capability of the current folder |
| | | * and returns true if the given flag is supported by the server. |
| | | * |
| | | * @param string $flag Permanentflag name |
| | | * |
| | | * @return boolean True if this flag is supported |
| | | */ |
| | | abstract function check_permflag($flag); |
| | | |
| | | |
| | | /** |
| | | * Returns the delimiter that is used by the server |
| | | * for folder hierarchy separation. |
| | | * |
| | | * @return string Delimiter string |
| | | */ |
| | | abstract function get_hierarchy_delimiter(); |
| | | |
| | | |
| | | /** |
| | | * Get namespace |
| | | * |
| | | * @param string $name Namespace array index: personal, other, shared, prefix |
| | | * |
| | | * @return array Namespace data |
| | | */ |
| | | abstract function get_namespace($name = null); |
| | | |
| | | |
| | | /** |
| | | * Get messages count for a specific folder. |
| | | * |
| | | * @param string $folder Folder name |
| | | * @param string $mode Mode for count [ALL|THREADS|UNSEEN|RECENT] |
| | | * @param boolean $force Force reading from server and update cache |
| | | * @param boolean $status Enables storing folder status info (max UID/count), |
| | | * required for folder_status() |
| | | * |
| | | * @return int Number of messages |
| | | */ |
| | | abstract function count($folder = null, $mode = 'ALL', $force = false, $status = true); |
| | | |
| | | |
| | | /** |
| | | * Public method for listing headers. |
| | | * |
| | | * @param string $folder Folder name |
| | | * @param int $page Current page to list |
| | | * @param string $sort_field Header field to sort by |
| | | * @param string $sort_order Sort order [ASC|DESC] |
| | | * @param int $slice Number of slice items to extract from result array |
| | | * |
| | | * @return array Indexed array with message header objects |
| | | */ |
| | | abstract function list_messages($folder = null, $page = null, $sort_field = null, $sort_order = null, $slice = 0); |
| | | |
| | | |
| | | /** |
| | | * Return sorted list of message UIDs |
| | | * |
| | | * @param string $folder Folder to get index from |
| | | * @param string $sort_field Sort column |
| | | * @param string $sort_order Sort order [ASC, DESC] |
| | | * |
| | | * @return rcube_result_index|rcube_result_thread List of messages (UIDs) |
| | | */ |
| | | abstract function index($folder = null, $sort_field = null, $sort_order = null); |
| | | |
| | | |
| | | /** |
| | | * Invoke search request to the server. |
| | | * |
| | | * @param string $folder Folder name to search in |
| | | * @param string $str Search criteria |
| | | * @param string $charset Search charset |
| | | * @param string $sort_field Header field to sort by |
| | | * |
| | | * @todo: Search criteria should be provided in non-IMAP format, eg. array |
| | | */ |
| | | abstract function search($folder = null, $str = 'ALL', $charset = null, $sort_field = null); |
| | | |
| | | |
| | | /** |
| | | * Direct (real and simple) search request (without result sorting and caching). |
| | | * |
| | | * @param string $folder Folder name to search in |
| | | * @param string $str Search string |
| | | * |
| | | * @return rcube_result_index Search result (UIDs) |
| | | */ |
| | | abstract function search_once($folder = null, $str = 'ALL'); |
| | | |
| | | |
| | | /** |
| | | * Refresh saved search set |
| | | * |
| | | * @return array Current search set |
| | | */ |
| | | abstract function refresh_search(); |
| | | |
| | | |
| | | /* -------------------------------- |
| | | * messages management |
| | | * --------------------------------*/ |
| | | |
| | | /** |
| | | * Fetch message headers and body structure from the server and build |
| | | * an object structure similar to the one generated by PEAR::Mail_mimeDecode |
| | | * |
| | | * @param int $uid Message UID to fetch |
| | | * @param string $folder Folder to read from |
| | | * |
| | | * @return object rcube_mail_header Message data |
| | | */ |
| | | abstract function get_message($uid, $folder = null); |
| | | |
| | | |
| | | /** |
| | | * Return message headers object of a specific message |
| | | * |
| | | * @param int $id Message sequence ID or UID |
| | | * @param string $folder Folder to read from |
| | | * @param bool $force True to skip cache |
| | | * |
| | | * @return rcube_mail_header Message headers |
| | | */ |
| | | abstract function get_message_headers($uid, $folder = null, $force = false); |
| | | |
| | | |
| | | /** |
| | | * Fetch message body of a specific message from the server |
| | | * |
| | | * @param int $uid Message UID |
| | | * @param string $part Part number |
| | | * @param rcube_message_part $o_part Part object created by get_structure() |
| | | * @param mixed $print True to print part, ressource to write part contents in |
| | | * @param resource $fp File pointer to save the message part |
| | | * @param boolean $skip_charset_conv Disables charset conversion |
| | | * |
| | | * @return string Message/part body if not printed |
| | | */ |
| | | abstract function get_message_part($uid, $part = 1, $o_part = null, $print = null, $fp = null, $skip_charset_conv = false); |
| | | |
| | | |
| | | /** |
| | | * Fetch message body of a specific message from the server |
| | | * |
| | | * @param int $uid Message UID |
| | | * |
| | | * @return string $part Message/part body |
| | | * @see rcube_imap::get_message_part() |
| | | */ |
| | | public function get_body($uid, $part = 1) |
| | | { |
| | | $headers = $this->get_message_headers($uid); |
| | | return rcube_charset_convert($this->get_message_part($uid, $part, null), |
| | | $headers->charset ? $headers->charset : $this->default_charset); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns the whole message source as string (or saves to a file) |
| | | * |
| | | * @param int $uid Message UID |
| | | * @param resource $fp File pointer to save the message |
| | | * |
| | | * @return string Message source string |
| | | */ |
| | | abstract function get_raw_body($uid, $fp = null); |
| | | |
| | | |
| | | /** |
| | | * Returns the message headers as string |
| | | * |
| | | * @param int $uid Message UID |
| | | * |
| | | * @return string Message headers string |
| | | */ |
| | | abstract function get_raw_headers($uid); |
| | | |
| | | |
| | | /** |
| | | * Sends the whole message source to stdout |
| | | */ |
| | | abstract function print_raw_body($uid); |
| | | |
| | | |
| | | /** |
| | | * Set message flag to one or several messages |
| | | * |
| | | * @param mixed $uids Message UIDs as array or comma-separated string, or '*' |
| | | * @param string $flag Flag to set: SEEN, UNDELETED, DELETED, RECENT, ANSWERED, DRAFT, MDNSENT |
| | | * @param string $folder Folder name |
| | | * @param boolean $skip_cache True to skip message cache clean up |
| | | * |
| | | * @return bool Operation status |
| | | */ |
| | | abstract function set_flag($uids, $flag, $folder = null, $skip_cache = false); |
| | | |
| | | |
| | | /** |
| | | * Remove message flag for one or several messages |
| | | * |
| | | * @param mixed $uids Message UIDs as array or comma-separated string, or '*' |
| | | * @param string $flag Flag to unset: SEEN, DELETED, RECENT, ANSWERED, DRAFT, MDNSENT |
| | | * @param string $folder Folder name |
| | | * |
| | | * @return bool Operation status |
| | | * @see set_flag |
| | | */ |
| | | public function unset_flag($uids, $flag, $folder = null) |
| | | { |
| | | return $this->set_flag($uids, 'UN'.$flag, $folder); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Append a mail message (source) to a specific folder. |
| | | * |
| | | * @param string $folder Target folder |
| | | * @param string $message The message source string or filename |
| | | * @param string $headers Headers string if $message contains only the body |
| | | * @param boolean $is_file True if $message is a filename |
| | | * |
| | | * @return int|bool Appended message UID or True on success, False on error |
| | | */ |
| | | abstract function save_message($folder, &$message, $headers = '', $is_file = false); |
| | | |
| | | |
| | | /** |
| | | * Move message(s) from one folder to another. |
| | | * |
| | | * @param mixed $uids Message UIDs as array or comma-separated string, or '*' |
| | | * @param string $to Target folder |
| | | * @param string $from Source folder |
| | | * |
| | | * @return boolean True on success, False on error |
| | | */ |
| | | abstract function move_message($uids, $to, $from = null); |
| | | |
| | | |
| | | /** |
| | | * Copy message(s) from one mailbox to another. |
| | | * |
| | | * @param mixed $uids Message UIDs as array or comma-separated string, or '*' |
| | | * @param string $to Target folder |
| | | * @param string $from Source folder |
| | | * |
| | | * @return boolean True on success, False on error |
| | | */ |
| | | abstract function copy_message($uids, $to, $from = null); |
| | | |
| | | |
| | | /** |
| | | * Mark message(s) as deleted and expunge. |
| | | * |
| | | * @param mixed $uids Message UIDs as array or comma-separated string, or '*' |
| | | * @param string $folder Source folder |
| | | * |
| | | * @return boolean True on success, False on error |
| | | */ |
| | | abstract function delete_message($uids, $folder = null); |
| | | |
| | | |
| | | /** |
| | | * Expunge message(s) and clear the cache. |
| | | * |
| | | * @param mixed $uids Message UIDs as array or comma-separated string, or '*' |
| | | * @param string $folder Folder name |
| | | * @param boolean $clear_cache False if cache should not be cleared |
| | | * |
| | | * @return boolean True on success, False on error |
| | | */ |
| | | abstract function expunge_message($uids, $folder = null, $clear_cache = true); |
| | | |
| | | |
| | | /** |
| | | * Parse message UIDs input |
| | | * |
| | | * @param mixed $uids UIDs array or comma-separated list or '*' or '1:*' |
| | | * |
| | | * @return array Two elements array with UIDs converted to list and ALL flag |
| | | */ |
| | | protected function parse_uids($uids) |
| | | { |
| | | if ($uids === '*' || $uids === '1:*') { |
| | | if (empty($this->search_set)) { |
| | | $uids = '1:*'; |
| | | $all = true; |
| | | } |
| | | // get UIDs from current search set |
| | | else { |
| | | $uids = join(',', $this->search_set->get()); |
| | | } |
| | | } |
| | | else { |
| | | if (is_array($uids)) { |
| | | $uids = join(',', $uids); |
| | | } |
| | | |
| | | if (preg_match('/[^0-9,]/', $uids)) { |
| | | $uids = ''; |
| | | } |
| | | } |
| | | |
| | | return array($uids, (bool) $all); |
| | | } |
| | | |
| | | |
| | | /* -------------------------------- |
| | | * folder managment |
| | | * --------------------------------*/ |
| | | |
| | | /** |
| | | * Get a list of subscribed folders. |
| | | * |
| | | * @param string $root Optional root folder |
| | | * @param string $name Optional name pattern |
| | | * @param string $filter Optional filter |
| | | * @param string $rights Optional ACL requirements |
| | | * @param bool $skip_sort Enable to return unsorted list (for better performance) |
| | | * |
| | | * @return array List of folders |
| | | */ |
| | | abstract function list_folders_subscribed($root = '', $name = '*', $filter = null, $rights = null, $skip_sort = false); |
| | | |
| | | |
| | | /** |
| | | * Get a list of all folders available on the server. |
| | | * |
| | | * @param string $root IMAP root dir |
| | | * @param string $name Optional name pattern |
| | | * @param mixed $filter Optional filter |
| | | * @param string $rights Optional ACL requirements |
| | | * @param bool $skip_sort Enable to return unsorted list (for better performance) |
| | | * |
| | | * @return array Indexed array with folder names |
| | | */ |
| | | abstract function list_folders($root = '', $name = '*', $filter = null, $rights = null, $skip_sort = false); |
| | | |
| | | |
| | | /** |
| | | * Subscribe to a specific folder(s) |
| | | * |
| | | * @param array $folders Folder name(s) |
| | | * |
| | | * @return boolean True on success |
| | | */ |
| | | abstract function subscribe($folders); |
| | | |
| | | |
| | | /** |
| | | * Unsubscribe folder(s) |
| | | * |
| | | * @param array $folders Folder name(s) |
| | | * |
| | | * @return boolean True on success |
| | | */ |
| | | abstract function unsubscribe($folders); |
| | | |
| | | |
| | | /** |
| | | * Create a new folder on the server. |
| | | * |
| | | * @param string $folder New folder name |
| | | * @param boolean $subscribe True if the newvfolder should be subscribed |
| | | * |
| | | * @return boolean True on success, False on error |
| | | */ |
| | | abstract function create_folder($folder, $subscribe = false); |
| | | |
| | | |
| | | /** |
| | | * Set a new name to an existing folder |
| | | * |
| | | * @param string $folder Folder to rename |
| | | * @param string $new_name New folder name |
| | | * |
| | | * @return boolean True on success, False on error |
| | | */ |
| | | abstract function rename_folder($folder, $new_name); |
| | | |
| | | |
| | | /** |
| | | * Remove a folder from the server. |
| | | * |
| | | * @param string $folder Folder name |
| | | * |
| | | * @return boolean True on success, False on error |
| | | */ |
| | | abstract function delete_folder($folder); |
| | | |
| | | |
| | | /** |
| | | * Send expunge command and clear the cache. |
| | | * |
| | | * @param string $folder Folder name |
| | | * @param boolean $clear_cache False if cache should not be cleared |
| | | * |
| | | * @return boolean True on success, False on error |
| | | */ |
| | | public function expunge_folder($folder = null, $clear_cache = true) |
| | | { |
| | | return $this->expunge_message('*', $folder, $clear_cache); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Remove all messages in a folder.. |
| | | * |
| | | * @param string $folder Folder name |
| | | * |
| | | * @return boolean True on success, False on error |
| | | */ |
| | | public function clear_folder($folder = null) |
| | | { |
| | | return $this->delete_message('*', $folder); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Checks if folder exists and is subscribed |
| | | * |
| | | * @param string $folder Folder name |
| | | * @param boolean $subscription Enable subscription checking |
| | | * |
| | | * @return boolean True if folder exists, False otherwise |
| | | */ |
| | | abstract function folder_exists($folder, $subscription = false); |
| | | |
| | | |
| | | /** |
| | | * Get folder size (size of all messages in a folder) |
| | | * |
| | | * @param string $folder Folder name |
| | | * |
| | | * @return int Folder size in bytes, False on error |
| | | */ |
| | | abstract function folder_size($folder); |
| | | |
| | | |
| | | /** |
| | | * Returns the namespace where the folder is in |
| | | * |
| | | * @param string $folder Folder name |
| | | * |
| | | * @return string One of 'personal', 'other' or 'shared' |
| | | */ |
| | | abstract function folder_namespace($folder); |
| | | |
| | | |
| | | /** |
| | | * Gets folder attributes (from LIST response, e.g. \Noselect, \Noinferiors). |
| | | * |
| | | * @param string $folder Folder name |
| | | * @param bool $force Set to True if attributes should be refreshed |
| | | * |
| | | * @return array Options list |
| | | */ |
| | | abstract function folder_attributes($folder, $force = false); |
| | | |
| | | |
| | | /** |
| | | * Gets connection (and current folder) data: UIDVALIDITY, EXISTS, RECENT, |
| | | * PERMANENTFLAGS, UIDNEXT, UNSEEN |
| | | * |
| | | * @param string $folder Folder name |
| | | * |
| | | * @return array Data |
| | | */ |
| | | abstract function folder_data($folder); |
| | | |
| | | |
| | | /** |
| | | * Returns extended information about the folder. |
| | | * |
| | | * @param string $folder Folder name |
| | | * |
| | | * @return array Data |
| | | */ |
| | | abstract function folder_info($folder); |
| | | |
| | | |
| | | /** |
| | | * Returns current status of a folder |
| | | * |
| | | * @param string $folder Folder name |
| | | * |
| | | * @return int Folder status |
| | | */ |
| | | abstract function folder_status($folder = null); |
| | | |
| | | |
| | | /** |
| | | * Synchronizes messages cache. |
| | | * |
| | | * @param string $folder Folder name |
| | | */ |
| | | abstract function folder_sync($folder); |
| | | |
| | | |
| | | /** |
| | | * Modify folder name according to namespace. |
| | | * For output it removes prefix of the personal namespace if it's possible. |
| | | * For input it adds the prefix. Use it before creating a folder in root |
| | | * of the folders tree. |
| | | * |
| | | * @param string $folder Folder name |
| | | * @param string $mode Mode name (out/in) |
| | | * |
| | | * @return string Folder name |
| | | */ |
| | | abstract function mod_folder($folder, $mode = 'out'); |
| | | |
| | | |
| | | /** |
| | | * Create all folders specified as default |
| | | */ |
| | | public function create_default_folders() |
| | | { |
| | | // create default folders if they do not exist |
| | | foreach ($this->default_folders as $folder) { |
| | | if (!$this->folder_exists($folder)) { |
| | | $this->create_folder($folder, true); |
| | | } |
| | | else if (!$this->folder_exists($folder, true)) { |
| | | $this->subscribe($folder); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Get mailbox quota information. |
| | | * |
| | | * @return mixed Quota info or False if not supported |
| | | */ |
| | | abstract function get_quota(); |
| | | |
| | | |
| | | /* ----------------------------------------- |
| | | * ACL and METADATA methods |
| | | * ----------------------------------------*/ |
| | | |
| | | /** |
| | | * Changes the ACL on the specified folder (SETACL) |
| | | * |
| | | * @param string $folder Folder name |
| | | * @param string $user User name |
| | | * @param string $acl ACL string |
| | | * |
| | | * @return boolean True on success, False on failure |
| | | */ |
| | | abstract function set_acl($folder, $user, $acl); |
| | | |
| | | |
| | | /** |
| | | * Removes any <identifier,rights> pair for the |
| | | * specified user from the ACL for the specified |
| | | * folder (DELETEACL). |
| | | * |
| | | * @param string $folder Folder name |
| | | * @param string $user User name |
| | | * |
| | | * @return boolean True on success, False on failure |
| | | */ |
| | | abstract function delete_acl($folder, $user); |
| | | |
| | | |
| | | /** |
| | | * Returns the access control list for a folder (GETACL). |
| | | * |
| | | * @param string $folder Folder name |
| | | * |
| | | * @return array User-rights array on success, NULL on error |
| | | */ |
| | | abstract function get_acl($folder); |
| | | |
| | | |
| | | /** |
| | | * Returns information about what rights can be granted to the |
| | | * user (identifier) in the ACL for the folder (LISTRIGHTS). |
| | | * |
| | | * @param string $folder Folder name |
| | | * @param string $user User name |
| | | * |
| | | * @return array List of user rights |
| | | */ |
| | | abstract function list_rights($folder, $user); |
| | | |
| | | |
| | | /** |
| | | * Returns the set of rights that the current user has to a folder (MYRIGHTS). |
| | | * |
| | | * @param string $folder Folder name |
| | | * |
| | | * @return array MYRIGHTS response on success, NULL on error |
| | | */ |
| | | abstract function my_rights($folder); |
| | | |
| | | |
| | | /** |
| | | * Sets metadata/annotations (SETMETADATA/SETANNOTATION) |
| | | * |
| | | * @param string $folder Folder name (empty for server metadata) |
| | | * @param array $entries Entry-value array (use NULL value as NIL) |
| | | * |
| | | * @return boolean True on success, False on failure |
| | | */ |
| | | abstract function set_metadata($folder, $entries); |
| | | |
| | | |
| | | /** |
| | | * Unsets metadata/annotations (SETMETADATA/SETANNOTATION) |
| | | * |
| | | * @param string $folder Folder name (empty for server metadata) |
| | | * @param array $entries Entry names array |
| | | * |
| | | * @return boolean True on success, False on failure |
| | | */ |
| | | abstract function delete_metadata($folder, $entries); |
| | | |
| | | |
| | | /** |
| | | * Returns folder metadata/annotations (GETMETADATA/GETANNOTATION). |
| | | * |
| | | * @param string $folder Folder name (empty for server metadata) |
| | | * @param array $entries Entries |
| | | * @param array $options Command options (with MAXSIZE and DEPTH keys) |
| | | * |
| | | * @return array Metadata entry-value hash array on success, NULL on error |
| | | */ |
| | | abstract function get_metadata($folder, $entries, $options = array()); |
| | | |
| | | |
| | | /* ----------------------------------------- |
| | | * Cache related functions |
| | | * ----------------------------------------*/ |
| | | |
| | | /** |
| | | * Clears the cache. |
| | | * |
| | | * @param string $key Cache key name or pattern |
| | | * @param boolean $prefix_mode Enable it to clear all keys starting |
| | | * with prefix specified in $key |
| | | */ |
| | | abstract function clear_cache($key = null, $prefix_mode = false); |
| | | |
| | | /** |
| | | * Returns cached value |
| | | * |
| | | * @param string $key Cache key |
| | | * |
| | | * @return mixed Cached value |
| | | */ |
| | | abstract function get_cache($key); |
| | | |
| | | } // end class rcube_storage |
| | | |
| | | |
| | | /** |
| | | * Class representing a message part |
| | | * |
| | | * @package Mail |
| | | */ |
| | | class rcube_message_part |
| | | { |
| | | var $mime_id = ''; |
| | | var $ctype_primary = 'text'; |
| | | var $ctype_secondary = 'plain'; |
| | | var $mimetype = 'text/plain'; |
| | | var $disposition = ''; |
| | | var $filename = ''; |
| | | var $encoding = '8bit'; |
| | | var $charset = ''; |
| | | var $size = 0; |
| | | var $headers = array(); |
| | | var $d_parameters = array(); |
| | | var $ctype_parameters = array(); |
| | | |
| | | function __clone() |
| | | { |
| | | if (isset($this->parts)) { |
| | | foreach ($this->parts as $idx => $part) { |
| | | if (is_object($part)) { |
| | | $this->parts[$idx] = clone $part; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Class for sorting an array of rcube_mail_header objects in a predetermined order. |
| | | * |
| | | * @package Mail |
| | | * @author Eric Stadtherr |
| | | */ |
| | | class rcube_header_sorter |
| | | { |
| | | private $uids = array(); |
| | | |
| | | |
| | | /** |
| | | * Set the predetermined sort order. |
| | | * |
| | | * @param array $index Numerically indexed array of IMAP UIDs |
| | | */ |
| | | function set_index($index) |
| | | { |
| | | $index = array_flip($index); |
| | | |
| | | $this->uids = $index; |
| | | } |
| | | |
| | | /** |
| | | * Sort the array of header objects |
| | | * |
| | | * @param array $headers Array of rcube_mail_header objects indexed by UID |
| | | */ |
| | | function sort_headers(&$headers) |
| | | { |
| | | uksort($headers, array($this, "compare_uids")); |
| | | } |
| | | |
| | | /** |
| | | * Sort method called by uksort() |
| | | * |
| | | * @param int $a Array key (UID) |
| | | * @param int $b Array key (UID) |
| | | */ |
| | | function compare_uids($a, $b) |
| | | { |
| | | // then find each sequence number in my ordered list |
| | | $posa = isset($this->uids[$a]) ? intval($this->uids[$a]) : -1; |
| | | $posb = isset($this->uids[$b]) ? intval($this->uids[$b]) : -1; |
| | | |
| | | // return the relative position as the comparison value |
| | | return $posa - $posb; |
| | | } |
| | | } |
old mode 100755
new mode 100644
| | |
| | | break; |
| | | case 'config': |
| | | $value = $this->config[$name]; |
| | | if (is_array($value) && $value[$_SESSION['imap_host']]) { |
| | | $value = $value[$_SESSION['imap_host']]; |
| | | if (is_array($value) && $value[$_SESSION['storage_host']]) { |
| | | $value = $value[$_SESSION['storage_host']]; |
| | | } |
| | | break; |
| | | case 'request': |
| | |
| | | $messages['loginfailed'] = 'Login failed.'; |
| | | $messages['cookiesdisabled'] = 'Your browser does not accept cookies.'; |
| | | $messages['sessionerror'] = 'Your session is invalid or expired.'; |
| | | $messages['imaperror'] = 'Connection to IMAP server failed.'; |
| | | $messages['storageerror'] = 'Connection to storage server failed.'; |
| | | $messages['servererror'] = 'Server Error!'; |
| | | $messages['servererrormsg'] = 'Server Error: $msg'; |
| | | $messages['dberror'] = 'Database Error!'; |
| | |
| | | |
| | | */ |
| | | |
| | | $current = $RCMAIL->imap->get_mailbox_name(); |
| | | $current = $RCMAIL->storage->get_folder(); |
| | | $check_all = !empty($_GET['_refresh']) || (bool)$RCMAIL->config->get('check_all_folders'); |
| | | |
| | | // list of folders to check |
| | | if ($check_all) { |
| | | $a_mailboxes = $RCMAIL->imap->list_mailboxes('', '*', 'mail'); |
| | | $a_mailboxes = $RCMAIL->storage->list_folders_subscribed('', '*', 'mail'); |
| | | } |
| | | else { |
| | | $a_mailboxes = (array) $current; |
| | |
| | | $is_current = $mbox_name == $current; |
| | | if ($is_current) { |
| | | // Synchronize mailbox cache, handle flag changes |
| | | $RCMAIL->imap->mailbox_sync($mbox_name); |
| | | $RCMAIL->storage->folder_sync($mbox_name); |
| | | } |
| | | |
| | | // Get mailbox status |
| | | $status = $RCMAIL->imap->mailbox_status($mbox_name); |
| | | $status = $RCMAIL->storage->folder_status($mbox_name); |
| | | |
| | | if ($status & 1) { |
| | | // trigger plugin hook |
| | |
| | | if ($search_request && isset($_SESSION['search']) |
| | | && $_SESSION['search_request'] == $search_request |
| | | ) { |
| | | $_SESSION['search'] = $RCMAIL->imap->refresh_search(); |
| | | $_SESSION['search'] = $RCMAIL->storage->refresh_search(); |
| | | } |
| | | |
| | | if (!empty($_GET['_quota'])) |
| | |
| | | if (empty($_GET['_list'])) |
| | | continue; |
| | | |
| | | // get overall message count; allow caching because rcube_imap::mailbox_status() did a refresh |
| | | $all_count = $RCMAIL->imap->messagecount(null, $RCMAIL->imap->threading ? 'THREADS' : 'ALL'); |
| | | // get overall message count; allow caching because rcube_storage::folder_status() did a refresh |
| | | $all_count = $RCMAIL->storage->count(null, $RCMAIL->storage->get_threading() ? 'THREADS' : 'ALL'); |
| | | |
| | | $page = $RCMAIL->storage->get_page(); |
| | | $page_size = $RCMAIL->storage->get_pagesize(); |
| | | |
| | | // check current page if we're not on the first page |
| | | if ($all_count && $RCMAIL->imap->list_page > 1) { |
| | | $remaining = $all_count - $RCMAIL->imap->page_size * ($RCMAIL->imap->list_page - 1); |
| | | if ($all_count && $page > 1) { |
| | | $remaining = $all_count - $page_size * ($page - 1); |
| | | if ($remaining <= 0) { |
| | | $RCMAIL->imap->set_page($RCMAIL->imap->list_page-1); |
| | | $_SESSION['page'] = $RCMAIL->imap->list_page; |
| | | $page -= 1; |
| | | $RCMAIL->storage->set_page($page); |
| | | $_SESSION['page'] = $page; |
| | | } |
| | | } |
| | | |
| | | $OUTPUT->set_env('messagecount', $all_count); |
| | | $OUTPUT->set_env('pagecount', ceil($all_count/$RCMAIL->imap->page_size)); |
| | | $OUTPUT->set_env('pagecount', ceil($all_count/$page_size)); |
| | | $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($all_count), $mbox_name); |
| | | $OUTPUT->set_env('current_page', $all_count ? $RCMAIL->imap->list_page : 1); |
| | | $OUTPUT->set_env('current_page', $all_count ? $page : 1); |
| | | |
| | | // remove old rows (and clear selection if new list is empty) |
| | | $OUTPUT->command('message_list.clear', $all_count ? false : true); |
| | | |
| | | if ($all_count) { |
| | | $a_headers = $RCMAIL->imap->list_headers($mbox_name, null, $_SESSION['sort_col'], $_SESSION['sort_order']); |
| | | $a_headers = $RCMAIL->storage->list_messages($mbox_name, null, $_SESSION['sort_col'], $_SESSION['sort_order']); |
| | | // add message rows |
| | | rcmail_js_message_list($a_headers, false); |
| | | // remove messages that don't exists from list selection array |
| | |
| | | $_SESSION['compose_data_'.$COMPOSE_ID] = array( |
| | | 'id' => $COMPOSE_ID, |
| | | 'param' => request2param(RCUBE_INPUT_GET), |
| | | 'mailbox' => $RCMAIL->imap->get_mailbox_name(), |
| | | 'mailbox' => $RCMAIL->storage->get_folder(), |
| | | ); |
| | | $COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID]; |
| | | |
| | |
| | | $OUTPUT->set_env('draft_autosave', $CONFIG['draft_autosave']); |
| | | } |
| | | // set current mailbox in client environment |
| | | $OUTPUT->set_env('mailbox', $RCMAIL->imap->get_mailbox_name()); |
| | | $OUTPUT->set_env('mailbox', $RCMAIL->storage->get_folder()); |
| | | $OUTPUT->set_env('sig_above', $RCMAIL->config->get('sig_above', false)); |
| | | $OUTPUT->set_env('top_posting', $RCMAIL->config->get('top_posting', false)); |
| | | $OUTPUT->set_env('recipients_separator', trim($RCMAIL->config->get('recipients_separator', ','))); |
| | |
| | | |
| | | // get reference message and set compose mode |
| | | if ($msg_uid = $COMPOSE['param']['draft_uid']) { |
| | | $RCMAIL->imap->set_mailbox($CONFIG['drafts_mbox']); |
| | | $RCMAIL->storage->set_folder($CONFIG['drafts_mbox']); |
| | | $compose_mode = RCUBE_COMPOSE_DRAFT; |
| | | } |
| | | else if ($msg_uid = $COMPOSE['param']['reply_uid']) |
| | |
| | | |
| | | // make sure message is marked as read |
| | | if ($MESSAGE && $MESSAGE->headers && empty($MESSAGE->headers->flags['SEEN'])) |
| | | $RCMAIL->imap->set_flag($msg_uid, 'SEEN'); |
| | | $RCMAIL->storage->set_flag($msg_uid, 'SEEN'); |
| | | |
| | | if (!empty($MESSAGE->headers->charset)) |
| | | $RCMAIL->imap->set_charset($MESSAGE->headers->charset); |
| | | $RCMAIL->storage->set_charset($MESSAGE->headers->charset); |
| | | |
| | | if ($compose_mode == RCUBE_COMPOSE_REPLY) |
| | | { |
| | |
| | | $temp_dir = unslashify($RCMAIL->config->get('temp_dir')); |
| | | $path = tempnam($temp_dir, 'rcmAttmnt'); |
| | | if ($fp = fopen($path, 'w')) { |
| | | $RCMAIL->imap->get_raw_body($message->uid, $fp); |
| | | $RCMAIL->storage->get_raw_body($message->uid, $fp); |
| | | fclose($fp); |
| | | } else |
| | | return false; |
| | | } else { |
| | | $data = $RCMAIL->imap->get_raw_body($message->uid); |
| | | $data = $RCMAIL->storage->get_raw_body($message->uid); |
| | | } |
| | | |
| | | $attachment = array( |
| | |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | if ($RCMAIL->imap->mailbox_exists($folder, true)) { |
| | | if ($RCMAIL->storage->folder_exists($folder, true)) { |
| | | return true; |
| | | } |
| | | |
| | | // folder may exist but isn't subscribed (#1485241) |
| | | if ($create) { |
| | | if (!$RCMAIL->imap->mailbox_exists($folder)) |
| | | return $RCMAIL->imap->create_mailbox($folder, true); |
| | | if (!$RCMAIL->storage->folder_exists($folder)) |
| | | return $RCMAIL->storage->create_folder($folder, true); |
| | | else |
| | | return $RCMAIL->imap->subscribe($folder); |
| | | return $RCMAIL->storage->subscribe($folder); |
| | | } |
| | | |
| | | return false; |
| | |
| | | $target = get_input_value('_target_mbox', RCUBE_INPUT_POST, true); |
| | | $mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true); |
| | | |
| | | $copied = $RCMAIL->imap->copy_message($uids, $target, $mbox); |
| | | $copied = $RCMAIL->storage->copy_message($uids, $target, $mbox); |
| | | |
| | | if (!$copied) { |
| | | // send error message |
| | |
| | | // send EXPUNGE command |
| | | if ($RCMAIL->action == 'expunge') { |
| | | |
| | | $success = $RCMAIL->imap->expunge($mbox); |
| | | $success = $RCMAIL->storage->expunge_folder($mbox); |
| | | |
| | | // reload message list if current mailbox |
| | | if ($success) { |
| | |
| | | // clear mailbox |
| | | else if ($RCMAIL->action == 'purge') |
| | | { |
| | | $delimiter = $RCMAIL->imap->get_hierarchy_delimiter(); |
| | | $delimiter = $RCMAIL->storage->get_hierarchy_delimiter(); |
| | | $trash_regexp = '/^' . preg_quote($CONFIG['trash_mbox'] . $delimiter, '/') . '/'; |
| | | $junk_regexp = '/^' . preg_quote($CONFIG['junk_mbox'] . $delimiter, '/') . '/'; |
| | | |
| | |
| | | if ($mbox == $CONFIG['trash_mbox'] || $mbox == $CONFIG['junk_mbox'] |
| | | || preg_match($trash_regexp, $mbox) || preg_match($junk_regexp, $mbox) |
| | | ) { |
| | | $success = $RCMAIL->imap->clear_mailbox($mbox); |
| | | $success = $RCMAIL->storage->clear_folder($mbox); |
| | | |
| | | if ($success) { |
| | | $OUTPUT->show_message('folderpurged', 'confirmation'); |
| | |
| | | $DRAFTS_MBOX => array('subject'=>1, 'to'=>1) |
| | | ); |
| | | |
| | | // actions that do not require imap connection here |
| | | $NOIMAP_ACTIONS = array('addcontact', 'autocomplete', 'upload', 'display-attachment', 'remove-attachment', 'get'); |
| | | |
| | | // always instantiate imap object (but not yet connect to server) |
| | | $RCMAIL->imap_init(); |
| | | |
| | | // log in to imap server |
| | | if (!in_array($RCMAIL->action, $NOIMAP_ACTIONS) && !$RCMAIL->imap_connect()) { |
| | | $RCMAIL->kill_session(); |
| | | |
| | | if ($OUTPUT->ajax_call) |
| | | $OUTPUT->redirect(array(), 2000); |
| | | |
| | | $OUTPUT->set_env('task', 'login'); |
| | | $OUTPUT->send('login'); |
| | | } |
| | | // always instantiate storage object (but not connect to server yet) |
| | | $RCMAIL->storage_init(); |
| | | |
| | | // set imap properties and session vars |
| | | if (strlen(trim($mbox = get_input_value('_mbox', RCUBE_INPUT_GPC, true)))) |
| | | $RCMAIL->imap->set_mailbox(($_SESSION['mbox'] = $mbox)); |
| | | else if ($RCMAIL->imap) |
| | | $_SESSION['mbox'] = $RCMAIL->imap->get_mailbox_name(); |
| | | $RCMAIL->storage->set_folder(($_SESSION['mbox'] = $mbox)); |
| | | else if ($RCMAIL->storage) |
| | | $_SESSION['mbox'] = $RCMAIL->storage->get_folder(); |
| | | |
| | | if (!empty($_GET['_page'])) |
| | | $RCMAIL->imap->set_page(($_SESSION['page'] = intval($_GET['_page']))); |
| | | $RCMAIL->storage->set_page(($_SESSION['page'] = intval($_GET['_page']))); |
| | | |
| | | // set default sort col/order to session |
| | | if (!isset($_SESSION['sort_col'])) |
| | |
| | | unset($a_threading[$_SESSION['mbox']]); |
| | | $RCMAIL->user->save_prefs(array('message_threading' => $a_threading)); |
| | | } |
| | | $RCMAIL->imap->set_threading($a_threading[$_SESSION['mbox']]); |
| | | $RCMAIL->storage->set_threading($a_threading[$_SESSION['mbox']]); |
| | | |
| | | // set message set for search result |
| | | if (!empty($_REQUEST['_search']) && isset($_SESSION['search']) |
| | | && $_SESSION['search_request'] == $_REQUEST['_search'] |
| | | ) { |
| | | $RCMAIL->imap->set_search_set($_SESSION['search']); |
| | | $RCMAIL->storage->set_search_set($_SESSION['search']); |
| | | $OUTPUT->set_env('search_request', $_REQUEST['_search']); |
| | | $OUTPUT->set_env('search_text', $_SESSION['last_text_search']); |
| | | } |
| | | |
| | | // set main env variables, labels and page title |
| | | if (empty($RCMAIL->action) || $RCMAIL->action == 'list') { |
| | | $mbox_name = $RCMAIL->imap->get_mailbox_name(); |
| | | $mbox_name = $RCMAIL->storage->get_folder(); |
| | | |
| | | if (empty($RCMAIL->action)) { |
| | | // initialize searching result if search_filter is used |
| | | if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL') { |
| | | $search_request = md5($mbox_name.$_SESSION['search_filter']); |
| | | |
| | | $RCMAIL->imap->search($mbox_name, $_SESSION['search_filter'], RCMAIL_CHARSET, $_SESSION['sort_col']); |
| | | $_SESSION['search'] = $RCMAIL->imap->get_search_set(); |
| | | $RCMAIL->storage->search($mbox_name, $_SESSION['search_filter'], RCMAIL_CHARSET, $_SESSION['sort_col']); |
| | | $_SESSION['search'] = $RCMAIL->storage->get_search_set(); |
| | | $_SESSION['search_request'] = $search_request; |
| | | $OUTPUT->set_env('search_request', $search_request); |
| | | } |
| | |
| | | $OUTPUT->set_env('search_mods', $search_mods); |
| | | } |
| | | |
| | | $threading = (bool) $RCMAIL->storage->get_threading(); |
| | | |
| | | // set current mailbox and some other vars in client environment |
| | | $OUTPUT->set_env('mailbox', $mbox_name); |
| | | $OUTPUT->set_env('pagesize', $RCMAIL->imap->page_size); |
| | | $OUTPUT->set_env('quota', $RCMAIL->imap->get_capability('QUOTA')); |
| | | $OUTPUT->set_env('delimiter', $RCMAIL->imap->get_hierarchy_delimiter()); |
| | | $OUTPUT->set_env('threading', (bool) $RCMAIL->imap->threading); |
| | | $OUTPUT->set_env('threads', $RCMAIL->imap->threading || $RCMAIL->imap->get_capability('THREAD')); |
| | | $OUTPUT->set_env('pagesize', $RCMAIL->storage->get_pagesize()); |
| | | $OUTPUT->set_env('quota', $RCMAIL->storage->get_capability('QUOTA')); |
| | | $OUTPUT->set_env('delimiter', $RCMAIL->storage->get_hierarchy_delimiter()); |
| | | $OUTPUT->set_env('threading', $threading); |
| | | $OUTPUT->set_env('threads', $threading || $RCMAIL->storage->get_capability('THREAD')); |
| | | $OUTPUT->set_env('preview_pane_mark_read', $RCMAIL->config->get('preview_pane_mark_read', 0)); |
| | | |
| | | if ($CONFIG['flag_for_deletion']) |
| | |
| | | 'movingmessage', 'copyingmessage', 'deletingmessage', 'markingmessage', |
| | | 'copy', 'move', 'quota'); |
| | | |
| | | $OUTPUT->set_pagetitle(rcmail_localize_foldername($RCMAIL->imap->mod_mailbox($mbox_name))); |
| | | $OUTPUT->set_pagetitle(rcmail_localize_foldername($RCMAIL->storage->mod_folder($mbox_name))); |
| | | } |
| | | |
| | | |
| | |
| | | // save some variables for use in ajax list |
| | | $_SESSION['list_attrib'] = $attrib; |
| | | |
| | | $mbox = $RCMAIL->imap->get_mailbox_name(); |
| | | $delim = $RCMAIL->imap->get_hierarchy_delimiter(); |
| | | $mbox = $RCMAIL->storage->get_folder(); |
| | | $delim = $RCMAIL->storage->get_hierarchy_delimiter(); |
| | | |
| | | // show 'to' instead of 'from' in sent/draft messages |
| | | if ((strpos($mbox.$delim, $CONFIG['sent_mbox'].$delim)===0 || strpos($mbox.$delim, $CONFIG['drafts_mbox'].$delim)===0) |
| | |
| | | $head_replace = true; |
| | | } |
| | | |
| | | $mbox = $RCMAIL->imap->get_mailbox_name(); |
| | | $delim = $RCMAIL->imap->get_hierarchy_delimiter(); |
| | | $mbox = $RCMAIL->storage->get_folder(); |
| | | $delim = $RCMAIL->storage->get_hierarchy_delimiter(); |
| | | |
| | | // make sure 'threads' and 'subject' columns are present |
| | | if (!in_array('subject', $a_show_cols)) |
| | |
| | | $insert_top); |
| | | } |
| | | |
| | | if ($RCMAIL->imap->threading) { |
| | | if ($RCMAIL->storage->get_threading()) { |
| | | $OUTPUT->command('init_threads', (array) $roots, $mbox); |
| | | } |
| | | } |
| | |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | if ($page===NULL) |
| | | $page = $RCMAIL->imap->list_page; |
| | | if ($page === NULL) { |
| | | $page = $RCMAIL->storage->get_page(); |
| | | } |
| | | |
| | | $start_msg = ($page-1) * $RCMAIL->imap->page_size + 1; |
| | | $page_size = $RCMAIL->storage->get_pagesize(); |
| | | $start_msg = ($page-1) * $page_size + 1; |
| | | |
| | | if ($count!==NULL) |
| | | $max = $count; |
| | | else if ($RCMAIL->action) |
| | | $max = $RCMAIL->imap->messagecount(NULL, $RCMAIL->imap->threading ? 'THREADS' : 'ALL'); |
| | | $max = $RCMAIL->storage->count(NULL, $RCMAIL->storage->get_threading() ? 'THREADS' : 'ALL'); |
| | | |
| | | if ($max==0) |
| | | $out = rcube_label('mailboxempty'); |
| | | else |
| | | $out = rcube_label(array('name' => $RCMAIL->imap->threading ? 'threadsfromto' : 'messagesfromto', |
| | | $out = rcube_label(array('name' => $RCMAIL->storage->get_threading() ? 'threadsfromto' : 'messagesfromto', |
| | | 'vars' => array('from' => $start_msg, |
| | | 'to' => min($max, $start_msg + $RCMAIL->imap->page_size - 1), |
| | | 'to' => min($max, $start_msg + $page_size - 1), |
| | | 'count' => $max))); |
| | | |
| | | return Q($out); |
| | |
| | | function rcmail_get_mailbox_name_text() |
| | | { |
| | | global $RCMAIL; |
| | | return rcmail_localize_foldername($RCMAIL->imap->get_mailbox_name()); |
| | | return rcmail_localize_foldername($RCMAIL->storage->get_folder()); |
| | | } |
| | | |
| | | |
| | |
| | | $old_unseen = rcmail_get_unseen_count($mbox_name); |
| | | |
| | | if ($count === null) |
| | | $unseen = $RCMAIL->imap->messagecount($mbox_name, 'UNSEEN', $force); |
| | | $unseen = $RCMAIL->storage->count($mbox_name, 'UNSEEN', $force); |
| | | else |
| | | $unseen = $count; |
| | | |
| | |
| | | // fix (unknown/malformed) HTML tags before "wash" |
| | | $html = preg_replace_callback('/(<[\/]*)([^\s>]+)/', 'rcmail_html_tag_callback', $html); |
| | | |
| | | // charset was converted to UTF-8 in rcube_imap::get_message_part(), |
| | | // charset was converted to UTF-8 in rcube_storage::get_message_part(), |
| | | // change/add charset specification in HTML accordingly, |
| | | // washtml cannot work without that |
| | | $meta = '<meta http-equiv="Content-Type" content="text/html; charset='.RCMAIL_CHARSET.'" />'; |
| | |
| | | if (!rcmail_mem_check($part->size * 10)) { |
| | | $out .= html::span('part-notice', rcube_label('messagetoobig'). ' ' |
| | | . html::a('?_task=mail&_action=get&_download=1&_uid='.$MESSAGE->uid.'&_part='.$part->mime_id |
| | | .'&_mbox='. urlencode($RCMAIL->imap->get_mailbox_name()), rcube_label('download'))); |
| | | .'&_mbox='. urlencode($RCMAIL->storage->get_folder()), rcube_label('download'))); |
| | | continue; |
| | | } |
| | | |
| | |
| | | if (!rcmail_mem_check(strlen($MESSAGE->body) * 10)) { |
| | | $out .= html::span('part-notice', rcube_label('messagetoobig'). ' ' |
| | | . html::a('?_task=mail&_action=get&_download=1&_uid='.$MESSAGE->uid.'&_part=0' |
| | | .'&_mbox='. urlencode($RCMAIL->imap->get_mailbox_name()), rcube_label('download'))); |
| | | .'&_mbox='. urlencode($RCMAIL->storage->get_folder()), rcube_label('download'))); |
| | | } |
| | | else { |
| | | $plugin = $RCMAIL->plugins->exec_hook('message_body_prefix', array( |
| | |
| | | $message = new rcube_message($message); |
| | | |
| | | if ($message->headers->mdn_to && empty($message->headers->flags['MDNSENT']) && |
| | | ($RCMAIL->imap->check_permflag('MDNSENT') || $RCMAIL->imap->check_permflag('*'))) |
| | | ($RCMAIL->storage->check_permflag('MDNSENT') || $RCMAIL->storage->check_permflag('*'))) |
| | | { |
| | | $identity = $RCMAIL->user->get_identity(); |
| | | $sender = format_email_recipient($identity['email'], $identity['name']); |
| | |
| | | |
| | | if ($sent) |
| | | { |
| | | $RCMAIL->imap->set_flag($message->uid, 'MDNSENT'); |
| | | $RCMAIL->storage->set_flag($message->uid, 'MDNSENT'); |
| | | return true; |
| | | } |
| | | } |
| | |
| | | |
| | | // Set env variables for messageerror.html template |
| | | if ($RCMAIL->action == 'show') { |
| | | $mbox_name = $RCMAIL->imap->get_mailbox_name(); |
| | | $mbox_name = $RCMAIL->storage->get_folder(); |
| | | $RCMAIL->output->set_env('mailbox', $mbox_name); |
| | | $RCMAIL->output->set_env('uid', null); |
| | | } |
| | |
| | | ob_end_clean(); |
| | | |
| | | // Now we need IMAP connection |
| | | if (!$RCMAIL->imap_connect()) { |
| | | if (!$RCMAIL->storage_connect()) { |
| | | // Get action is often executed simultanously. |
| | | // Some servers have MAXPERIP or other limits. |
| | | // To workaround this we'll wait for some time |
| | |
| | | if (!rcmail_mem_check($part->size * 10)) { |
| | | $out = '<body>' . rcube_label('messagetoobig'). ' ' |
| | | . html::a('?_task=mail&_action=get&_download=1&_uid='.$MESSAGE->uid.'&_part='.$part->mime_id |
| | | .'&_mbox='. urlencode($RCMAIL->imap->get_mailbox_name()), rcube_label('download')) . '</body></html>'; |
| | | .'&_mbox='. urlencode($RCMAIL->storage->get_folder()), rcube_label('download')) . '</body></html>'; |
| | | } |
| | | else { |
| | | // get part body if not available |
| | |
| | | $stdout = fopen('php://output', 'w'); |
| | | stream_filter_register('rcube_content', 'rcube_content_filter') or die('Failed to register content filter'); |
| | | stream_filter_append($stdout, 'rcube_content'); |
| | | $RCMAIL->imap->get_message_part($MESSAGE->uid, $part->mime_id, $part, false, $stdout); |
| | | $RCMAIL->storage->get_message_part($MESSAGE->uid, $part->mime_id, $part, false, $stdout); |
| | | } |
| | | } |
| | | else { |
| | |
| | | if ($part->body) |
| | | echo $part->body; |
| | | else if ($part->size) |
| | | $RCMAIL->imap->get_message_part($MESSAGE->uid, $part->mime_id, $part, true); |
| | | $RCMAIL->storage->get_message_part($MESSAGE->uid, $part->mime_id, $part, true); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | */ |
| | | |
| | | $a_folders = $RCMAIL->imap->list_mailboxes('', '*', 'mail'); |
| | | $a_folders = $RCMAIL->storage->list_folders_subscribed('', '*', 'mail'); |
| | | |
| | | if (!empty($a_folders)) |
| | | { |
| | | $current = $RCMAIL->imap->get_mailbox_name(); |
| | | $current = $RCMAIL->storage->get_folder(); |
| | | $inbox = ($current == 'INBOX'); |
| | | $check_all = (bool)$RCMAIL->config->get('check_all_folders'); |
| | | |
| | |
| | | if (!$check_all && $unseen_old !== null && $mbox_row != $current) |
| | | $unseen = $unseen_old; |
| | | else |
| | | $unseen = $RCMAIL->imap->messagecount($mbox_row, 'UNSEEN', $unseen_old === null); |
| | | $unseen = $RCMAIL->storage->count($mbox_row, 'UNSEEN', $unseen_old === null); |
| | | |
| | | if ($unseen || $unseen_old === null) { |
| | | $OUTPUT->command('set_unread_count', $mbox_row, $unseen, $inbox && $mbox_row == 'INBOX'); |
| | |
| | | |
| | | if ($uid = get_input_value('_uid', RCUBE_INPUT_POST)) |
| | | { |
| | | $source = $RCMAIL->imap->get_raw_headers($uid); |
| | | $source = $RCMAIL->storage->get_raw_headers($uid); |
| | | |
| | | if ($source !== false) { |
| | | $source = htmlspecialchars(trim($source)); |
| | |
| | | if ($save_arr) |
| | | $RCMAIL->user->save_prefs($save_arr); |
| | | |
| | | $mbox_name = $RCMAIL->imap->get_mailbox_name(); |
| | | $mbox_name = $RCMAIL->storage->get_folder(); |
| | | $threading = (bool) $RCMAIL->storage->get_threading(); |
| | | |
| | | // Synchronize mailbox cache, handle flag changes |
| | | $RCMAIL->imap->mailbox_sync($mbox_name); |
| | | $RCMAIL->storage->folder_sync($mbox_name); |
| | | |
| | | // initialize searching result if search_filter is used |
| | | if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL') |
| | | { |
| | | $search_request = md5($mbox_name.$_SESSION['search_filter']); |
| | | $RCMAIL->imap->search($mbox_name, $_SESSION['search_filter'], RCMAIL_CHARSET, $sort_col); |
| | | $_SESSION['search'] = $RCMAIL->imap->get_search_set(); |
| | | $RCMAIL->storage->search($mbox_name, $_SESSION['search_filter'], RCMAIL_CHARSET, $sort_col); |
| | | $_SESSION['search'] = $RCMAIL->storage->get_search_set(); |
| | | $_SESSION['search_request'] = $search_request; |
| | | $OUTPUT->set_env('search_request', $search_request); |
| | | } |
| | | |
| | | // fetch message headers |
| | | if ($count = $RCMAIL->imap->messagecount($mbox_name, $RCMAIL->imap->threading ? 'THREADS' : 'ALL', !empty($_REQUEST['_refresh']))) |
| | | $a_headers = $RCMAIL->imap->list_headers($mbox_name, NULL, $sort_col, $sort_order); |
| | | if ($count = $RCMAIL->storage->count($mbox_name, $threading ? 'THREADS' : 'ALL', !empty($_REQUEST['_refresh']))) |
| | | $a_headers = $RCMAIL->storage->list_messages($mbox_name, NULL, $sort_col, $sort_order); |
| | | |
| | | // update search set (possible change of threading mode) |
| | | if (!empty($_REQUEST['_search']) && isset($_SESSION['search']) |
| | | && $_SESSION['search_request'] == $_REQUEST['_search'] |
| | | ) { |
| | | $_SESSION['search'] = $RCMAIL->imap->get_search_set(); |
| | | $_SESSION['search'] = $RCMAIL->storage->get_search_set(); |
| | | } |
| | | // remove old search data |
| | | else if (empty($_REQUEST['_search']) && isset($_SESSION['search'])) { |
| | |
| | | rcmail_send_unread_count($mbox_name, !empty($_REQUEST['_refresh']), $unseen); |
| | | |
| | | // update message count display |
| | | $pages = ceil($count/$RCMAIL->imap->page_size); |
| | | $pages = ceil($count/$RCMAIL->storage->get_pagesize()); |
| | | $OUTPUT->set_env('messagecount', $count); |
| | | $OUTPUT->set_env('pagecount', $pages); |
| | | $OUTPUT->set_env('threading', (bool) $RCMAIL->imap->threading); |
| | | $OUTPUT->set_env('current_page', $count ? $RCMAIL->imap->list_page : 1); |
| | | $OUTPUT->set_env('threading', $threading); |
| | | $OUTPUT->set_env('current_page', $count ? $RCMAIL->storage->get_page() : 1); |
| | | $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count), $mbox_name); |
| | | $OUTPUT->command('set_mailboxname', rcmail_get_mailbox_name_text()); |
| | | |
| | |
| | | } |
| | | else { |
| | | // handle IMAP errors (e.g. #1486905) |
| | | if ($err_code = $RCMAIL->imap->get_error_code()) { |
| | | if ($err_code = $RCMAIL->storage->get_error_code()) { |
| | | rcmail_display_server_error(); |
| | | } |
| | | else if ($search_request) |
| | |
| | | 'flagged' => 'FLAGGED', |
| | | 'unflagged' => 'UNFLAGGED'); |
| | | |
| | | $threading = (bool) $RCMAIL->storage->get_threading(); |
| | | |
| | | if (($uids = get_input_value('_uid', RCUBE_INPUT_POST)) && ($flag = get_input_value('_flag', RCUBE_INPUT_POST))) |
| | | { |
| | | $flag = $a_flags_map[$flag] ? $a_flags_map[$flag] : strtoupper($flag); |
| | | |
| | | if ($flag == 'DELETED' && $CONFIG['skip_deleted'] && $_POST['_from'] != 'show') { |
| | | // count messages before changing anything |
| | | $old_count = $RCMAIL->imap->messagecount(NULL, $RCMAIL->imap->threading ? 'THREADS' : 'ALL'); |
| | | $old_pages = ceil($old_count / $RCMAIL->imap->page_size); |
| | | $old_count = $RCMAIL->storage->count(NULL, $threading ? 'THREADS' : 'ALL'); |
| | | $old_pages = ceil($old_count / $RCMAIL->storage->get_pagesize()); |
| | | $count = sizeof(explode(',', $uids)); |
| | | } |
| | | |
| | | $marked = $RCMAIL->imap->set_flag($uids, $flag); |
| | | $marked = $RCMAIL->storage->set_flag($uids, $flag); |
| | | |
| | | if (!$marked) { |
| | | // send error message |
| | |
| | | |
| | | if ($flag == 'DELETED' && $CONFIG['read_when_deleted'] && !empty($_POST['_ruid'])) { |
| | | $ruids = get_input_value('_ruid', RCUBE_INPUT_POST); |
| | | $read = $RCMAIL->imap->set_flag($ruids, 'SEEN'); |
| | | $read = $RCMAIL->storage->set_flag($ruids, 'SEEN'); |
| | | |
| | | if ($read && !$CONFIG['skip_deleted']) |
| | | $OUTPUT->command('flag_deleted_as_read', $ruids); |
| | | } |
| | | |
| | | if ($flag == 'SEEN' || $flag == 'UNSEEN' || ($flag == 'DELETED' && !$CONFIG['skip_deleted'])) { |
| | | rcmail_send_unread_count($RCMAIL->imap->get_mailbox_name()); |
| | | rcmail_send_unread_count($RCMAIL->storage->get_folder()); |
| | | } |
| | | else if ($flag == 'DELETED' && $CONFIG['skip_deleted']) { |
| | | if ($_POST['_from'] == 'show') { |
| | |
| | | else |
| | | $OUTPUT->command('command', 'list'); |
| | | } else { |
| | | $search_request = get_input_value('_search', RCUBE_INPUT_GPC); |
| | | // refresh saved search set after moving some messages |
| | | if (($search_request = get_input_value('_search', RCUBE_INPUT_GPC)) && $RCMAIL->imap->search_set) { |
| | | $_SESSION['search'] = $RCMAIL->imap->refresh_search(); |
| | | if ($search_request && $RCMAIL->storage->get_search_set()) { |
| | | $_SESSION['search'] = $RCMAIL->storage->refresh_search(); |
| | | } |
| | | |
| | | $msg_count = $RCMAIL->imap->messagecount(NULL, $RCMAIL->imap->threading ? 'THREADS' : 'ALL'); |
| | | $pages = ceil($msg_count / $RCMAIL->imap->page_size); |
| | | $nextpage_count = $old_count - $RCMAIL->imap->page_size * $RCMAIL->imap->list_page; |
| | | $remaining = $msg_count - $RCMAIL->imap->page_size * ($RCMAIL->imap->list_page - 1); |
| | | $msg_count = $RCMAIL->storage->count(NULL, $threading ? 'THREADS' : 'ALL'); |
| | | $page_size = $RCMAIL->storage->get_pagesize(); |
| | | $page = $RCMAIL->storage->get_page(); |
| | | $pages = ceil($msg_count / $page_size); |
| | | $nextpage_count = $old_count - $page_size * $page; |
| | | $remaining = $msg_count - $page_size * ($page - 1); |
| | | |
| | | // jump back one page (user removed the whole last page) |
| | | if ($RCMAIL->imap->list_page > 1 && $remaining == 0) { |
| | | $RCMAIL->imap->set_page($RCMAIL->imap->list_page-1); |
| | | $_SESSION['page'] = $RCMAIL->imap->list_page; |
| | | if ($page > 1 && $remaining == 0) { |
| | | $page -= 1; |
| | | $RCMAIL->storage->set_page($page); |
| | | $_SESSION['page'] = $page; |
| | | $jump_back = true; |
| | | } |
| | | |
| | | // update message count display |
| | | $OUTPUT->set_env('messagecount', $msg_count); |
| | | $OUTPUT->set_env('current_page', $RCMAIL->imap->list_page); |
| | | $OUTPUT->set_env('current_page', $page); |
| | | $OUTPUT->set_env('pagecount', $pages); |
| | | |
| | | // update mailboxlist |
| | | $mbox = $RCMAIL->imap->get_mailbox_name(); |
| | | $unseen_count = $msg_count ? $RCMAIL->imap->messagecount($mbox, 'UNSEEN') : 0; |
| | | $mbox = $RCMAIL->storage->get_folder(); |
| | | $unseen_count = $msg_count ? $RCMAIL->storage->count($mbox, 'UNSEEN') : 0; |
| | | $old_unseen = rcmail_get_unseen_count($mbox); |
| | | |
| | | if ($old_unseen != $unseen_count) { |
| | |
| | | } |
| | | $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count), $mbox); |
| | | |
| | | if ($RCMAIL->imap->threading) |
| | | if ($threading) { |
| | | $count = get_input_value('_count', RCUBE_INPUT_POST); |
| | | } |
| | | |
| | | // add new rows from next page (if any) |
| | | if ($count && $uids != '*' && ($jump_back || $nextpage_count > 0)) { |
| | | $sort_col = isset($_SESSION['sort_col']) ? $_SESSION['sort_col'] : $CONFIG['message_sort_col']; |
| | | $sort_order = isset($_SESSION['sort_order']) ? $_SESSION['sort_order'] : $CONFIG['message_sort_order']; |
| | | |
| | | $a_headers = $RCMAIL->imap->list_headers($mbox, NULL, $sort_col, $sort_order, |
| | | $a_headers = $RCMAIL->storage->list_messages($mbox, NULL, $sort_col, $sort_order, |
| | | $jump_back ? NULL : $count); |
| | | |
| | | rcmail_js_message_list($a_headers, false); |
| | |
| | | return; |
| | | |
| | | // count messages before changing anything |
| | | $old_count = $RCMAIL->imap->messagecount(NULL, $RCMAIL->imap->threading ? 'THREADS' : 'ALL'); |
| | | $old_pages = ceil($old_count / $RCMAIL->imap->page_size); |
| | | $threading = (bool) $RCMAIL->storage->get_threading(); |
| | | $old_count = $RCMAIL->storage->count(NULL, $threading ? 'THREADS' : 'ALL'); |
| | | $old_pages = ceil($old_count / $RCMAIL->storage->get_pagesize()); |
| | | |
| | | // move messages |
| | | if ($RCMAIL->action=='moveto' && !empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) { |
| | |
| | | $target = get_input_value('_target_mbox', RCUBE_INPUT_POST, true); |
| | | $mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true); |
| | | |
| | | $moved = $RCMAIL->imap->move_message($uids, $target, $mbox); |
| | | $moved = $RCMAIL->storage->move_message($uids, $target, $mbox); |
| | | |
| | | if (!$moved) { |
| | | // send error message |
| | |
| | | $count = sizeof(explode(',', ($uids = get_input_value('_uid', RCUBE_INPUT_POST)))); |
| | | $mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true); |
| | | |
| | | $del = $RCMAIL->imap->delete_message($uids, $mbox); |
| | | $del = $RCMAIL->storage->delete_message($uids, $mbox); |
| | | |
| | | if (!$del) { |
| | | // send error message |
| | |
| | | exit; |
| | | } |
| | | |
| | | $search_request = get_input_value('_search', RCUBE_INPUT_GPC); |
| | | |
| | | // refresh saved search set after moving some messages |
| | | if (($search_request = get_input_value('_search', RCUBE_INPUT_GPC)) && $RCMAIL->imap->search_set) { |
| | | $_SESSION['search'] = $RCMAIL->imap->refresh_search(); |
| | | if ($search_request && $RCMAIL->storage->get_search_set()) { |
| | | $_SESSION['search'] = $RCMAIL->storage->refresh_search(); |
| | | } |
| | | |
| | | if ($_POST['_from'] == 'show') |
| | |
| | | } |
| | | else |
| | | { |
| | | $msg_count = $RCMAIL->imap->messagecount(NULL, $RCMAIL->imap->threading ? 'THREADS' : 'ALL'); |
| | | $pages = ceil($msg_count / $RCMAIL->imap->page_size); |
| | | $nextpage_count = $old_count - $RCMAIL->imap->page_size * $RCMAIL->imap->list_page; |
| | | $remaining = $msg_count - $RCMAIL->imap->page_size * ($RCMAIL->imap->list_page - 1); |
| | | $msg_count = $RCMAIL->storage->count(NULL, $threading ? 'THREADS' : 'ALL'); |
| | | $page_size = $RCMAIL->storage->get_pagesize(); |
| | | $page = $RCMAIL->storage->get_page(); |
| | | $pages = ceil($msg_count / $page_size); |
| | | $nextpage_count = $old_count - $page_size * $page; |
| | | $remaining = $msg_count - $page_size * ($page - 1); |
| | | |
| | | // jump back one page (user removed the whole last page) |
| | | if ($RCMAIL->imap->list_page > 1 && $remaining == 0) { |
| | | $RCMAIL->imap->set_page($RCMAIL->imap->list_page-1); |
| | | $_SESSION['page'] = $RCMAIL->imap->list_page; |
| | | if ($page > 1 && $remaining == 0) { |
| | | $page -= 1; |
| | | $RCMAIL->storage->set_page($page); |
| | | $_SESSION['page'] = $page; |
| | | $jump_back = true; |
| | | } |
| | | |
| | | // update message count display |
| | | $OUTPUT->set_env('messagecount', $msg_count); |
| | | $OUTPUT->set_env('current_page', $RCMAIL->imap->list_page); |
| | | $OUTPUT->set_env('current_page', $page); |
| | | $OUTPUT->set_env('pagecount', $pages); |
| | | |
| | | // update mailboxlist |
| | | $mbox = $RCMAIL->imap->get_mailbox_name(); |
| | | $unseen_count = $msg_count ? $RCMAIL->imap->messagecount($mbox, 'UNSEEN') : 0; |
| | | $mbox = $RCMAIL->storage->get_folder(); |
| | | $unseen_count = $msg_count ? $RCMAIL->storage->count($mbox, 'UNSEEN') : 0; |
| | | $old_unseen = rcmail_get_unseen_count($mbox); |
| | | |
| | | if ($old_unseen != $unseen_count) { |
| | |
| | | $OUTPUT->command('set_quota', rcmail_quota_content()); |
| | | $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count), $mbox); |
| | | |
| | | if ($RCMAIL->imap->threading) |
| | | if ($threading) { |
| | | $count = get_input_value('_count', RCUBE_INPUT_POST); |
| | | } |
| | | |
| | | // add new rows from next page (if any) |
| | | if ($addrows && $count && $uids != '*' && ($jump_back || $nextpage_count > 0)) { |
| | | $sort_col = isset($_SESSION['sort_col']) ? $_SESSION['sort_col'] : $CONFIG['message_sort_col']; |
| | | $sort_order = isset($_SESSION['sort_order']) ? $_SESSION['sort_order'] : $CONFIG['message_sort_order']; |
| | | |
| | | $a_headers = $RCMAIL->imap->list_headers($mbox, NULL, $sort_col, $sort_order, |
| | | $a_headers = $RCMAIL->storage->list_messages($mbox, NULL, $sort_col, $sort_order, |
| | | $jump_back ? NULL : $count); |
| | | |
| | | rcmail_js_message_list($a_headers, false); |
| | |
| | | */ |
| | | |
| | | $uid = get_input_value('_uid', RCUBE_INPUT_GET); |
| | | $index = $RCMAIL->imap->message_index(null, $_SESSION['sort_col'], $_SESSION['sort_order']); |
| | | $cnt = $index->countMessages(); |
| | | $index = $RCMAIL->storage->index(null, $_SESSION['sort_col'], $_SESSION['sort_order']); |
| | | $cnt = $index->count_messages(); |
| | | |
| | | if ($cnt && ($pos = $index->exists($uid, true)) !== false) { |
| | | $prev = $pos ? $index->getElement($pos-1) : 0; |
| | | $first = $pos ? $index->getElement('FIRST') : 0; |
| | | $next = $pos < $cnt-1 ? $index->getElement($pos+1) : 0; |
| | | $last = $pos < $cnt-1 ? $index->getElement('LAST') : 0; |
| | | $prev = $pos ? $index->get_element($pos-1) : 0; |
| | | $first = $pos ? $index->get_element('FIRST') : 0; |
| | | $next = $pos < $cnt-1 ? $index->get_element($pos+1) : 0; |
| | | $last = $pos < $cnt-1 ? $index->get_element('LAST') : 0; |
| | | } |
| | | |
| | | // Set UIDs and activate navigation buttons |
| | |
| | | $REMOTE_REQUEST = TRUE; |
| | | |
| | | // reset list_page and old search results |
| | | $RCMAIL->imap->set_page(1); |
| | | $RCMAIL->imap->set_search_set(NULL); |
| | | $RCMAIL->storage->set_page(1); |
| | | $RCMAIL->storage->set_search_set(NULL); |
| | | $_SESSION['page'] = 1; |
| | | |
| | | // using encodeURI with javascript "should" give us |
| | |
| | | |
| | | // execute IMAP search |
| | | if ($search_str) |
| | | $RCMAIL->imap->search($mbox, $search_str, $imap_charset, $_SESSION['sort_col']); |
| | | $RCMAIL->storage->search($mbox, $search_str, $imap_charset, $_SESSION['sort_col']); |
| | | |
| | | // save search results in session |
| | | if (!is_array($_SESSION['search'])) |
| | | $_SESSION['search'] = array(); |
| | | |
| | | if ($search_str) { |
| | | $_SESSION['search'] = $RCMAIL->imap->get_search_set(); |
| | | $_SESSION['search'] = $RCMAIL->storage->get_search_set(); |
| | | $_SESSION['last_text_search'] = $str; |
| | | } |
| | | $_SESSION['search_request'] = $search_request; |
| | | |
| | | |
| | | // Get the headers |
| | | $result_h = $RCMAIL->imap->list_headers($mbox, 1, $_SESSION['sort_col'], $_SESSION['sort_order']); |
| | | $count = $RCMAIL->imap->messagecount($mbox, $RCMAIL->imap->threading ? 'THREADS' : 'ALL'); |
| | | $result_h = $RCMAIL->storage->list_messages($mbox, 1, $_SESSION['sort_col'], $_SESSION['sort_order']); |
| | | $count = $RCMAIL->storage->count($mbox, $RCMAIL->storage->get_threading() ? 'THREADS' : 'ALL'); |
| | | |
| | | |
| | | // Make sure we got the headers |
| | | if (!empty($result_h)) { |
| | | rcmail_js_message_list($result_h); |
| | | if ($search_str) |
| | | $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $RCMAIL->imap->messagecount(NULL, 'ALL'))); |
| | | $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $RCMAIL->storage->count(NULL, 'ALL'))); |
| | | } |
| | | // handle IMAP errors (e.g. #1486905) |
| | | else if ($err_code = $RCMAIL->imap->get_error_code()) { |
| | | else if ($err_code = $RCMAIL->storage->get_error_code()) { |
| | | rcmail_display_server_error(); |
| | | } |
| | | else { |
| | |
| | | // update message count display |
| | | $OUTPUT->set_env('search_request', $search_str ? $search_request : ''); |
| | | $OUTPUT->set_env('messagecount', $count); |
| | | $OUTPUT->set_env('pagecount', ceil($count/$RCMAIL->imap->page_size)); |
| | | $OUTPUT->set_env('pagecount', ceil($count/$RCMAIL->storage->get_pagesize())); |
| | | $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count, 1), $mbox); |
| | | $OUTPUT->send(); |
| | | |
| | | |
| | |
| | | |
| | | // set replied/forwarded flag |
| | | if ($COMPOSE['reply_uid']) |
| | | $RCMAIL->imap->set_flag($COMPOSE['reply_uid'], 'ANSWERED', $COMPOSE['mailbox']); |
| | | $RCMAIL->storage->set_flag($COMPOSE['reply_uid'], 'ANSWERED', $COMPOSE['mailbox']); |
| | | else if ($COMPOSE['forward_uid']) |
| | | $RCMAIL->imap->set_flag($COMPOSE['forward_uid'], 'FORWARDED', $COMPOSE['mailbox']); |
| | | $RCMAIL->storage->set_flag($COMPOSE['forward_uid'], 'FORWARDED', $COMPOSE['mailbox']); |
| | | |
| | | } // End of SMTP Delivery Block |
| | | |
| | |
| | | |
| | | if ($store_target) { |
| | | // check if folder is subscribed |
| | | if ($RCMAIL->imap->mailbox_exists($store_target, true)) |
| | | if ($RCMAIL->storage->folder_exists($store_target, true)) |
| | | $store_folder = true; |
| | | // folder may be existing but not subscribed (#1485241) |
| | | else if (!$RCMAIL->imap->mailbox_exists($store_target)) |
| | | $store_folder = $RCMAIL->imap->create_mailbox($store_target, true); |
| | | else if ($RCMAIL->imap->subscribe($store_target)) |
| | | else if (!$RCMAIL->storage->folder_exists($store_target)) |
| | | $store_folder = $RCMAIL->storage->create_folder($store_target, true); |
| | | else if ($RCMAIL->storage->subscribe($store_target)) |
| | | $store_folder = true; |
| | | |
| | | // append message to sent box |
| | |
| | | 'message' => "Could not create message: ".$msg->getMessage()), |
| | | TRUE, FALSE); |
| | | else { |
| | | $saved = $RCMAIL->imap->save_message($store_target, $msg, $headers, $mailbody_file ? true : false); |
| | | $saved = $RCMAIL->storage->save_message($store_target, $msg, $headers, $mailbody_file ? true : false); |
| | | } |
| | | |
| | | if ($mailbody_file) { |
| | |
| | | if ($olddraftmessageid) { |
| | | // delete previous saved draft |
| | | // @TODO: use message UID (remember to check UIDVALIDITY) to skip this SEARCH |
| | | $delete_idx = $RCMAIL->imap->search_once($CONFIG['drafts_mbox'], |
| | | $delete_idx = $RCMAIL->storage->search_once($CONFIG['drafts_mbox'], |
| | | 'HEADER Message-ID '.$olddraftmessageid); |
| | | |
| | | if ($del_uid = $delete_idx->getElement('FIRST')) { |
| | | $deleted = $RCMAIL->imap->delete_message($del_uid, $CONFIG['drafts_mbox']); |
| | | $deleted = $RCMAIL->storage->delete_message($del_uid, $CONFIG['drafts_mbox']); |
| | | |
| | | // raise error if deletion of old draft failed |
| | | if (!$deleted) |
| | |
| | | |
| | | // remember new draft-uid ($saved could be an UID or TRUE here) |
| | | if (is_bool($saved)) { |
| | | $draft_idx = $RCMAIL->imap->search_once($CONFIG['drafts_mbox'], 'HEADER Message-ID '.$msgid); |
| | | $draft_idx = $RCMAIL->storage->search_once($CONFIG['drafts_mbox'], 'HEADER Message-ID '.$msgid); |
| | | $saved = $draft_idx->getElement('FIRST'); |
| | | } |
| | | $COMPOSE['param']['draft_uid'] = $saved; |
| | |
| | | rcmail_message_error($uid); |
| | | } |
| | | |
| | | $mbox_name = $RCMAIL->imap->get_mailbox_name(); |
| | | $mbox_name = $RCMAIL->storage->get_folder(); |
| | | |
| | | // show images? |
| | | rcmail_check_safe($MESSAGE); |
| | | |
| | | // set message charset as default |
| | | if (!empty($MESSAGE->headers->charset)) |
| | | $RCMAIL->imap->set_charset($MESSAGE->headers->charset); |
| | | $RCMAIL->storage->set_charset($MESSAGE->headers->charset); |
| | | |
| | | $OUTPUT->set_pagetitle(abbreviate_string($MESSAGE->subject, 128, '...', true)); |
| | | |
| | |
| | | $OUTPUT->set_env('safemode', $MESSAGE->is_safe); |
| | | $OUTPUT->set_env('sender', $MESSAGE->sender['string']); |
| | | $OUTPUT->set_env('permaurl', rcmail_url('show', array('_uid' => $MESSAGE->uid, '_mbox' => $mbox_name))); |
| | | $OUTPUT->set_env('delimiter', $RCMAIL->imap->get_hierarchy_delimiter()); |
| | | $OUTPUT->set_env('delimiter', $RCMAIL->storage->get_hierarchy_delimiter()); |
| | | $OUTPUT->set_env('mailbox', $mbox_name); |
| | | |
| | | // mimetypes supported by the browser (default settings) |
| | |
| | | if ($MESSAGE->headers->mdn_to |
| | | && empty($MESSAGE->headers->flags['MDNSENT']) |
| | | && empty($MESSAGE->headers->flags['SEEN']) |
| | | && ($RCMAIL->imap->check_permflag('MDNSENT') || $RCMAIL->imap->check_permflag('*')) |
| | | && ($RCMAIL->storage->check_permflag('MDNSENT') || $RCMAIL->storage->check_permflag('*')) |
| | | && $mbox_name != $CONFIG['drafts_mbox'] |
| | | && $mbox_name != $CONFIG['sent_mbox'] |
| | | ) { |
| | |
| | | { |
| | | global $MESSAGE, $RCMAIL, $CONFIG; |
| | | |
| | | $mbox = $RCMAIL->imap->get_mailbox_name(); |
| | | $delim = $RCMAIL->imap->get_hierarchy_delimiter(); |
| | | $mbox = $RCMAIL->storage->get_folder(); |
| | | $delim = $RCMAIL->storage->get_hierarchy_delimiter(); |
| | | $dbox = $CONFIG['drafts_mbox']; |
| | | |
| | | // the message is not a draft |
| | |
| | | if ($MESSAGE && $MESSAGE->headers && empty($MESSAGE->headers->flags['SEEN']) && |
| | | ($RCMAIL->action == 'show' || ($RCMAIL->action == 'preview' && intval($CONFIG['preview_pane_mark_read']) == 0))) |
| | | { |
| | | if ($RCMAIL->imap->set_flag($MESSAGE->uid, 'SEEN')) { |
| | | if ($RCMAIL->storage->set_flag($MESSAGE->uid, 'SEEN')) { |
| | | if ($count = rcmail_get_unseen_count($mbox_name)) { |
| | | rcmail_set_unseen_count($mbox_name, $count - 1); |
| | | } |
| | |
| | | // similar code as in program/steps/mail/get.inc |
| | | if ($uid = get_input_value('_uid', RCUBE_INPUT_GET)) |
| | | { |
| | | $headers = $RCMAIL->imap->get_headers($uid); |
| | | $headers = $RCMAIL->storage->get_message_headers($uid); |
| | | $charset = $headers->charset ? $headers->charset : $CONFIG['default_charset']; |
| | | header("Content-Type: text/plain; charset={$charset}"); |
| | | |
| | |
| | | header("Content-Disposition: attachment; filename=\"$filename\""); |
| | | } |
| | | |
| | | $RCMAIL->imap->print_raw_body($uid); |
| | | $RCMAIL->storage->print_raw_body($uid); |
| | | } |
| | | else |
| | | { |
| | |
| | | |
| | | // WARNING: folder names in UI are encoded with RCMAIL_CHARSET |
| | | |
| | | // init IMAP connection |
| | | $RCMAIL->imap_connect(); |
| | | |
| | | function rcmail_folder_form($attrib) |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | $storage = $RCMAIL->get_storage(); |
| | | |
| | | // edited folder name (empty in create-folder mode) |
| | | $mbox = trim(get_input_value('_mbox', RCUBE_INPUT_GPC, true)); |
| | |
| | | $parent = trim(get_input_value('_path', RCUBE_INPUT_GPC, true)); |
| | | $parent_imap = rcube_charset_convert($parent, RCMAIL_CHARSET, 'UTF7-IMAP'); |
| | | |
| | | $threading_supported = $RCMAIL->imap->get_capability('THREAD'); |
| | | $delimiter = $RCMAIL->imap->get_hierarchy_delimiter(); |
| | | $threading_supported = $storage->get_capability('THREAD'); |
| | | $delimiter = $storage->get_hierarchy_delimiter(); |
| | | |
| | | // Get mailbox parameters |
| | | if (strlen($mbox)) { |
| | | $options = rcmail_folder_options($mbox_imap); |
| | | $namespace = $RCMAIL->imap->get_namespace(); |
| | | $namespace = $storage->get_namespace(); |
| | | |
| | | $path = explode($delimiter, $mbox_imap); |
| | | $folder = array_pop($path); |
| | |
| | | |
| | | // allow creating subfolders of INBOX folder |
| | | if ($path == 'INBOX') { |
| | | $path = $RCMAIL->imap->mod_mailbox($path, 'in'); |
| | | $path = $storage->mod_folder($path, 'in'); |
| | | } |
| | | } |
| | | |
| | | // remove personal namespace prefix |
| | | if (strlen($path)) { |
| | | $path_id = $path; |
| | | $path = $RCMAIL->imap->mod_mailbox($path.$delimiter); |
| | | $path = $storage->mod_folder($path.$delimiter); |
| | | if ($path[strlen($path)-1] == $delimiter) { |
| | | $path = substr($path, 0, -1); |
| | | } |
| | |
| | | ); |
| | | |
| | | if ((!$options['noselect'] && !$options['is_root']) || $mbox_imap == 'INBOX') { |
| | | $msgcount = $RCMAIL->imap->messagecount($mbox_imap, 'ALL', true, false); |
| | | $msgcount = $storage->count($mbox_imap, 'ALL', true, false); |
| | | |
| | | // Size |
| | | if ($msgcount) { |
| | |
| | | // WARNING: folder names in UI are encoded with RCMAIL_CHARSET |
| | | |
| | | // init IMAP connection |
| | | $RCMAIL->imap_connect(); |
| | | $STORAGE = $RCMAIL->get_storage(); |
| | | |
| | | // subscribe mailbox |
| | | if ($RCMAIL->action == 'subscribe') |
| | | { |
| | | $mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true, 'UTF7-IMAP'); |
| | | if (strlen($mbox)) { |
| | | $result = $RCMAIL->imap->subscribe(array($mbox)); |
| | | $result = $STORAGE->subscribe(array($mbox)); |
| | | |
| | | // Handle virtual (non-existing) folders |
| | | if (!$result && $RCMAIL->imap->get_error_code() == -1 && |
| | | $RCMAIL->imap->get_response_code() == rcube_imap::TRYCREATE |
| | | if (!$result && $STORAGE->get_error_code() == -1 && |
| | | $STORAGE->get_response_code() == rcube_storage::TRYCREATE |
| | | ) { |
| | | $result = $RCMAIL->imap->create_mailbox($mbox, true); |
| | | $result = $STORAGE->create_folder($mbox, true); |
| | | if ($result) { |
| | | // @TODO: remove 'virtual' class of folder's row |
| | | } |
| | |
| | | if ($result) { |
| | | // Handle subscription of protected folder (#1487656) |
| | | if ($CONFIG['protect_default_folders'] == true |
| | | && in_array($mbox, $CONFIG['default_imap_folders']) |
| | | && in_array($mbox, $CONFIG['default_folders']) |
| | | ) { |
| | | $OUTPUT->command('disable_subscription', $mbox); |
| | | } |
| | |
| | | { |
| | | $mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true, 'UTF7-IMAP'); |
| | | if (strlen($mbox)) { |
| | | $result = $RCMAIL->imap->unsubscribe(array($mbox)); |
| | | $result = $STORAGE->unsubscribe(array($mbox)); |
| | | if ($result) |
| | | $OUTPUT->show_message('folderunsubscribed', 'confirmation'); |
| | | else |
| | |
| | | $plugin = $RCMAIL->plugins->exec_hook('folder_delete', array('name' => $mbox)); |
| | | |
| | | if (!$plugin['abort']) { |
| | | $deleted = $RCMAIL->imap->delete_mailbox($plugin['name']); |
| | | $deleted = $STORAGE->delete_folder($plugin['name']); |
| | | } |
| | | else { |
| | | $deleted = $plugin['result']; |
| | |
| | | { |
| | | $mbox_utf8 = get_input_value('_mbox', RCUBE_INPUT_POST, true); |
| | | $mbox = rcube_charset_convert($mbox_utf8, RCMAIL_CHARSET, 'UTF7-IMAP'); |
| | | $delimiter = $RCMAIL->imap->get_hierarchy_delimiter(); |
| | | $delimiter = $STORAGE->get_hierarchy_delimiter(); |
| | | $trash_regexp = '/^' . preg_quote($CONFIG['trash_mbox'] . $delimiter, '/') . '/'; |
| | | |
| | | // we should only be purging trash (or their subfolders) |
| | | if (!strlen($CONFIG['trash_mbox']) || $mbox == $CONFIG['trash_mbox'] |
| | | || preg_match($trash_regexp, $mbox) |
| | | ) { |
| | | $success = $RCMAIL->imap->clear_mailbox($mbox); |
| | | $success = $STORAGE->delete_message('*', $mbox); |
| | | $delete = true; |
| | | } |
| | | // copy to Trash |
| | | else { |
| | | $success = $RCMAIL->imap->move_message('1:*', $CONFIG['trash_mbox'], $mbox); |
| | | $success = $STORAGE->move_message('1:*', $CONFIG['trash_mbox'], $mbox); |
| | | $delete = false; |
| | | } |
| | | |
| | |
| | | { |
| | | $name = trim(get_input_value('_mbox', RCUBE_INPUT_POST, true)); |
| | | |
| | | $size = $RCMAIL->imap->get_mailbox_size($name); |
| | | $size = $STORAGE->folder_size($name); |
| | | |
| | | // @TODO: check quota and show percentage usage of specified mailbox? |
| | | |
| | |
| | | $table->add_header('subscribed', ''); |
| | | } |
| | | |
| | | // get folders from server |
| | | $RCMAIL->imap->clear_cache('mailboxes', true); |
| | | $STORAGE = $RCMAIL->get_storage(); |
| | | |
| | | $a_unsubscribed = $RCMAIL->imap->list_unsubscribed(); |
| | | $a_subscribed = $RCMAIL->imap->list_mailboxes('', '*', null, null, true); // unsorted |
| | | $delimiter = $RCMAIL->imap->get_hierarchy_delimiter(); |
| | | $namespace = $RCMAIL->imap->get_namespace(); |
| | | // get folders from server |
| | | $STORAGE->clear_cache('mailboxes', true); |
| | | |
| | | $a_unsubscribed = $STORAGE->list_folders(); |
| | | $a_subscribed = $STORAGE->list_folders_subscribed('', '*', null, null, true); // unsorted |
| | | $delimiter = $STORAGE->get_hierarchy_delimiter(); |
| | | $namespace = $STORAGE->get_namespace(); |
| | | $a_js_folders = array(); |
| | | $seen = array(); |
| | | $list_folders = array(); |
| | |
| | | // pre-process folders list |
| | | foreach ($a_unsubscribed as $i => $folder) { |
| | | $folder_id = $folder; |
| | | $folder = $RCMAIL->imap->mod_mailbox($folder); |
| | | $folder = $STORAGE->mod_folder($folder); |
| | | $foldersplit = explode($delimiter, $folder); |
| | | $name = rcube_charset_convert(array_pop($foldersplit), 'UTF7-IMAP'); |
| | | $parent_folder = join($delimiter, $foldersplit); |
| | |
| | | $idx = $i + 1; |
| | | $sub_key = array_search($folder['id'], $a_subscribed); |
| | | $subscribed = $sub_key !== false; |
| | | $protected = ($CONFIG['protect_default_folders'] == true && in_array($folder['id'], $CONFIG['default_imap_folders'])); |
| | | $protected = ($CONFIG['protect_default_folders'] == true && in_array($folder['id'], $CONFIG['default_folders'])); |
| | | $noselect = false; |
| | | $classes = array($i%2 ? 'even' : 'odd'); |
| | | |
| | |
| | | } |
| | | |
| | | if (!$protected) { |
| | | $attrs = $RCMAIL->imap->mailbox_attributes($folder['id']); |
| | | $attrs = $STORAGE->folder_attributes($folder['id']); |
| | | $noselect = in_array('\\Noselect', $attrs); |
| | | } |
| | | |
| | |
| | | |
| | | $OUTPUT->add_gui_object('subscriptionlist', $attrib['id']); |
| | | $OUTPUT->set_env('subscriptionrows', $a_js_folders); |
| | | $OUTPUT->set_env('defaultfolders', $CONFIG['default_imap_folders']); |
| | | $OUTPUT->set_env('defaultfolders', $CONFIG['default_folders']); |
| | | $OUTPUT->set_env('delimiter', $delimiter); |
| | | |
| | | return $form_start . $table->show($attrib) . $form_end; |
| | |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | $delimiter = $RCMAIL->imap->get_hierarchy_delimiter(); |
| | | $storage = $RCMAIL->get_storage(); |
| | | $delimiter = $storage->get_hierarchy_delimiter(); |
| | | |
| | | $plugin = $RCMAIL->plugins->exec_hook('folder_rename', array( |
| | | 'oldname' => $oldname, 'newname' => $newname)); |
| | | |
| | | if (!$plugin['abort']) { |
| | | $renamed = $RCMAIL->imap->rename_mailbox($oldname, $newname); |
| | | $renamed = $storage->rename_folder($oldname, $newname); |
| | | } |
| | | else { |
| | | $renamed = $plugin['result']; |
| | |
| | | |
| | | $OUTPUT->set_pagetitle(rcube_label('folders')); |
| | | $OUTPUT->include_script('list.js'); |
| | | $OUTPUT->set_env('quota', $RCMAIL->imap->get_capability('QUOTA')); |
| | | $OUTPUT->set_env('quota', $STORAGE->get_capability('QUOTA')); |
| | | |
| | | // add some labels to client |
| | | $OUTPUT->add_label('deletefolderconfirm', 'purgefolderconfirm', 'folderdeleting', |
| | |
| | | ); |
| | | } |
| | | |
| | | $RCMAIL->imap_connect(); |
| | | $threading_supported = $RCMAIL->imap->get_capability('THREAD'); |
| | | $storage = $RCMAIL->get_storage(); |
| | | $threading_supported = $storage->get_capability('THREAD'); |
| | | |
| | | if (!isset($no_override['autoexpand_threads']) && $threading_supported) { |
| | | $field_id = 'rcmfd_autoexpand_threads'; |
| | |
| | | ); |
| | | |
| | | // Configure special folders |
| | | if (!isset($no_override['default_imap_folders'])) { |
| | | |
| | | $RCMAIL->imap_connect(); |
| | | |
| | | if (!isset($no_override['default_folders'])) { |
| | | // load folders list only when needed |
| | | if ($current) { |
| | | $select = rcmail_mailbox_select(array( |
| | |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | $options = $RCMAIL->imap->mailbox_info($mailbox); |
| | | $options = $RCMAIL->get_storage()->folder_info($mailbox); |
| | | $options['protected'] = $options['is_root'] || ($options['special'] && $RCMAIL->config->get('protect_default_folders')); |
| | | |
| | | return $options; |
| | |
| | | { |
| | | global $RCMAIL, $CONFIG, $OUTPUT; |
| | | |
| | | $delimiter = $RCMAIL->imap->get_hierarchy_delimiter(); |
| | | $storage = $RCMAIL->get_storage(); |
| | | $delimiter = $storage->get_hierarchy_delimiter(); |
| | | $name_utf8 = rcube_charset_convert($name, 'UTF7-IMAP'); |
| | | $protected = ($CONFIG['protect_default_folders'] == true && in_array($name, $CONFIG['default_imap_folders'])); |
| | | $protected = ($CONFIG['protect_default_folders'] == true && in_array($name, $CONFIG['default_folders'])); |
| | | |
| | | $foldersplit = explode($delimiter, $RCMAIL->imap->mod_mailbox($name)); |
| | | $foldersplit = explode($delimiter, $storage->mod_folder($name)); |
| | | $level = count($foldersplit) - 1; |
| | | $display_name = str_repeat(' ', $level) |
| | | . Q($protected ? rcmail_localize_foldername($name) : rcube_charset_convert($foldersplit[$level], 'UTF7-IMAP')); |
| | |
| | | // WARNING: folder names in UI are encoded with RCMAIL_CHARSET |
| | | |
| | | // init IMAP connection |
| | | $RCMAIL->imap_connect(); |
| | | $STORAGE = $RCMAIL->get_storage(); |
| | | |
| | | |
| | | $name = trim(get_input_value('_name', RCUBE_INPUT_POST, true)); |
| | |
| | | $old_imap = rcube_charset_convert($old, RCMAIL_CHARSET, 'UTF7-IMAP'); |
| | | // $path is in UTF7-IMAP already |
| | | |
| | | $delimiter = $RCMAIL->imap->get_hierarchy_delimiter(); |
| | | $delimiter = $STORAGE->get_hierarchy_delimiter(); |
| | | $options = strlen($old_imap) ? rcmail_folder_options($old_imap) : array(); |
| | | |
| | | // Folder name checks |
| | |
| | | $name_imap = $path . $delimiter . $name_imap; |
| | | } |
| | | else { |
| | | $name_imap = $RCMAIL->imap->mod_mailbox($name_imap, 'in'); |
| | | $name_imap = $STORAGE->mod_folder($name_imap, 'in'); |
| | | } |
| | | } |
| | | |
| | | // Check access rights to the parent folder |
| | | if (!$error && strlen($path) && (!strlen($old_imap) || $old_imap != $name_imap)) { |
| | | $parent_opts = $RCMAIL->imap->mailbox_info($path); |
| | | $parent_opts = $STORAGE->folder_info($path); |
| | | if ($parent_opts['namespace'] != 'personal' |
| | | && (empty($parent_opts['rights']) || !preg_match('/[ck]/', implode($parent_opts))) |
| | | ) { |
| | |
| | | $folder = $plugin['record']; |
| | | |
| | | if (!$plugin['abort']) { |
| | | $created = $RCMAIL->imap->create_mailbox($folder['name'], $folder['subscribe']); |
| | | $created = $STORAGE->create_folder($folder['name'], $folder['subscribe']); |
| | | } |
| | | else { |
| | | $created = $plugin['result']; |
| | |
| | | |
| | | if (!$plugin['abort']) { |
| | | if ($rename) { |
| | | $updated = $RCMAIL->imap->rename_mailbox($folder['oldname'], $folder['name']); |
| | | $updated = $STORAGE->rename_folder($folder['oldname'], $folder['name']); |
| | | } |
| | | else { |
| | | $updated = true; |
| | |
| | | break; |
| | | case 'folders': |
| | | |
| | | // special handling for 'default_imap_folders' |
| | | if (in_array('default_imap_folders', (array)$CONFIG['dont_override'])) { |
| | | // special handling for 'default_folders' |
| | | if (in_array('default_folders', (array)$CONFIG['dont_override'])) { |
| | | foreach (array('drafts_mbox','sent_mbox','junk_mbox','trash_mbox') as $p) |
| | | $a_user_prefs[$p] = $CONFIG[$p]; |
| | | } else { |
| | | $a_user_prefs['default_imap_folders'] = array('INBOX'); |
| | | $a_user_prefs['default_folders'] = array('INBOX'); |
| | | foreach (array('drafts_mbox','sent_mbox','junk_mbox','trash_mbox') as $p) { |
| | | if ($a_user_prefs[$p]) |
| | | $a_user_prefs['default_imap_folders'][] = $a_user_prefs[$p]; |
| | | $a_user_prefs['default_folders'][] = $a_user_prefs[$p]; |
| | | } |
| | | } |
| | | |
| | |
| | | $GLOBALS['RCMAIL'] = $RCMAIL = rcmail::get_instance(); |
| | | $GLOBALS['OUTPUT'] = $OUTPUT = $RCMAIL->load_gui(); |
| | | $RCMAIL->action = 'autocomplete'; |
| | | $RCMAIL->imap_init(false); |
| | | $IMAP = $RCMAIL->imap; |
| | | $RCMAIL->storage_init(false); |
| | | |
| | | require_once INSTALL_PATH . 'program/steps/mail/func.inc'; |
| | | |