Changeset c321a955 in github


Ignore:
Timestamp:
Jan 16, 2012 10:14:41 AM (16 months ago)
Author:
thomascube <thomas@…>
Branches:
master, HEAD, courier-fix, dev-browser-capabilities, pdo, release-0.8
Children:
a2c4956
Parents:
8764b6e
Message:

Merged devel-framework branch (r5746:5779) back into trunk

Files:
2 added
1 deleted
37 edited

Legend:

Unmodified
Added
Removed
  • bin/msgexport.sh

    r1c4f23d rc321a955  
    3232        global $IMAP; 
    3333 
    34         $IMAP->set_mailbox($mbox); 
     34        $IMAP->set_folder($mbox); 
     35 
     36    $index = $IMAP->index($mbox, null, 'ASC'); 
     37    $count = $index->countMessages(); 
     38    $index = $index->get(); 
    3539 
    3640        vputs("Getting message list of {$mbox}..."); 
    37         vputs($IMAP->messagecount()." messages\n"); 
     41        vputs("$count messages\n"); 
    3842 
    3943        if ($filename) 
     
    4953                $out = STDOUT; 
    5054 
    51         for ($count = $IMAP->messagecount(), $i=1; $i <= $count; $i++) 
     55        for ($i = 0; $i < $count; $i++) 
    5256        { 
    53                 $headers = $IMAP->get_headers($i, null, false); 
     57                $headers = $IMAP->get_message_headers($index[$i]); 
    5458                $from = current(rcube_mime::decode_address_list($headers->from, 1, false)); 
    5559 
    5660                fwrite($out, sprintf("From %s %s UID %d\n", $from['mailto'], $headers->date, $headers->uid)); 
    57                 fwrite($out, $IMAP->conn->fetchPartHeader($mbox, $i)); 
    58                 fwrite($out, $IMAP->conn->handlePartBody($mbox, $i)); 
     61                fwrite($out, $IMAP->print_raw_body($headers->uid)); 
    5962                fwrite($out, "\n\n\n"); 
    6063 
    61                 progress_update($i, $count); 
     64                progress_update($i+1, $count); 
    6265        } 
    6366        vputs("\ncomplete.\n"); 
     
    117120 
    118121        $filename = null; 
    119         $mailboxes = $args['mbox'] == '*' ? $IMAP->list_mailboxes(null) : array($args['mbox']); 
     122        $mailboxes = $args['mbox'] == '*' ? $IMAP->list_folders(null) : array($args['mbox']); 
    120123 
    121124        foreach ($mailboxes as $mbox) 
  • index.php

    rfdff340 rc321a955  
    4949 
    5050// check DB connections and exit on failure 
    51 if ($err_str = $DB->is_error()) { 
     51if ($err_str = $RCMAIL->db->is_error()) { 
    5252  raise_error(array( 
    5353    'code' => 603, 
     
    129129  } 
    130130  else { 
    131     $error_code = (isset($RCMAIL->imap) && is_object($RCMAIL->imap)) ? $RCMAIL->imap->get_error_code() : 1; 
    132  
    133     $OUTPUT->show_message($error_code < -1 ? 'imaperror' : (!$auth['valid'] ? 'invalidrequest' : 'loginfailed'), 'warning'); 
     131    $error_code = is_object($RCMAIL->storage) ? $RCMAIL->storage->get_error_code() : 1; 
     132 
     133    $OUTPUT->show_message($error_code < -1 ? 'storageerror' : (!$auth['valid'] ? 'invalidrequest' : 'loginfailed'), 'warning'); 
    134134    $RCMAIL->plugins->exec_hook('login_failed', array( 
    135135      'code' => $error_code, 'host' => $auth['host'], 'user' => $auth['user'])); 
     
    140140// end session (after optional referer check) 
    141141else if ($RCMAIL->task == 'logout' && isset($_SESSION['user_id']) && (!$RCMAIL->config->get('referer_check') || rcube_check_referer())) { 
    142   $userdata = array('user' => $_SESSION['username'], 'host' => $_SESSION['imap_host'], 'lang' => $RCMAIL->user->language); 
     142  $userdata = array( 
     143    'user' => $_SESSION['username'], 
     144    'host' => $_SESSION['storage_host'], 
     145    'lang' => $RCMAIL->user->language, 
     146  ); 
    143147  $OUTPUT->show_message('loggedout'); 
    144148  $RCMAIL->logout_actions(); 
  • installer/rcube_install.php

    r3efe96a rc321a955  
    4242    'imap_root' => 'imap_ns_personal', 
    4343    'pagesize' => 'mail_pagesize', 
     44    'default_imap_folders' => 'default_folders', 
    4445  ); 
    4546 
     
    180181        $value = '%p'; 
    181182      } 
    182       else if ($prop == 'default_imap_folders') { 
     183      else if ($prop == 'default_folders') { 
    183184            $value = array(); 
    184             foreach ($this->config['default_imap_folders'] as $_folder) { 
     185            foreach ($this->config['default_folders'] as $_folder) { 
    185186              switch ($_folder) { 
    186187              case 'Drafts': $_folder = $this->config['drafts_mbox']; break; 
  • program/include/iniset.php

    • Property mode changed from 100755 to 100644
  • program/include/main.inc

    r4391a780 rc321a955  
    2727 */ 
    2828 
    29 require_once 'utf7.inc'; 
    3029require_once INSTALL_PATH . 'program/include/rcube_shared.inc'; 
    3130 
     
    184183 
    185184 
    186 /** 
    187  * Catch an error and throw an exception. 
    188  * 
    189  * @param  int    Level of the error 
    190  * @param  string Error message 
    191  */  
    192 function rcube_error_handler($errno, $errstr) 
    193 { 
    194   throw new ErrorException($errstr, 0, $errno); 
    195 } 
    196  
    197  
    198 /** 
    199  * Convert a string from one charset to another. 
    200  * Uses mbstring and iconv functions if possible 
    201  * 
    202  * @param  string Input string 
    203  * @param  string Suspected charset of the input string 
    204  * @param  string Target charset to convert to; defaults to RCMAIL_CHARSET 
    205  * @return string Converted string 
    206  */ 
     185// Deprecated 
    207186function rcube_charset_convert($str, $from, $to=NULL) 
    208187{ 
    209   static $iconv_options = null; 
    210   static $mbstring_loaded = null; 
    211   static $mbstring_list = null; 
    212   static $conv = null; 
    213  
    214   $error = false; 
    215  
    216   $to = empty($to) ? strtoupper(RCMAIL_CHARSET) : rcube_parse_charset($to); 
    217   $from = rcube_parse_charset($from); 
    218  
    219   if ($from == $to || empty($str) || empty($from)) 
    220     return $str; 
    221  
    222   // convert charset using iconv module 
    223   if (function_exists('iconv') && $from != 'UTF7-IMAP' && $to != 'UTF7-IMAP') { 
    224     if ($iconv_options === null) { 
    225       // ignore characters not available in output charset 
    226       $iconv_options = '//IGNORE'; 
    227       if (iconv('', $iconv_options, '') === false) { 
    228         // iconv implementation does not support options 
    229         $iconv_options = ''; 
    230       } 
    231     } 
    232  
    233     // throw an exception if iconv reports an illegal character in input 
    234     // it means that input string has been truncated 
    235     set_error_handler('rcube_error_handler', E_NOTICE); 
    236     try { 
    237       $_iconv = iconv($from, $to . $iconv_options, $str); 
    238     } catch (ErrorException $e) { 
    239       $_iconv = false; 
    240     } 
    241     restore_error_handler(); 
    242     if ($_iconv !== false) { 
    243       return $_iconv; 
    244     } 
    245   } 
    246  
    247   if ($mbstring_loaded === null) 
    248     $mbstring_loaded = extension_loaded('mbstring'); 
    249  
    250   // convert charset using mbstring module 
    251   if ($mbstring_loaded) { 
    252     $aliases['WINDOWS-1257'] = 'ISO-8859-13'; 
    253  
    254     if ($mbstring_list === null) { 
    255       $mbstring_list = mb_list_encodings(); 
    256       $mbstring_list = array_map('strtoupper', $mbstring_list); 
    257     } 
    258  
    259     $mb_from = $aliases[$from] ? $aliases[$from] : $from; 
    260     $mb_to = $aliases[$to] ? $aliases[$to] : $to; 
    261  
    262     // return if encoding found, string matches encoding and convert succeeded 
    263     if (in_array($mb_from, $mbstring_list) && in_array($mb_to, $mbstring_list)) { 
    264       if (mb_check_encoding($str, $mb_from) && ($out = mb_convert_encoding($str, $mb_to, $mb_from))) 
    265         return $out; 
    266     } 
    267   } 
    268  
    269   // convert charset using bundled classes/functions 
    270   if ($to == 'UTF-8') { 
    271     if ($from == 'UTF7-IMAP') { 
    272       if ($_str = utf7_to_utf8($str)) 
    273         return $_str; 
    274     } 
    275     else if ($from == 'UTF-7') { 
    276       if ($_str = rcube_utf7_to_utf8($str)) 
    277         return $_str; 
    278     } 
    279     else if (($from == 'ISO-8859-1') && function_exists('utf8_encode')) { 
    280       return utf8_encode($str); 
    281     } 
    282     else if (class_exists('utf8')) { 
    283       if (!$conv) 
    284         $conv = new utf8($from); 
    285       else 
    286         $conv->loadCharset($from); 
    287  
    288       if($_str = $conv->strToUtf8($str)) 
    289         return $_str; 
    290     } 
    291     $error = true; 
    292   } 
    293  
    294   // encode string for output 
    295   if ($from == 'UTF-8') { 
    296     // @TODO: we need a function for UTF-7 (RFC2152) conversion 
    297     if ($to == 'UTF7-IMAP' || $to == 'UTF-7') { 
    298       if ($_str = utf8_to_utf7($str)) 
    299         return $_str; 
    300     } 
    301     else if ($to == 'ISO-8859-1' && function_exists('utf8_decode')) { 
    302       return utf8_decode($str); 
    303     } 
    304     else if (class_exists('utf8')) { 
    305       if (!$conv) 
    306         $conv = new utf8($to); 
    307       else 
    308         $conv->loadCharset($from); 
    309  
    310       if ($_str = $conv->strToUtf8($str)) 
    311         return $_str; 
    312     } 
    313     $error = true; 
    314   } 
    315  
    316   // return UTF-8 or original string 
    317   return $str; 
    318 } 
    319  
    320  
    321 /** 
    322  * Parse and validate charset name string (see #1485758). 
    323  * Sometimes charset string is malformed, there are also charset aliases  
    324  * but we need strict names for charset conversion (specially utf8 class) 
    325  * 
    326  * @param  string Input charset name 
    327  * @return string The validated charset name 
    328  */ 
    329 function rcube_parse_charset($input) 
    330 { 
    331   static $charsets = array(); 
    332   $charset = strtoupper($input); 
    333  
    334   if (isset($charsets[$input])) 
    335     return $charsets[$input]; 
    336  
    337   $charset = preg_replace(array( 
    338     '/^[^0-9A-Z]+/',    // e.g. _ISO-8859-JP$SIO 
    339     '/\$.*$/',          // e.g. _ISO-8859-JP$SIO 
    340     '/UNICODE-1-1-*/',  // RFC1641/1642 
    341     '/^X-/',            // X- prefix (e.g. X-ROMAN8 => ROMAN8) 
    342     ), '', $charset); 
    343  
    344   if ($charset == 'BINARY') 
    345     return $charsets[$input] = null; 
    346  
    347   # Aliases: some of them from HTML5 spec. 
    348   $aliases = array( 
    349     'USASCII'       => 'WINDOWS-1252', 
    350     'ANSIX31101983' => 'WINDOWS-1252', 
    351     'ANSIX341968'   => 'WINDOWS-1252', 
    352     'UNKNOWN8BIT'   => 'ISO-8859-15', 
    353     'UNKNOWN'       => 'ISO-8859-15', 
    354     'USERDEFINED'   => 'ISO-8859-15', 
    355     'KSC56011987'   => 'EUC-KR', 
    356     'GB2312'        => 'GBK', 
    357     'GB231280'      => 'GBK', 
    358     'UNICODE'       => 'UTF-8', 
    359     'UTF7IMAP'      => 'UTF7-IMAP', 
    360     'TIS620'        => 'WINDOWS-874', 
    361     'ISO88599'      => 'WINDOWS-1254', 
    362     'ISO885911'     => 'WINDOWS-874', 
    363     'MACROMAN'      => 'MACINTOSH', 
    364     '77'            => 'MAC', 
    365     '128'           => 'SHIFT-JIS', 
    366     '129'           => 'CP949', 
    367     '130'           => 'CP1361', 
    368     '134'           => 'GBK', 
    369     '136'           => 'BIG5', 
    370     '161'           => 'WINDOWS-1253', 
    371     '162'           => 'WINDOWS-1254', 
    372     '163'           => 'WINDOWS-1258', 
    373     '177'           => 'WINDOWS-1255', 
    374     '178'           => 'WINDOWS-1256', 
    375     '186'           => 'WINDOWS-1257', 
    376     '204'           => 'WINDOWS-1251', 
    377     '222'           => 'WINDOWS-874', 
    378     '238'           => 'WINDOWS-1250', 
    379     'MS950'         => 'CP950', 
    380     'WINDOWS949'    => 'UHC', 
    381   ); 
    382  
    383   // allow A-Z and 0-9 only 
    384   $str = preg_replace('/[^A-Z0-9]/', '', $charset); 
    385  
    386   if (isset($aliases[$str])) 
    387     $result = $aliases[$str]; 
    388   // UTF 
    389   else if (preg_match('/U[A-Z][A-Z](7|8|16|32)(BE|LE)*/', $str, $m)) 
    390     $result = 'UTF-' . $m[1] . $m[2]; 
    391   // ISO-8859 
    392   else if (preg_match('/ISO8859([0-9]{0,2})/', $str, $m)) { 
    393     $iso = 'ISO-8859-' . ($m[1] ? $m[1] : 1); 
    394     // some clients sends windows-1252 text as latin1, 
    395     // it is safe to use windows-1252 for all latin1 
    396     $result = $iso == 'ISO-8859-1' ? 'WINDOWS-1252' : $iso; 
    397   } 
    398   // handle broken charset names e.g. WINDOWS-1250HTTP-EQUIVCONTENT-TYPE 
    399   else if (preg_match('/(WIN|WINDOWS)([0-9]+)/', $str, $m)) { 
    400     $result = 'WINDOWS-' . $m[2]; 
    401   } 
    402   // LATIN 
    403   else if (preg_match('/LATIN(.*)/', $str, $m)) { 
    404     $aliases = array('2' => 2, '3' => 3, '4' => 4, '5' => 9, '6' => 10, 
    405         '7' => 13, '8' => 14, '9' => 15, '10' => 16, 
    406         'ARABIC' => 6, 'CYRILLIC' => 5, 'GREEK' => 7, 'GREEK1' => 7, 'HEBREW' => 8); 
    407  
    408     // some clients sends windows-1252 text as latin1, 
    409     // it is safe to use windows-1252 for all latin1 
    410     if ($m[1] == 1) { 
    411       $result = 'WINDOWS-1252'; 
    412     } 
    413     // if iconv is not supported we need ISO labels, it's also safe for iconv 
    414     else if (!empty($aliases[$m[1]])) { 
    415       $result = 'ISO-8859-'.$aliases[$m[1]]; 
    416     } 
    417     // iconv requires convertion of e.g. LATIN-1 to LATIN1 
    418     else { 
    419       $result = $str; 
    420     } 
    421   } 
    422   else { 
    423     $result = $charset; 
    424   } 
    425  
    426   $charsets[$input] = $result; 
    427  
    428   return $result; 
    429 } 
    430  
    431  
    432 /** 
    433  * Converts string from standard UTF-7 (RFC 2152) to UTF-8. 
    434  * 
    435  * @param  string  Input string 
    436  * @return string  The converted string 
    437  */ 
    438 function rcube_utf7_to_utf8($str) 
    439 { 
    440   $Index_64 = array( 
    441     0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 
    442     0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 
    443     0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0, 
    444     1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, 
    445     0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 
    446     1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, 
    447     0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 
    448     1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, 
    449   ); 
    450  
    451   $u7len = strlen($str); 
    452   $str = strval($str); 
    453   $res = ''; 
    454  
    455   for ($i=0; $u7len > 0; $i++, $u7len--) 
    456   { 
    457     $u7 = $str[$i]; 
    458     if ($u7 == '+') 
    459     { 
    460       $i++; 
    461       $u7len--; 
    462       $ch = ''; 
    463  
    464       for (; $u7len > 0; $i++, $u7len--) 
    465       { 
    466         $u7 = $str[$i]; 
    467  
    468         if (!$Index_64[ord($u7)]) 
    469           break; 
    470  
    471         $ch .= $u7; 
    472       } 
    473  
    474       if ($ch == '') { 
    475         if ($u7 == '-') 
    476           $res .= '+'; 
    477         continue; 
    478       } 
    479  
    480       $res .= rcube_utf16_to_utf8(base64_decode($ch)); 
    481     } 
    482     else 
    483     { 
    484       $res .= $u7; 
    485     } 
    486   } 
    487  
    488   return $res; 
    489 } 
    490  
    491 /** 
    492  * Converts string from UTF-16 to UTF-8 (helper for utf-7 to utf-8 conversion) 
    493  * 
    494  * @param  string  Input string 
    495  * @return string  The converted string 
    496  */ 
    497 function rcube_utf16_to_utf8($str) 
    498 { 
    499   $len = strlen($str); 
    500   $dec = ''; 
    501  
    502   for ($i = 0; $i < $len; $i += 2) { 
    503     $c = ord($str[$i]) << 8 | ord($str[$i + 1]); 
    504     if ($c >= 0x0001 && $c <= 0x007F) { 
    505       $dec .= chr($c); 
    506     } else if ($c > 0x07FF) { 
    507       $dec .= chr(0xE0 | (($c >> 12) & 0x0F)); 
    508       $dec .= chr(0x80 | (($c >>  6) & 0x3F)); 
    509       $dec .= chr(0x80 | (($c >>  0) & 0x3F)); 
    510     } else { 
    511       $dec .= chr(0xC0 | (($c >>  6) & 0x1F)); 
    512       $dec .= chr(0x80 | (($c >>  0) & 0x3F)); 
    513     } 
    514   } 
    515   return $dec; 
     188    return rcube_charset::convert($str, $from, $to); 
     189} 
     190 
     191 
     192// Deprecated 
     193function rc_detect_encoding($string, $failover='') 
     194{ 
     195    return rcube_charset::detect($string, $failover); 
     196} 
     197 
     198 
     199// Deprecated 
     200function rc_utf8_clean($input) 
     201{ 
     202    return rcube_charset::clean($input); 
     203} 
     204 
     205 
     206/** 
     207 * Convert a variable into a javascript object notation 
     208 * 
     209 * @param mixed Input value 
     210 * @return string Serialized JSON string 
     211 */ 
     212function json_serialize($input) 
     213{ 
     214    $input = rcube_charset::clean($input); 
     215 
     216    // sometimes even using rcube_charset::clean() the input contains invalid UTF-8 sequences 
     217    // that's why we have @ here 
     218    return @json_encode($input); 
    516219} 
    517220 
     
    1194897 
    1195898  // get mailbox list 
    1196   $mbox_name = $RCMAIL->imap->get_mailbox_name(); 
     899  $mbox_name = $RCMAIL->storage->get_folder(); 
    1197900 
    1198901  // build the folders tree 
    1199902  if (empty($a_mailboxes)) { 
    1200903    // get mailbox list 
    1201     $a_folders = $RCMAIL->imap->list_mailboxes('', $attrib['folder_name'], $attrib['folder_filter']); 
    1202     $delimiter = $RCMAIL->imap->get_hierarchy_delimiter(); 
     904    $a_folders = $RCMAIL->storage->list_folders_subscribed('', $attrib['folder_name'], $attrib['folder_filter']); 
     905    $delimiter = $RCMAIL->storage->get_hierarchy_delimiter(); 
    1203906    $a_mailboxes = array(); 
    1204907 
     
    1246949  $p += array('maxlength' => 100, 'realnames' => false); 
    1247950  $a_mailboxes = array(); 
    1248  
    1249   if (empty($p['folder_name'])) 
     951  $storage = $RCMAIL->get_storage(); 
     952 
     953  if (empty($p['folder_name'])) { 
    1250954    $p['folder_name'] = '*'; 
     955  } 
    1251956 
    1252957  if ($p['unsubscribed']) 
    1253     $list = $RCMAIL->imap->list_unsubscribed('', $p['folder_name'], $p['folder_filter'], $p['folder_rights']); 
     958    $list = $storage->list_folders('', $p['folder_name'], $p['folder_filter'], $p['folder_rights']); 
    1254959  else 
    1255     $list = $RCMAIL->imap->list_mailboxes('', $p['folder_name'], $p['folder_filter'], $p['folder_rights']); 
    1256  
    1257   $delimiter = $RCMAIL->imap->get_hierarchy_delimiter(); 
     960    $list = $storage->list_folders_subscribed('', $p['folder_name'], $p['folder_filter'], $p['folder_rights']); 
     961 
     962  $delimiter = $storage->get_hierarchy_delimiter(); 
    1258963 
    1259964  foreach ($list as $folder) { 
     
    1286991  if (!$path) { 
    1287992    $n_folder = $folder; 
    1288     $folder = $RCMAIL->imap->mod_mailbox($folder); 
     993    $folder = $RCMAIL->storage->mod_folder($folder); 
    1289994 
    1290995    if ($n_folder != $folder) { 
     
    13411046  $maxlength = intval($attrib['maxlength']); 
    13421047  $realnames = (bool)$attrib['realnames']; 
    1343   $msgcounts = $RCMAIL->imap->get_cache('messagecount'); 
     1048  $msgcounts = $RCMAIL->storage->get_cache('messagecount'); 
    13441049 
    13451050  $out = ''; 
     
    14331138 
    14341139    // skip folders in which it isn't possible to create subfolders 
    1435     if (!empty($opts['skip_noinferiors']) && ($attrs = $RCMAIL->imap->mailbox_attributes($folder['id'])) 
     1140    if (!empty($opts['skip_noinferiors']) && ($attrs = $RCMAIL->storage->folder_attributes($folder['id'])) 
    14361141        && in_array('\\Noinferiors', $attrs) 
    14371142    ) { 
     
    15021207 
    15031208    $protect_folders = $RCMAIL->config->get('protect_default_folders'); 
    1504     $default_folders = (array) $RCMAIL->config->get('default_imap_folders'); 
    1505     $delimiter       = $RCMAIL->imap->get_hierarchy_delimiter(); 
     1209    $default_folders = (array) $RCMAIL->config->get('default_folders'); 
     1210    $delimiter       = $RCMAIL->storage->get_hierarchy_delimiter(); 
    15061211    $path            = explode($delimiter, $path); 
    15071212    $result          = array(); 
     
    15461251  global $RCMAIL; 
    15471252 
    1548   $quota = $RCMAIL->imap->get_quota(); 
     1253  $quota = $RCMAIL->storage->get_quota(); 
    15491254  $quota = $RCMAIL->plugins->exec_hook('quota', $quota); 
    15501255 
     
    15921297    global $RCMAIL; 
    15931298 
    1594     $err_code = $RCMAIL->imap->get_error_code(); 
    1595     $res_code = $RCMAIL->imap->get_response_code(); 
    1596  
    1597     if ($res_code == rcube_imap::NOPERM) { 
     1299    $err_code = $RCMAIL->storage->get_error_code(); 
     1300    $res_code = $RCMAIL->storage->get_response_code(); 
     1301 
     1302    if ($err_code < 0) { 
     1303        $RCMAIL->output->show_message('storageerror', 'error'); 
     1304    } 
     1305    else if ($res_code == rcube_storage::NOPERM) { 
    15981306        $RCMAIL->output->show_message('errornoperm', 'error'); 
    15991307    } 
    1600     else if ($res_code == rcube_imap::READONLY) { 
     1308    else if ($res_code == rcube_storage::READONLY) { 
    16011309        $RCMAIL->output->show_message('errorreadonly', 'error'); 
    16021310    } 
    1603     else if ($err_code && ($err_str = $RCMAIL->imap->get_error_str())) { 
     1311    else if ($err_code && ($err_str = $RCMAIL->storage->get_error_str())) { 
    16041312        // try to detect access rights problem and display appropriate message 
    16051313        if (stripos($err_str, 'Permission denied') !== false) 
     
    19691677  $d = preg_replace('/^[^\.]+\./', '', $n); 
    19701678  // %h - IMAP host 
    1971   $h = $_SESSION['imap_host'] ? $_SESSION['imap_host'] : $host; 
     1679  $h = $_SESSION['storage_host'] ? $_SESSION['storage_host'] : $host; 
    19721680  // %z - IMAP domain without first part, e.g. %h=imap.domain.tld, %z=domain.tld 
    19731681  $z = preg_replace('/^[^\.]+\./', '', $h); 
  • program/include/rcmail.php

    rfdff340 rc321a955  
    8787 
    8888  /** 
    89    * Instance of rcube_imap class. 
    90    * 
    91    * @var rcube_imap 
    92    */ 
    93   public $imap; 
     89   * Instance of rcube_storage class. 
     90   * 
     91   * @var rcube_storage 
     92   */ 
     93  public $storage; 
    9494 
    9595  /** 
     
    172172    // connect to database 
    173173    $this->get_dbh(); 
    174  
    175     // set global object for backward compatibility 
    176     $GLOBALS['DB'] = $this->db; 
    177174 
    178175    // start session 
     
    242239    if (is_object($user)) { 
    243240      $this->user = $user; 
    244  
    245       // set global object for backward compatibility 
    246       $GLOBALS['USER'] = $this->user; 
    247241 
    248242      // overwrite config with user preferences 
     
    425419    } 
    426420    else if ($id && $ldap_config[$id]) { 
    427       $contacts = new rcube_ldap($ldap_config[$id], $this->config->get('ldap_debug'), $this->config->mail_domain($_SESSION['imap_host'])); 
     421      $contacts = new rcube_ldap($ldap_config[$id], $this->config->get('ldap_debug'), $this->config->mail_domain($_SESSION['storage_host'])); 
    428422    } 
    429423    else if ($id === '0') { 
     
    585579 
    586580  /** 
    587    * Create global IMAP object and connect to server 
    588    * 
    589    * @param boolean True if connection should be established 
    590    */ 
    591   public function imap_init($connect = false) 
     581   * Initialize and get storage object 
     582   * 
     583   * @return rcube_storage Storage object 
     584   */ 
     585  public function get_storage() 
    592586  { 
    593587    // already initialized 
    594     if (is_object($this->imap)) 
     588    if (!is_object($this->storage)) { 
     589      $this->storage_init(); 
     590    } 
     591 
     592    return $this->storage; 
     593  } 
     594 
     595 
     596  /** 
     597   * Connect to the IMAP server with stored session data. 
     598   * 
     599   * @return bool True on success, False on error 
     600   * @deprecated 
     601   */ 
     602  public function imap_connect() 
     603  { 
     604    return $this->storage_connect(); 
     605  } 
     606 
     607 
     608  /** 
     609   * Initialize IMAP object. 
     610   * 
     611   * @deprecated 
     612   */ 
     613  public function imap_init() 
     614  { 
     615    $this->storage_init(); 
     616  } 
     617 
     618 
     619  /** 
     620   * Initialize storage object 
     621   */ 
     622  public function storage_init() 
     623  { 
     624    // already initialized 
     625    if (is_object($this->storage)) { 
    595626      return; 
    596  
    597     $this->imap = new rcube_imap(); 
    598     $this->imap->skip_deleted = $this->config->get('skip_deleted'); 
    599  
    600     // enable caching of imap data 
    601     $imap_cache     = $this->config->get('imap_cache'); 
     627    } 
     628 
     629    $driver = $this->config->get('storage_driver', 'imap'); 
     630    $driver_class = "rcube_{$driver}"; 
     631 
     632    if (!class_exists($driver_class)) { 
     633      raise_error(array( 
     634        'code' => 700, 'type' => 'php', 
     635        'file' => __FILE__, 'line' => __LINE__, 
     636        'message' => "Storage driver class ($driver) not found!"), 
     637        true, true); 
     638    } 
     639 
     640    // Initialize storage object 
     641    $this->storage = new $driver_class; 
     642 
     643    // for backward compat. (deprecated, will be removed) 
     644    $this->imap = $this->storage; 
     645 
     646    // enable caching of mail data 
     647    $storage_cache  = $this->config->get("{$driver}_cache"); 
    602648    $messages_cache = $this->config->get('messages_cache'); 
    603649    // for backward compatybility 
    604     if ($imap_cache === null && $messages_cache === null && $this->config->get('enable_caching')) { 
    605         $imap_cache     = 'db'; 
     650    if ($storage_cache === null && $messages_cache === null && $this->config->get('enable_caching')) { 
     651        $storage_cache  = 'db'; 
    606652        $messages_cache = true; 
    607653    } 
    608654 
    609     if ($imap_cache) 
    610         $this->imap->set_caching($imap_cache); 
     655    if ($storage_cache) 
     656        $this->storage->set_caching($storage_cache); 
    611657    if ($messages_cache) 
    612         $this->imap->set_messages_caching(true); 
     658        $this->storage->set_messages_caching(true); 
    613659 
    614660    // set pagesize from config 
     
    617663        $pagesize = $this->config->get('pagesize', 50); 
    618664    } 
    619     $this->imap->set_pagesize($pagesize); 
    620  
    621     // set connection options 
     665    $this->storage->set_pagesize($pagesize); 
     666 
     667    // set class options 
    622668    $options = array( 
    623       'auth_type'   => $this->config->get('imap_auth_type', 'check'), 
    624       'auth_cid'    => $this->config->get('imap_auth_cid'), 
    625       'auth_pw'     => $this->config->get('imap_auth_pw'), 
    626       'debug'       => (bool) $this->config->get('imap_debug', 0), 
    627       'force_caps'  => (bool) $this->config->get('imap_force_caps'), 
    628       'timeout'     => (int) $this->config->get('imap_timeout', 0), 
     669      'auth_type'   => $this->config->get("{$driver}_auth_type", 'check'), 
     670      'auth_cid'    => $this->config->get("{$driver}_auth_cid"), 
     671      'auth_pw'     => $this->config->get("{$driver}_auth_pw"), 
     672      'debug'       => (bool) $this->config->get("{$driver}_debug"), 
     673      'force_caps'  => (bool) $this->config->get("{$driver}_force_caps"), 
     674      'timeout'     => (int) $this->config->get("{$driver}_timeout"), 
     675      'skip_deleted' => (bool) $this->config->get('skip_deleted'), 
     676      'driver'      => $driver, 
    629677    ); 
    630678 
    631     $this->imap->set_options($options); 
    632  
    633     // set global object for backward compatibility 
    634     $GLOBALS['IMAP'] = $this->imap; 
    635  
    636     $hook = $this->plugins->exec_hook('imap_init', array('fetch_headers' => $this->imap->fetch_add_headers)); 
    637     if ($hook['fetch_headers']) 
    638       $this->imap->fetch_add_headers = $hook['fetch_headers']; 
    639  
    640     // support this parameter for backward compatibility but log warning 
    641     if ($connect) { 
    642       $this->imap_connect(); 
    643       raise_error(array( 
    644         'code' => 800, 'type' => 'imap', 
    645         'file' => __FILE__, 'line' => __LINE__, 
    646         'message' => "rcube::imap_init(true) is deprecated, use rcube::imap_connect() instead"), 
    647         true, false); 
    648     } 
    649   } 
    650  
    651  
    652   /** 
    653    * Connect to IMAP server with stored session data 
    654    * 
    655    * @return bool True on success, false on error 
    656    */ 
    657   public function imap_connect() 
    658   { 
    659     if (!$this->imap) 
    660       $this->imap_init(); 
    661  
    662     if ($_SESSION['imap_host'] && !$this->imap->conn->connected()) { 
    663       if (!$this->imap->connect($_SESSION['imap_host'], $_SESSION['username'], $this->decrypt($_SESSION['password']), $_SESSION['imap_port'], $_SESSION['imap_ssl'])) { 
     679    if (!empty($_SESSION['storage_host'])) { 
     680      $options['host']     = $_SESSION['storage_host']; 
     681      $options['user']     = $_SESSION['username']; 
     682      $options['port']     = $_SESSION['storage_port']; 
     683      $options['ssl']      = $_SESSION['storage_ssl']; 
     684      $options['password'] = $this->decrypt($_SESSION['password']); 
     685    } 
     686 
     687    $options = $this->plugins->exec_hook("storage_init", $options); 
     688 
     689    // for backward compat. (deprecated, to be removed) 
     690    $options = $this->plugins->exec_hook("imap_init", $options); 
     691 
     692    $this->storage->set_options($options); 
     693    $this->set_storage_prop(); 
     694  } 
     695 
     696 
     697  /** 
     698   * Connect to the mail storage server with stored session data 
     699   * 
     700   * @return bool True on success, False on error 
     701   */ 
     702  public function storage_connect() 
     703  { 
     704    $storage = $this->get_storage(); 
     705 
     706    if ($_SESSION['storage_host'] && !$storage->is_connected()) { 
     707      $host = $_SESSION['storage_host']; 
     708      $user = $_SESSION['username']; 
     709      $port = $_SESSION['storage_port']; 
     710      $ssl  = $_SESSION['storage_ssl']; 
     711      $pass = $this->decrypt($_SESSION['password']); 
     712 
     713      if (!$storage->connect($host, $user, $pass, $port, $ssl)) { 
    664714        if ($this->output) 
    665           $this->output->show_message($this->imap->get_error_code() == -1 ? 'imaperror' : 'sessionerror', 'error'); 
     715          $this->output->show_message($storage->get_error_code() == -1 ? 'storageerror' : 'sessionerror', 'error'); 
    666716      } 
    667717      else { 
    668         $this->set_imap_prop(); 
    669         return $this->imap->conn; 
     718        $this->set_storage_prop(); 
     719        return $storage->is_connected(); 
    670720      } 
    671721    } 
     
    745795 
    746796  /** 
    747    * Perfom login to the IMAP server and to the webmail service. 
     797   * Perfom login to the mail server and to the webmail service. 
    748798   * This will also create a new user entry if auto_create_user is configured. 
    749799   * 
    750    * @param string IMAP user name 
    751    * @param string IMAP password 
    752    * @param string IMAP host 
     800   * @param string Mail storage (IMAP) user name 
     801   * @param string Mail storage (IMAP) password 
     802   * @param string Mail storage (IMAP) host 
    753803   * 
    754804   * @return boolean True on success, False on failure 
     
    786836    if ($a_host['host']) { 
    787837      $host = $a_host['host']; 
    788       $imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? $a_host['scheme'] : null; 
     838      $ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? $a_host['scheme'] : null; 
    789839      if (!empty($a_host['port'])) 
    790         $imap_port = $a_host['port']; 
    791       else if ($imap_ssl && $imap_ssl != 'tls' && (!$config['default_port'] || $config['default_port'] == 143)) 
    792         $imap_port = 993; 
    793     } 
    794  
    795     $imap_port = $imap_port ? $imap_port : $config['default_port']; 
     840        $port = $a_host['port']; 
     841      else if ($ssl && $ssl != 'tls' && (!$config['default_port'] || $config['default_port'] == 143)) 
     842        $port = 993; 
     843    } 
     844 
     845    if (!$port) { 
     846        $port = $config['default_port']; 
     847    } 
    796848 
    797849    /* Modify username with domain if required 
     
    806858    } 
    807859 
    808     // Convert username to lowercase. If IMAP backend 
     860    // Convert username to lowercase. If storage backend 
    809861    // is case-insensitive we need to store always the same username (#1487113) 
    810862    if ($config['login_lc']) { 
     
    831883      $username = $user->data['username']; 
    832884 
    833     if (!$this->imap) 
    834       $this->imap_init(); 
    835  
    836     // try IMAP login 
    837     if (!($imap_login = $this->imap->connect($host, $username, $pass, $imap_port, $imap_ssl))) { 
     885    if (!$this->storage) 
     886      $this->storage_init(); 
     887 
     888    // try to log in 
     889    if (!($login = $this->storage->connect($host, $username, $pass, $port, $ssl))) { 
    838890      // try with lowercase 
    839891      $username_lc = mb_strtolower($username); 
     
    843895          $username_lc = $user->data['username']; 
    844896 
    845         if ($imap_login = $this->imap->connect($host, $username_lc, $pass, $imap_port, $imap_ssl)) 
     897        if ($login = $this->storage->connect($host, $username_lc, $pass, $port, $ssl)) 
    846898          $username = $username_lc; 
    847899      } 
    848900    } 
    849901 
    850     // exit if IMAP login failed 
    851     if (!$imap_login) 
     902    // exit if login failed 
     903    if (!$login) { 
    852904      return false; 
     905    } 
    853906 
    854907    // user already registered -> update user's record 
     
    882935      // Configure environment 
    883936      $this->set_user($user); 
    884       $this->set_imap_prop(); 
     937      $this->set_storage_prop(); 
    885938      $this->session_configure(); 
    886939 
     
    890943      // create default folders on first login 
    891944      if ($config['create_default_folders'] && (!empty($created) || empty($user->data['last_login']))) { 
    892         $this->imap->create_default_folders(); 
     945        $this->storage->create_default_folders(); 
    893946      } 
    894947 
    895948      // set session vars 
    896       $_SESSION['user_id']   = $user->ID; 
    897       $_SESSION['username']  = $user->data['username']; 
    898       $_SESSION['imap_host'] = $host; 
    899       $_SESSION['imap_port'] = $imap_port; 
    900       $_SESSION['imap_ssl']  = $imap_ssl; 
    901       $_SESSION['password']  = $this->encrypt($pass); 
    902       $_SESSION['login_time'] = mktime(); 
     949      $_SESSION['user_id']      = $user->ID; 
     950      $_SESSION['username']     = $user->data['username']; 
     951      $_SESSION['storage_host'] = $host; 
     952      $_SESSION['storage_port'] = $port; 
     953      $_SESSION['storage_ssl']  = $ssl; 
     954      $_SESSION['password']     = $this->encrypt($pass); 
     955      $_SESSION['login_time']   = mktime(); 
    903956 
    904957      if (isset($_REQUEST['_timezone']) && $_REQUEST['_timezone'] != '_default_') 
     
    908961 
    909962      // force reloading complete list of subscribed mailboxes 
    910       $this->imap->clear_cache('mailboxes', true); 
     963      $this->storage->clear_cache('mailboxes', true); 
    911964 
    912965      return true; 
     
    918971 
    919972  /** 
    920    * Set root dir and last stored mailbox 
     973   * Set storage parameters. 
    921974   * This must be done AFTER connecting to the server! 
    922975   */ 
    923   public function set_imap_prop() 
    924   { 
    925     $this->imap->set_charset($this->config->get('default_charset', RCMAIL_CHARSET)); 
    926  
    927     if ($default_folders = $this->config->get('default_imap_folders')) { 
    928       $this->imap->set_default_mailboxes($default_folders); 
     976  private function set_storage_prop() 
     977  { 
     978    $storage = $this->get_storage(); 
     979 
     980    $storage->set_charset($this->config->get('default_charset', RCMAIL_CHARSET)); 
     981 
     982    if ($default_folders = $this->config->get('default_folders')) { 
     983      $storage->set_default_folders($default_folders); 
    929984    } 
    930985    if (isset($_SESSION['mbox'])) { 
    931       $this->imap->set_mailbox($_SESSION['mbox']); 
     986      $storage->set_folder($_SESSION['mbox']); 
    932987    } 
    933988    if (isset($_SESSION['page'])) { 
    934       $this->imap->set_page($_SESSION['page']); 
     989      $storage->set_page($_SESSION['page']); 
    935990    } 
    936991  } 
     
    9581013      list($user, $domain) = explode('@', get_input_value('_user', RCUBE_INPUT_POST)); 
    9591014      if (!empty($domain)) { 
    960         foreach ($default_host as $imap_host => $mail_domains) { 
     1015        foreach ($default_host as $storage_host => $mail_domains) { 
    9611016          if (is_array($mail_domains) && in_array($domain, $mail_domains)) { 
    962             $host = $imap_host; 
     1017            $host = $storage_host; 
    9631018            break; 
    9641019          } 
     
    11681223        return; 
    11691224 
    1170       $this->imap_connect(); 
     1225      $this->storage_connect(); 
    11711226    } 
    11721227 
    11731228    if ($config['logout_purge'] && !empty($config['trash_mbox'])) { 
    1174       $this->imap->clear_mailbox($config['trash_mbox']); 
     1229      $this->storage->clear_folder($config['trash_mbox']); 
    11751230    } 
    11761231 
    11771232    if ($config['logout_expunge']) { 
    1178       $this->imap->expunge('INBOX'); 
     1233      $this->storage->expunge_folder('INBOX'); 
    11791234    } 
    11801235 
     
    12081263    } 
    12091264 
    1210     if (is_object($this->imap)) 
    1211       $this->imap->close(); 
     1265    if (is_object($this->storage)) 
     1266      $this->storage->close(); 
    12121267 
    12131268    // before closing the database connection, write session data 
     
    16081663  private function fix_namespace_settings($user) 
    16091664  { 
    1610     $prefix     = $this->imap->get_namespace('prefix'); 
     1665    $prefix     = $this->storage->get_namespace('prefix'); 
    16111666    $prefix_len = strlen($prefix); 
    16121667 
     
    16191674 
    16201675    // Build namespace prefix regexp 
    1621     $ns     = $this->imap->get_namespace(); 
     1676    $ns     = $this->storage->get_namespace(); 
    16221677    $regexp = array(); 
    16231678 
     
    16431698    } 
    16441699 
    1645     if (!empty($prefs['default_imap_folders'])) { 
    1646       foreach ($prefs['default_imap_folders'] as $idx => $name) { 
     1700    if (!empty($prefs['default_folders'])) { 
     1701      foreach ($prefs['default_folders'] as $idx => $name) { 
    16471702        if ($name != 'INBOX' && !preg_match($regexp, $name)) { 
    1648           $prefs['default_imap_folders'][$idx] = $prefix.$name; 
     1703          $prefs['default_folders'][$idx] = $prefix.$name; 
    16491704        } 
    16501705      } 
     
    16961751    // save updated preferences and reset imap settings (default folders) 
    16971752    $user->save_prefs($prefs); 
    1698     $this->set_imap_prop(); 
     1753    $this->set_storage_prop(); 
    16991754  } 
    17001755 
  • program/include/rcube_config.php

    re86a21b rc321a955  
    7373            $this->prop[$folder] = rcube_charset_convert($this->prop[$folder], RCMAIL_CHARSET, 'UTF7-IMAP'); 
    7474 
    75         if (!empty($this->prop['default_imap_folders'])) 
    76             foreach ($this->prop['default_imap_folders'] as $n => $folder) 
    77                 $this->prop['default_imap_folders'][$n] = rcube_charset_convert($folder, RCMAIL_CHARSET, 'UTF7-IMAP'); 
     75        if (!empty($this->prop['default_folders'])) 
     76            foreach ($this->prop['default_folders'] as $n => $folder) 
     77                $this->prop['default_folders'][$n] = rcube_charset_convert($folder, RCMAIL_CHARSET, 'UTF7-IMAP'); 
    7878 
    7979        // set PHP error logging according to config 
  • program/include/rcube_imap.php

    r2081eed rc321a955  
    66 |                                                                       | 
    77 | This file is part of the Roundcube Webmail client                     | 
    8  | Copyright (C) 2005-2011, The Roundcube Dev Team                       | 
    9  | Copyright (C) 2011, Kolab Systems AG                                  | 
     8 | Copyright (C) 2005-2012, The Roundcube Dev Team                       | 
     9 | Copyright (C) 2011-2012, Kolab Systems AG                             | 
    1010 | Licensed under the GNU GPL                                            | 
    1111 |                                                                       | 
    1212 | PURPOSE:                                                              | 
    13  |   IMAP Engine                                                         | 
     13 |   IMAP Storage Engine                                                 | 
    1414 |                                                                       | 
    1515 +-----------------------------------------------------------------------+ 
     
    3131 * @version    2.0 
    3232 */ 
    33 class rcube_imap 
     33class rcube_imap extends rcube_storage 
    3434{ 
    35     public $skip_deleted = false; 
    36     public $page_size = 10; 
    37     public $list_page = 1; 
    38     public $threading = false; 
    39     public $fetch_add_headers = ''; 
    40     public $get_all_headers = false; 
    41  
    4235    /** 
    4336     * Instance of rcube_imap_generic 
     
    5245     * @var rcube_imap_cache 
    5346     */ 
    54     private $mcache; 
     47    protected $mcache; 
    5548 
    5649    /** 
     
    5952     * @var rcube_cache 
    6053     */ 
    61     private $cache; 
     54    protected $cache; 
    6255 
    6356    /** 
     
    6659     * @var array 
    6760     */ 
    68     private $icache = array(); 
    69  
    70     private $mailbox = 'INBOX'; 
    71     private $delimiter = NULL; 
    72     private $namespace = NULL; 
    73     private $sort_field = ''; 
    74     private $sort_order = 'DESC'; 
    75     private $default_charset = 'ISO-8859-1'; 
    76     private $struct_charset = NULL; 
    77     private $default_folders = array('INBOX'); 
    78     private $uid_id_map = array(); 
    79     private $msg_headers = array(); 
    80     public  $search_set = NULL; 
    81     public  $search_string = ''; 
    82     private $search_charset = ''; 
    83     private $search_sort_field = ''; 
    84     private $search_threads = false; 
    85     private $search_sorted = false; 
    86     private $options = array('auth_method' => 'check'); 
    87     private $host, $user, $pass, $port, $ssl; 
    88     private $caching = false; 
    89     private $messages_caching = false; 
    90  
    91     /** 
    92      * All (additional) headers used (in any way) by Roundcube 
    93      * Not listed here: DATE, FROM, TO, CC, REPLY-TO, SUBJECT, CONTENT-TYPE, LIST-POST 
    94      * (used for messages listing) are hardcoded in rcube_imap_generic::fetchHeaders() 
    95      * 
    96      * @var array 
    97      * @see rcube_imap::fetch_add_headers 
    98      */ 
    99     private $all_headers = array( 
    100         'IN-REPLY-TO', 
    101         'BCC', 
    102         'MESSAGE-ID', 
    103         'CONTENT-TRANSFER-ENCODING', 
    104         'REFERENCES', 
    105         'X-DRAFT-INFO', 
    106         'MAIL-FOLLOWUP-TO', 
    107         'MAIL-REPLY-TO', 
    108         'RETURN-PATH', 
    109     ); 
    110  
    111     const UNKNOWN       = 0; 
    112     const NOPERM        = 1; 
    113     const READONLY      = 2; 
    114     const TRYCREATE     = 3; 
    115     const INUSE         = 4; 
    116     const OVERQUOTA     = 5; 
    117     const ALREADYEXISTS = 6; 
    118     const NONEXISTENT   = 7; 
    119     const CONTACTADMIN  = 8; 
     61    protected $icache = array(); 
     62 
     63    protected $list_page = 1; 
     64    protected $delimiter; 
     65    protected $namespace; 
     66    protected $sort_field = ''; 
     67    protected $sort_order = 'DESC'; 
     68    protected $struct_charset; 
     69    protected $uid_id_map = array(); 
     70    protected $msg_headers = array(); 
     71    protected $search_set; 
     72    protected $search_string = ''; 
     73    protected $search_charset = ''; 
     74    protected $search_sort_field = ''; 
     75    protected $search_threads = false; 
     76    protected $search_sorted = false; 
     77    protected $options = array('auth_method' => 'check'); 
     78    protected $caching = false; 
     79    protected $messages_caching = false; 
     80    protected $threading = false; 
    12081 
    12182 
     
    12384     * Object constructor. 
    12485     */ 
    125     function __construct() 
     86    public function __construct() 
    12687    { 
    12788        $this->conn = new rcube_imap_generic(); 
     
    12990        // Set namespace and delimiter from session, 
    13091        // so some methods would work before connection 
    131         if (isset($_SESSION['imap_namespace'])) 
     92        if (isset($_SESSION['imap_namespace'])) { 
    13293            $this->namespace = $_SESSION['imap_namespace']; 
    133         if (isset($_SESSION['imap_delimiter'])) 
     94        } 
     95        if (isset($_SESSION['imap_delimiter'])) { 
    13496            $this->delimiter = $_SESSION['imap_delimiter']; 
     97        } 
     98    } 
     99 
     100 
     101    /** 
     102     * Magic getter for backward compat. 
     103     * 
     104     * @deprecated. 
     105     */ 
     106    public function __get($name) 
     107    { 
     108        if (isset($this->{$name})) { 
     109            return $this->{$name}; 
     110        } 
    135111    } 
    136112 
     
    144120     * @param  integer  $port    Port to connect to 
    145121     * @param  string   $use_ssl SSL schema (either ssl or tls) or null if plain connection 
     122     * 
    146123     * @return boolean  TRUE on success, FALSE on failure 
    147      * @access public 
    148      */ 
    149     function connect($host, $user, $pass, $port=143, $use_ssl=null) 
     124     */ 
     125    public function connect($host, $user, $pass, $port=143, $use_ssl=null) 
    150126    { 
    151127        // check for OpenSSL support in PHP build 
    152         if ($use_ssl && extension_loaded('openssl')) 
     128        if ($use_ssl && extension_loaded('openssl')) { 
    153129            $this->options['ssl_mode'] = $use_ssl == 'imaps' ? 'ssl' : $use_ssl; 
     130        } 
    154131        else if ($use_ssl) { 
    155132            raise_error(array('code' => 403, 'type' => 'imap', 
     
    162139 
    163140        if ($this->options['debug']) { 
    164             $this->conn->setDebug(true, array($this, 'debug_handler')); 
     141            $this->set_debug(true); 
    165142 
    166143            $this->options['ident'] = array( 
     
    179156                    'attempt' => ++$attempt))); 
    180157 
    181             if (!empty($data['pass'])) 
     158            if (!empty($data['pass'])) { 
    182159                $pass = $data['pass']; 
     160            } 
    183161 
    184162            $this->conn->connect($data['host'], $data['user'], $pass, $data); 
    185163        } while(!$this->conn->connected() && $data['retry']); 
    186164 
    187         $this->host = $data['host']; 
    188         $this->user = $data['user']; 
    189         $this->pass = $pass; 
    190         $this->port = $port; 
    191         $this->ssl  = $use_ssl; 
     165        $config = array( 
     166            'host'     => $data['host'], 
     167            'user'     => $data['user'], 
     168            'password' => $pass, 
     169            'port'     => $port, 
     170            'ssl'      => $use_ssl, 
     171        ); 
     172 
     173        $this->options      = array_merge($this->options, $config); 
     174        $this->connect_done = true; 
    192175 
    193176        if ($this->conn->connected()) { 
     
    213196 
    214197    /** 
    215      * Close IMAP connection 
     198     * Close IMAP connection. 
    216199     * Usually done on script shutdown 
    217      * 
    218      * @access public 
    219      */ 
    220     function close() 
     200     */ 
     201    public function close() 
    221202    { 
    222203        $this->conn->closeConnection(); 
    223         if ($this->mcache) 
     204        if ($this->mcache) { 
    224205            $this->mcache->close(); 
    225     } 
    226  
    227  
    228     /** 
    229      * Close IMAP connection and re-connect 
    230      * This is used to avoid some strange socket errors when talking to Courier IMAP 
    231      * 
    232      * @access public 
    233      */ 
    234     function reconnect() 
    235     { 
    236         $this->conn->closeConnection(); 
    237         $connected = $this->connect($this->host, $this->user, $this->pass, $this->port, $this->ssl); 
    238  
    239         // issue SELECT command to restore connection status 
    240         if ($connected && strlen($this->mailbox)) 
    241             $this->conn->select($this->mailbox); 
     206        } 
     207    } 
     208 
     209 
     210    /** 
     211     * Check connection state, connect if not connected. 
     212     */ 
     213    public function check_connection() 
     214    { 
     215        // Establish connection if it wasn't done yet 
     216        if (!$this->connect_done && !empty($this->options['user'])) { 
     217            return $this->connect( 
     218                $this->options['host'], 
     219                $this->options['user'], 
     220                $this->options['password'], 
     221                $this->options['port'], 
     222                $this->options['ssl'] 
     223            ); 
     224        } 
     225 
     226        return $this->is_connected(); 
     227    } 
     228 
     229 
     230    /** 
     231     * Checks IMAP connection. 
     232     * 
     233     * @return boolean  TRUE on success, FALSE on failure 
     234     */ 
     235    public function is_connected() 
     236    { 
     237        return $this->conn->connected(); 
    242238    } 
    243239 
     
    248244     * @return int Error code 
    249245     */ 
    250     function get_error_code() 
     246    public function get_error_code() 
    251247    { 
    252248        return $this->conn->errornum; 
     
    255251 
    256252    /** 
    257      * Returns message of last error 
    258      * 
    259      * @return string Error message 
    260      */ 
    261     function get_error_str() 
     253     * Returns text of last error 
     254     * 
     255     * @return string Error string 
     256     */ 
     257    public function get_error_str() 
    262258    { 
    263259        return $this->conn->error; 
     
    270266     * @return int Response code 
    271267     */ 
    272     function get_response_code() 
     268    public function get_response_code() 
    273269    { 
    274270        switch ($this->conn->resultcode) { 
     
    296292 
    297293    /** 
    298      * Returns last command response 
    299      * 
    300      * @return string Response 
    301      */ 
    302     function get_response_str() 
    303     { 
    304         return $this->conn->result; 
    305     } 
    306  
    307  
    308     /** 
    309      * Set options to be used in rcube_imap_generic::connect() 
    310      * 
    311      * @param array $opt Options array 
    312      */ 
    313     function set_options($opt) 
    314     { 
    315         $this->options = array_merge($this->options, (array)$opt); 
    316     } 
    317  
    318  
    319     /** 
    320294     * Activate/deactivate debug mode 
    321295     * 
    322296     * @param boolean $dbg True if IMAP conversation should be logged 
    323      * @access public 
    324      */ 
    325     function set_debug($dbg = true) 
     297     */ 
     298    public function set_debug($dbg = true) 
    326299    { 
    327300        $this->options['debug'] = $dbg; 
     
    331304 
    332305    /** 
    333      * Set default message charset 
    334      * 
    335      * This will be used for message decoding if a charset specification is not available 
    336      * 
    337      * @param  string $cs Charset string 
    338      * @access public 
    339      */ 
    340     function set_charset($cs) 
    341     { 
    342         $this->default_charset = $cs; 
    343     } 
    344  
    345  
    346     /** 
    347      * This list of folders will be listed above all other folders 
    348      * 
    349      * @param  array $arr Indexed list of folder names 
    350      * @access public 
    351      */ 
    352     function set_default_mailboxes($arr) 
    353     { 
    354         if (is_array($arr)) { 
    355             $this->default_folders = $arr; 
    356  
    357             // add inbox if not included 
    358             if (!in_array('INBOX', $this->default_folders)) 
    359                 array_unshift($this->default_folders, 'INBOX'); 
    360         } 
    361     } 
    362  
    363  
    364     /** 
    365      * Set internal mailbox reference. 
    366      * 
    367      * All operations will be perfomed on this mailbox/folder 
    368      * 
    369      * @param  string $mailbox Mailbox/Folder name 
    370      * @access public 
    371      */ 
    372     function set_mailbox($mailbox) 
    373     { 
    374         if ($this->mailbox == $mailbox) 
     306     * Set internal folder reference. 
     307     * All operations will be perfomed on this folder. 
     308     * 
     309     * @param  string $folder Folder name 
     310     */ 
     311    public function set_folder($folder) 
     312    { 
     313        if ($this->folder == $folder) { 
    375314            return; 
    376  
    377         $this->mailbox = $mailbox; 
    378  
    379         // clear messagecount cache for this mailbox 
    380         $this->_clear_messagecount($mailbox); 
    381     } 
    382  
    383  
    384     /** 
    385      * Set internal list page 
    386      * 
    387      * @param  number $page Page number to list 
    388      * @access public 
    389      */ 
    390     function set_page($page) 
    391     { 
    392         $this->list_page = (int)$page; 
    393     } 
    394  
    395  
    396     /** 
    397      * Set internal page size 
    398      * 
    399      * @param  number $size Number of messages to display on one page 
    400      * @access public 
    401      */ 
    402     function set_pagesize($size) 
    403     { 
    404         $this->page_size = (int)$size; 
     315        } 
     316 
     317        $this->folder = $folder; 
     318 
     319        // clear messagecount cache for this folder 
     320        $this->clear_messagecount($folder); 
    405321    } 
    406322 
     
    416332     *                      4 - true if sorted, bool 
    417333     */ 
    418     function set_search_set($set) 
     334    public function set_search_set($set) 
    419335    { 
    420336        $set = (array)$set; 
     
    434350     * @return array Search set 
    435351     */ 
    436     function get_search_set() 
    437     { 
     352    public function get_search_set() 
     353    { 
     354        if (empty($this->search_set)) { 
     355            return null; 
     356        } 
     357 
    438358        return array( 
    439359            $this->search_string, 
     
    447367 
    448368    /** 
    449      * Returns the currently used mailbox name 
    450      * 
    451      * @return  string Name of the mailbox/folder 
    452      * @access  public 
    453      */ 
    454     function get_mailbox_name() 
    455     { 
    456         return $this->mailbox; 
    457     } 
    458  
    459  
    460     /** 
    461      * Returns the IMAP server's capability 
     369     * Returns the IMAP server's capability. 
    462370     * 
    463371     * @param   string  $cap Capability name 
     372     * 
    464373     * @return  mixed   Capability value or TRUE if supported, FALSE if not 
    465      * @access  public 
    466      */ 
    467     function get_capability($cap) 
    468     { 
    469         return $this->conn->getCapability(strtoupper($cap)); 
    470     } 
    471  
    472  
    473     /** 
    474      * Sets threading flag to the best supported THREAD algorithm 
    475      * 
    476      * @param  boolean  $enable TRUE to enable and FALSE 
    477      * @return string   Algorithm or false if THREAD is not supported 
    478      * @access public 
    479      */ 
    480     function set_threading($enable=false) 
    481     { 
    482         $this->threading = false; 
    483  
    484         if ($enable && ($caps = $this->get_capability('THREAD'))) { 
    485             if (in_array('REFS', $caps)) 
    486                 $this->threading = 'REFS'; 
    487             else if (in_array('REFERENCES', $caps)) 
    488                 $this->threading = 'REFERENCES'; 
    489             else if (in_array('ORDEREDSUBJECT', $caps)) 
    490                 $this->threading = 'ORDEREDSUBJECT'; 
    491         } 
    492  
    493         return $this->threading; 
    494     } 
    495  
    496  
    497     /** 
    498      * Checks the PERMANENTFLAGS capability of the current mailbox 
     374     */ 
     375    public function get_capability($cap) 
     376    { 
     377        $cap      = strtoupper($cap); 
     378        $sess_key = "STORAGE_$cap"; 
     379 
     380        if (!isset($_SESSION[$sess_key])) { 
     381            if (!$this->check_connection()) { 
     382                return false; 
     383            } 
     384 
     385            $_SESSION[$sess_key] = $this->conn->getCapability($cap); 
     386        } 
     387 
     388        return $_SESSION[$sess_key]; 
     389    } 
     390 
     391 
     392    /** 
     393     * Checks the PERMANENTFLAGS capability of the current folder 
    499394     * and returns true if the given flag is supported by the IMAP server 
    500395     * 
    501396     * @param   string  $flag Permanentflag name 
     397     * 
    502398     * @return  boolean True if this flag is supported 
    503      * @access  public 
    504      */ 
    505     function check_permflag($flag) 
     399     */ 
     400    public function check_permflag($flag) 
    506401    { 
    507402        $flag = strtoupper($flag); 
    508403        $imap_flag = $this->conn->flags[$flag]; 
     404 
     405        if ($this->folder !== null) { 
     406            $this->check_connection(); 
     407        } 
     408        // @TODO: cache permanent flags (?) 
     409 
    509410        return (in_array_nocase($imap_flag, $this->conn->data['PERMANENTFLAGS'])); 
    510411    } 
     
    517418     * @access  public 
    518419     */ 
    519     function get_hierarchy_delimiter() 
     420    public function get_hierarchy_delimiter() 
    520421    { 
    521422        return $this->delimiter; 
     
    529430     * 
    530431     * @return  array  Namespace data 
    531      * @access  public 
    532      */ 
    533     function get_namespace($name=null) 
     432     */ 
     433    public function get_namespace($name = null) 
    534434    { 
    535435        $ns = $this->namespace; 
     
    546446    /** 
    547447     * Sets delimiter and namespaces 
    548      * 
    549      * @access private 
    550      */ 
    551     private function set_env() 
     448     */ 
     449    protected function set_env() 
    552450    { 
    553451        if ($this->delimiter !== null && $this->namespace !== null) { 
     
    561459        $imap_delimiter = $config->get('imap_delimiter'); 
    562460 
    563         if (!$this->conn->connected()) 
     461        if (!$this->check_connection()) { 
    564462            return; 
     463        } 
    565464 
    566465        $ns = $this->conn->getNamespace(); 
     
    615514        } 
    616515 
    617         // Find personal namespace prefix for mod_mailbox() 
     516        // Find personal namespace prefix for mod_folder() 
    618517        // Prefix can be removed when there is only one personal namespace 
    619518        if (is_array($this->namespace['personal']) && count($this->namespace['personal']) == 1) { 
     
    627526 
    628527    /** 
    629      * Get message count for a specific mailbox 
    630      * 
    631      * @param  string  $mailbox Mailbox/folder name 
     528     * Get message count for a specific folder 
     529     * 
     530     * @param  string  $folder  Folder name 
    632531     * @param  string  $mode    Mode for count [ALL|THREADS|UNSEEN|RECENT] 
    633532     * @param  boolean $force   Force reading from server and update cache 
    634533     * @param  boolean $status  Enables storing folder status info (max UID/count), 
    635      *                          required for mailbox_status() 
     534     *                          required for folder_status() 
     535     * 
    636536     * @return int     Number of messages 
    637      * @access public 
    638      */ 
    639     function messagecount($mailbox='', $mode='ALL', $force=false, $status=true) 
    640     { 
    641         if (!strlen($mailbox)) { 
    642             $mailbox = $this->mailbox; 
    643         } 
    644  
    645         return $this->_messagecount($mailbox, $mode, $force, $status); 
    646     } 
    647  
    648  
    649     /** 
    650      * Private method for getting nr of messages 
    651      * 
    652      * @param string  $mailbox Mailbox name 
     537     */ 
     538    public function count($folder='', $mode='ALL', $force=false, $status=true) 
     539    { 
     540        if (!strlen($folder)) { 
     541            $folder = $this->folder; 
     542        } 
     543 
     544        return $this->messagecount($folder, $mode, $force, $status); 
     545    } 
     546 
     547 
     548    /** 
     549     * protected method for getting nr of messages 
     550     * 
     551     * @param string  $folder  Folder name 
    653552     * @param string  $mode    Mode for count [ALL|THREADS|UNSEEN|RECENT] 
    654553     * @param boolean $force   Force reading from server and update cache 
    655554     * @param boolean $status  Enables storing folder status info (max UID/count), 
    656      *                         required for mailbox_status() 
     555     *                         required for folder_status() 
     556     * 
    657557     * @return int Number of messages 
    658      * @access  private 
    659      * @see     rcube_imap::messagecount() 
    660      */ 
    661     private function _messagecount($mailbox, $mode='ALL', $force=false, $status=true) 
     558     * @see rcube_imap::count() 
     559     */ 
     560    protected function messagecount($folder, $mode='ALL', $force=false, $status=true) 
    662561    { 
    663562        $mode = strtoupper($mode); 
    664563 
    665564        // count search set 
    666         if ($this->search_string && $mailbox == $this->mailbox && ($mode == 'ALL' || $mode == 'THREADS') && !$force) { 
    667             if ($mode == 'ALL') 
    668                 return $this->search_set->countMessages(); 
    669             else 
     565        if ($this->search_string && $folder == $this->folder && ($mode == 'ALL' || $mode == 'THREADS') && !$force) { 
     566            if ($mode == 'ALL') { 
     567                return $this->search_set->count_messages(); 
     568            } 
     569            else { 
    670570                return $this->search_set->count(); 
    671         } 
    672  
    673         $a_mailbox_cache = $this->get_cache('messagecount'); 
     571            } 
     572        } 
     573 
     574        $a_folder_cache = $this->get_cache('messagecount'); 
    674575 
    675576        // return cached value 
    676         if (!$force && is_array($a_mailbox_cache[$mailbox]) && isset($a_mailbox_cache[$mailbox][$mode])) 
    677             return $a_mailbox_cache[$mailbox][$mode]; 
    678  
    679         if (!is_array($a_mailbox_cache[$mailbox])) 
    680             $a_mailbox_cache[$mailbox] = array(); 
     577        if (!$force && is_array($a_folder_cache[$folder]) && isset($a_folder_cache[$folder][$mode])) { 
     578            return $a_folder_cache[$folder][$mode]; 
     579        } 
     580 
     581        if (!is_array($a_folder_cache[$folder])) { 
     582            $a_folder_cache[$folder] = array(); 
     583        } 
    681584 
    682585        if ($mode == 'THREADS') { 
    683             $res   = $this->fetch_threads($mailbox, $force); 
     586            $res   = $this->fetch_threads($folder, $force); 
    684587            $count = $res->count(); 
    685588 
    686589            if ($status) { 
    687                 $msg_count = $res->countMessages(); 
    688                 $this->set_folder_stats($mailbox, 'cnt', $msg_count); 
    689                 $this->set_folder_stats($mailbox, 'maxuid', $msg_count ? $this->id2uid($msg_count, $mailbox) : 0); 
    690             } 
     590                $msg_count = $res->count_messages(); 
     591                $this->set_folder_stats($folder, 'cnt', $msg_count); 
     592                $this->set_folder_stats($folder, 'maxuid', $msg_count ? $this->id2uid($msg_count, $folder) : 0); 
     593            } 
     594        } 
     595        // Need connection here 
     596        else if (!$this->check_connection()) { 
     597            return 0; 
    691598        } 
    692599        // RECENT count is fetched a bit different 
    693600        else if ($mode == 'RECENT') { 
    694             $count = $this->conn->countRecent($mailbox); 
     601            $count = $this->conn->countRecent($folder); 
    695602        } 
    696603        // use SEARCH for message counting 
    697         else if ($this->skip_deleted) { 
     604        else if (!empty($this->options['skip_deleted'])) { 
    698605            $search_str = "ALL UNDELETED"; 
    699606            $keys       = array('COUNT'); 
     
    715622            // get message count using (E)SEARCH 
    716623            // not very performant but more precise (using UNDELETED) 
    717             $index = $this->conn->search($mailbox, $search_str, true, $keys); 
     624            $index = $this->conn->search($folder, $search_str, true, $keys); 
    718625            $count = $index->count(); 
    719626 
    720627            if ($mode == 'ALL') { 
    721                 // Cache index data, will be used in message_index_direct() 
     628                // Cache index data, will be used in index_direct() 
    722629                $this->icache['undeleted_idx'] = $index; 
    723630 
    724631                if ($status) { 
    725                     $this->set_folder_stats($mailbox, 'cnt', $count); 
    726                     $this->set_folder_stats($mailbox, 'maxuid', $index->max()); 
     632                    $this->set_folder_stats($folder, 'cnt', $count); 
     633                    $this->set_folder_stats($folder, 'maxuid', $index->max()); 
    727634                } 
    728635            } 
    729636        } 
    730637        else { 
    731             if ($mode == 'UNSEEN') 
    732                 $count = $this->conn->countUnseen($mailbox); 
     638            if ($mode == 'UNSEEN') { 
     639                $count = $this->conn->countUnseen($folder); 
     640            } 
    733641            else { 
    734                 $count = $this->conn->countMessages($mailbox); 
     642                $count = $this->conn->countMessages($folder); 
    735643                if ($status) { 
    736                     $this->set_folder_stats($mailbox,'cnt', $count); 
    737                     $this->set_folder_stats($mailbox, 'maxuid', $count ? $this->id2uid($count, $mailbox) : 0); 
    738                 } 
    739             } 
    740         } 
    741  
    742         $a_mailbox_cache[$mailbox][$mode] = (int)$count; 
     644                    $this->set_folder_stats($folder,'cnt', $count); 
     645                    $this->set_folder_stats($folder, 'maxuid', $count ? $this->id2uid($count, $folder) : 0); 
     646                } 
     647            } 
     648        } 
     649 
     650        $a_folder_cache[$folder][$mode] = (int)$count; 
    743651 
    744652        // write back to cache 
    745         $this->update_cache('messagecount', $a_mailbox_cache); 
     653        $this->update_cache('messagecount', $a_folder_cache); 
    746654 
    747655        return (int)$count; 
     
    751659    /** 
    752660     * Public method for listing headers 
    753      * convert mailbox name with root dir first 
    754      * 
    755      * @param   string   $mailbox    Mailbox/folder name 
     661     * 
     662     * @param   string   $folder     Folder name 
    756663     * @param   int      $page       Current page to list 
    757664     * @param   string   $sort_field Header field to sort by 
     
    760667     * 
    761668     * @return  array    Indexed array with message header objects 
    762      * @access  public 
    763      */ 
    764     public function list_headers($mailbox='', $page=NULL, $sort_field=NULL, $sort_order=NULL, $slice=0) 
    765     { 
    766         if (!strlen($mailbox)) { 
    767             $mailbox = $this->mailbox; 
    768         } 
    769  
    770         return $this->_list_headers($mailbox, $page, $sort_field, $sort_order, $slice); 
    771     } 
    772  
    773  
    774     /** 
    775      * Private method for listing message headers 
    776      * 
    777      * @param   string   $mailbox    Mailbox name 
     669     */ 
     670    public function list_messages($folder='', $page=NULL, $sort_field=NULL, $sort_order=NULL, $slice=0) 
     671    { 
     672        if (!strlen($folder)) { 
     673            $folder = $this->folder; 
     674        } 
     675 
     676        return $this->_list_messages($folder, $page, $sort_field, $sort_order, $slice); 
     677    } 
     678 
     679 
     680    /** 
     681     * protected method for listing message headers 
     682     * 
     683     * @param   string   $folder     Folder name 
    778684     * @param   int      $page       Current page to list 
    779685     * @param   string   $sort_field Header field to sort by 
     
    782688     * 
    783689     * @return  array    Indexed array with message header objects 
    784      * @see     rcube_imap::list_headers 
    785      */ 
    786     private function _list_headers($mailbox='', $page=NULL, $sort_field=NULL, $sort_order=NULL, $slice=0) 
    787     { 
    788         if (!strlen($mailbox)) { 
     690     * @see     rcube_imap::list_messages 
     691     */ 
     692    protected function _list_messages($folder='', $page=NULL, $sort_field=NULL, $sort_order=NULL, $slice=0) 
     693    { 
     694        if (!strlen($folder)) { 
    789695            return array(); 
    790696        } 
     
    794700 
    795701        // use saved message set 
    796         if ($this->search_string && $mailbox == $this->mailbox) { 
    797             return $this->_list_header_set($mailbox, $page, $slice); 
     702        if ($this->search_string && $folder == $this->folder) { 
     703            return $this->list_search_messages($folder, $page, $slice); 
    798704        } 
    799705 
    800706        if ($this->threading) { 
    801             return $this->_list_thread_headers($mailbox, $page, $slice); 
     707            return $this->list_thread_messages($folder, $page, $slice); 
    802708        } 
    803709 
    804710        // get UIDs of all messages in the folder, sorted 
    805         $index = $this->message_index($mailbox, $this->sort_field, $this->sort_order); 
    806  
    807         if ($index->isEmpty()) { 
     711        $index = $this->index($folder, $this->sort_field, $this->sort_order); 
     712 
     713        if ($index->is_empty()) { 
    808714            return array(); 
    809715        } 
     
    814720        $index->slice($from, $to - $from); 
    815721 
    816         if ($slice) 
     722        if ($slice) { 
    817723            $index->slice(-$slice, $slice); 
     724        } 
    818725 
    819726        // fetch reqested messages headers 
    820727        $a_index = $index->get(); 
    821         $a_msg_headers = $this->fetch_headers($mailbox, $a_index); 
     728        $a_msg_headers = $this->fetch_headers($folder, $a_index); 
    822729 
    823730        return array_values($a_msg_headers); 
     
    826733 
    827734    /** 
    828      * Private method for listing message headers using threads 
    829      * 
    830      * @param   string   $mailbox    Mailbox/folder name 
     735     * protected method for listing message headers using threads 
     736     * 
     737     * @param   string   $folder     Folder name 
    831738     * @param   int      $page       Current page to list 
    832739     * @param   int      $slice      Number of slice items to extract from result array 
    833740     * 
    834741     * @return  array    Indexed array with message header objects 
    835      * @see     rcube_imap::list_headers 
    836      */ 
    837     private function _list_thread_headers($mailbox, $page, $slice=0) 
     742     * @see     rcube_imap::list_messages 
     743     */ 
     744    protected function list_thread_messages($folder, $page, $slice=0) 
    838745    { 
    839746        // get all threads (not sorted) 
    840         if ($mcache = $this->get_mcache_engine()) 
    841             $threads = $mcache->get_thread($mailbox); 
    842         else 
    843             $threads = $this->fetch_threads($mailbox); 
    844  
    845         return $this->_fetch_thread_headers($mailbox, $threads, $page, $slice); 
    846     } 
    847  
     747        if ($mcache = $this->get_mcache_engine()) { 
     748            $threads = $mcache->get_thread($folder); 
     749        } 
     750        else { 
     751            $threads = $this->fetch_threads($folder); 
     752        } 
     753 
     754        return $this->fetch_thread_headers($folder, $threads, $page, $slice); 
     755    } 
    848756 
    849757    /** 
    850758     * Method for fetching threads data 
    851759     * 
    852      * @param  string $mailbox  Folder name 
    853      * @param  bool   $force    Use IMAP server, no cache 
     760     * @param  string $folder  Folder name 
     761     * @param  bool   $force   Use IMAP server, no cache 
    854762     * 
    855763     * @return rcube_imap_thread Thread data object 
    856764     */ 
    857     function fetch_threads($mailbox, $force = false) 
     765    function fetch_threads($folder, $force = false) 
    858766    { 
    859767        if (!$force && ($mcache = $this->get_mcache_engine())) { 
    860768            // don't store in self's internal cache, cache has it's own internal cache 
    861             return $mcache->get_thread($mailbox); 
     769            return $mcache->get_thread($folder); 
    862770        } 
    863771 
    864772        if (empty($this->icache['threads'])) { 
     773            if (!$this->check_connection()) { 
     774                return new rcube_result_thread(); 
     775            } 
     776 
    865777            // get all threads 
    866             $result = $this->conn->thread($mailbox, $this->threading, 
    867                 $this->skip_deleted ? 'UNDELETED' : '', true); 
     778            $result = $this->conn->thread($folder, $this->threading, 
     779                $this->options['skip_deleted'] ? 'UNDELETED' : '', true); 
    868780 
    869781            // add to internal (fast) cache 
     
    876788 
    877789    /** 
    878      * Private method for fetching threaded messages headers 
    879      * 
    880      * @param string              $mailbox    Mailbox name 
     790     * protected method for fetching threaded messages headers 
     791     * 
     792     * @param string              $folder     Folder name 
    881793     * @param rcube_result_thread $threads    Threads data object 
    882794     * @param int                 $page       List page number 
     
    884796     * 
    885797     * @return array  Messages headers 
    886      * @access  private 
    887      */ 
    888     private function _fetch_thread_headers($mailbox, $threads, $page, $slice=0) 
     798     */ 
     799    protected function fetch_thread_headers($folder, $threads, $page, $slice=0) 
    889800    { 
    890801        // Sort thread structure 
     
    896807        $threads->slice($from, $to - $from); 
    897808 
    898         if ($slice) 
     809        if ($slice) { 
    899810            $threads->slice(-$slice, $slice); 
     811        } 
    900812 
    901813        // Get UIDs of all messages in all threads 
     
    903815 
    904816        // fetch reqested headers from server 
    905         $a_msg_headers = $this->fetch_headers($mailbox, $a_index); 
     817        $a_msg_headers = $this->fetch_headers($folder, $a_index); 
    906818 
    907819        unset($a_index); 
    908820 
    909821        // Set depth, has_children and unread_children fields in headers 
    910         $this->_set_thread_flags($a_msg_headers, $threads); 
     822        $this->set_thread_flags($a_msg_headers, $threads); 
    911823 
    912824        return array_values($a_msg_headers); 
     
    915827 
    916828    /** 
    917      * Private method for setting threaded messages flags: 
     829     * protected method for setting threaded messages flags: 
    918830     * depth, has_children and unread_children 
    919831     * 
     
    922834     * 
    923835     * @return array Message headers array indexed by message UID 
    924      * @access private 
    925      */ 
    926     private function _set_thread_flags(&$headers, $threads) 
     836     */ 
     837    protected function set_thread_flags(&$headers, $threads) 
    927838    { 
    928839        $parents = array(); 
    929840 
    930         list ($msg_depth, $msg_children) = $threads->getThreadData(); 
     841        list ($msg_depth, $msg_children) = $threads->get_thread_data(); 
    931842 
    932843        foreach ($headers as $uid => $header) { 
     
    948859 
    949860    /** 
    950      * Private method for listing a set of message headers (search results) 
    951      * 
    952      * @param   string   $mailbox  Mailbox/folder name 
     861     * protected method for listing a set of message headers (search results) 
     862     * 
     863     * @param   string   $folder   Folder name 
    953864     * @param   int      $page     Current page to list 
    954865     * @param   int      $slice    Number of slice items to extract from result array 
    955866     * 
    956867     * @return  array    Indexed array with message header objects 
    957      * @access  private 
    958      */ 
    959     private function _list_header_set($mailbox, $page, $slice=0) 
    960     { 
    961         if (!strlen($mailbox) || empty($this->search_set) || $this->search_set->isEmpty()) { 
     868     */ 
     869    protected function list_search_messages($folder, $page, $slice=0) 
     870    { 
     871        if (!strlen($folder) || empty($this->search_set) || $this->search_set->is_empty()) { 
    962872            return array(); 
    963873        } 
     
    965875        // use saved messages from searching 
    966876        if ($this->threading) { 
    967             return $this->_list_thread_header_set($mailbox, $page, $slice); 
     877            return $this->list_search_thread_messages($folder, $page, $slice); 
    968878        } 
    969879 
     
    978888 
    979889        // return empty array if no messages found 
    980         if ($index->isEmpty()) 
     890        if ($index->is_empty()) { 
    981891            return array(); 
     892        } 
    982893 
    983894        // quickest method (default sorting) 
     
    995906 
    996907                // return empty array if no messages found 
    997                 if ($index->isEmpty()) 
     908                if ($index->is_empty()) { 
    998909                    return array(); 
     910                } 
    999911            } 
    1000912        } 
    1001913 
    1002914        if ($got_index) { 
    1003             if ($this->sort_order != $index->getParameters('ORDER')) { 
     915            if ($this->sort_order != $index->get_parameters('ORDER')) { 
    1004916                $index->revert(); 
    1005917            } 
     
    1008920            $index->slice($from, $to-$from); 
    1009921 
    1010             if ($slice) 
     922            if ($slice) { 
    1011923                $index->slice(-$slice, $slice); 
     924            } 
    1012925 
    1013926            // fetch headers 
    1014927            $a_index       = $index->get(); 
    1015             $a_msg_headers = $this->fetch_headers($mailbox, $a_index); 
     928            $a_msg_headers = $this->fetch_headers($folder, $a_index); 
    1016929 
    1017930            return array_values($a_msg_headers); 
     
    1024937        if (($cnt > 300 && $cnt > $this->page_size) || !$this->sort_field) { 
    1025938            // use memory less expensive (and quick) method for big result set 
    1026             $index = clone $this->message_index('', $this->sort_field, $this->sort_order); 
     939            $index = clone $this->index('', $this->sort_field, $this->sort_order); 
    1027940            // get messages uids for one page... 
    1028941            $index->slice($start_msg, min($cnt-$from, $this->page_size)); 
    1029942 
    1030             if ($slice) 
     943            if ($slice) { 
    1031944                $index->slice(-$slice, $slice); 
     945            } 
    1032946 
    1033947            // ...and fetch headers 
    1034948            $a_index       = $index->get(); 
    1035             $a_msg_headers = $this->fetch_headers($mailbox, $a_index); 
     949            $a_msg_headers = $this->fetch_headers($folder, $a_index); 
    1036950 
    1037951            return array_values($a_msg_headers); 
     
    1040954            // for small result set we can fetch all messages headers 
    1041955            $a_index       = $index->get(); 
    1042             $a_msg_headers = $this->fetch_headers($mailbox, $a_index, false); 
     956            $a_msg_headers = $this->fetch_headers($folder, $a_index, false); 
    1043957 
    1044958            // return empty array if no messages found 
    1045             if (!is_array($a_msg_headers) || empty($a_msg_headers)) 
     959            if (!is_array($a_msg_headers) || empty($a_msg_headers)) { 
    1046960                return array(); 
     961            } 
     962 
     963            if (!$this->check_connection()) { 
     964                return array(); 
     965            } 
    1047966 
    1048967            // if not already sorted 
     
    1054973                $from, min($cnt-$to, $this->page_size)); 
    1055974 
    1056             if ($slice) 
     975            if ($slice) { 
    1057976                $a_msg_headers = array_slice($a_msg_headers, -$slice, $slice); 
     977            } 
    1058978 
    1059979            return $a_msg_headers; 
     
    1063983 
    1064984    /** 
    1065      * Private method for listing a set of threaded message headers (search results) 
    1066      * 
    1067      * @param   string   $mailbox    Mailbox/folder name 
     985     * protected method for listing a set of threaded message headers (search results) 
     986     * 
     987     * @param   string   $folder     Folder name 
    1068988     * @param   int      $page       Current page to list 
    1069989     * @param   int      $slice      Number of slice items to extract from result array 
    1070990     * 
    1071991     * @return  array    Indexed array with message header objects 
    1072      * @access  private 
    1073      * @see     rcube_imap::list_header_set() 
    1074      */ 
    1075     private function _list_thread_header_set($mailbox, $page, $slice=0) 
     992     * @see rcube_imap::list_search_messages() 
     993     */ 
     994    protected function list_search_thread_messages($folder, $page, $slice=0) 
    1076995    { 
    1077996        // update search_set if previous data was fetched with disabled threading 
    1078997        if (!$this->search_threads) { 
    1079             if ($this->search_set->isEmpty()) 
     998            if ($this->search_set->is_empty()) { 
    1080999                return array(); 
     1000            } 
    10811001            $this->search('', $this->search_string, $this->search_charset, $this->sort_field); 
    10821002        } 
    10831003 
    1084         return $this->_fetch_thread_headers($mailbox, clone $this->search_set, $page, $slice); 
     1004        return $this->fetch_thread_headers($folder, clone $this->search_set, $page, $slice); 
    10851005    } 
    10861006 
     
    10891009     * Fetches messages headers (by UID) 
    10901010     * 
    1091      * @param  string  $mailbox  Mailbox name 
     1011     * @param  string  $folder   Folder name 
    10921012     * @param  array   $msgs     Message UIDs 
    10931013     * @param  bool    $sort     Enables result sorting by $msgs 
     
    10951015     * 
    10961016     * @return array Messages headers indexed by UID 
    1097      * @access private 
    1098      */ 
    1099     function fetch_headers($mailbox, $msgs, $sort = true, $force = false) 
    1100     { 
    1101         if (empty($msgs)) 
     1017     */ 
     1018    function fetch_headers($folder, $msgs, $sort = true, $force = false) 
     1019    { 
     1020        if (empty($msgs)) { 
    11021021            return array(); 
     1022        } 
    11031023 
    11041024        if (!$force && ($mcache = $this->get_mcache_engine())) { 
    1105             $headers = $mcache->get_messages($mailbox, $msgs); 
     1025            $headers = $mcache->get_messages($folder, $msgs); 
     1026        } 
     1027        else if (!$this->check_connection()) { 
     1028            return array(); 
    11061029        } 
    11071030        else { 
    11081031            // fetch reqested headers from server 
    11091032            $headers = $this->conn->fetchHeaders( 
    1110                 $mailbox, $msgs, true, false, $this->get_fetch_headers()); 
    1111         } 
    1112  
    1113         if (empty($headers)) 
     1033                $folder, $msgs, true, false, $this->get_fetch_headers()); 
     1034        } 
     1035 
     1036        if (empty($headers)) { 
    11141037            return array(); 
     1038        } 
    11151039 
    11161040        foreach ($headers as $h) { 
     
    11301054 
    11311055    /** 
    1132      * Returns current status of mailbox 
     1056     * Returns current status of folder 
    11331057     * 
    11341058     * We compare the maximum UID to determine the number of 
    11351059     * new messages because the RECENT flag is not reliable. 
    11361060     * 
    1137      * @param string $mailbox Mailbox/folder name 
     1061     * @param string $folder Folder name 
     1062     * 
    11381063     * @return int   Folder status 
    11391064     */ 
    1140     public function mailbox_status($mailbox = null) 
    1141     { 
    1142         if (!strlen($mailbox)) { 
    1143             $mailbox = $this->mailbox; 
    1144         } 
    1145         $old = $this->get_folder_stats($mailbox); 
     1065    public function folder_status($folder = null) 
     1066    { 
     1067        if (!strlen($folder)) { 
     1068            $folder = $this->folder; 
     1069        } 
     1070        $old = $this->get_folder_stats($folder); 
    11461071 
    11471072        // refresh message count -> will update 
    1148         $this->_messagecount($mailbox, 'ALL', true); 
     1073        $this->messagecount($folder, 'ALL', true); 
    11491074 
    11501075        $result = 0; 
     
    11541079        } 
    11551080 
    1156         $new = $this->get_folder_stats($mailbox); 
     1081        $new = $this->get_folder_stats($folder); 
    11571082 
    11581083        // got new messages 
    1159         if ($new['maxuid'] > $old['maxuid']) 
     1084        if ($new['maxuid'] > $old['maxuid']) { 
    11601085            $result += 1; 
     1086        } 
    11611087        // some messages has been deleted 
    1162         if ($new['cnt'] < $old['cnt']) 
     1088        if ($new['cnt'] < $old['cnt']) { 
    11631089            $result += 2; 
     1090        } 
    11641091 
    11651092        // @TODO: optional checking for messages flags changes (?) 
     
    11741101     * @TODO: move to separate DB table (cache?) 
    11751102     * 
    1176      * @param string $mailbox Mailbox name 
     1103     * @param string $folder  Folder name 
    11771104     * @param string $name    Data name 
    11781105     * @param mixed  $data    Data value 
    11791106     */ 
    1180     private function set_folder_stats($mailbox, $name, $data) 
    1181     { 
    1182         $_SESSION['folders'][$mailbox][$name] = $data; 
     1107    protected function set_folder_stats($folder, $name, $data) 
     1108    { 
     1109        $_SESSION['folders'][$folder][$name] = $data; 
    11831110    } 
    11841111 
     
    11871114     * Gets folder statistic data 
    11881115     * 
    1189      * @param string $mailbox Mailbox name 
     1116     * @param string $folder Folder name 
    11901117     * 
    11911118     * @return array Stats data 
    11921119     */ 
    1193     private function get_folder_stats($mailbox) 
    1194     { 
    1195         if ($_SESSION['folders'][$mailbox]) 
    1196             return (array) $_SESSION['folders'][$mailbox]; 
    1197         else 
    1198             return array(); 
     1120    protected function get_folder_stats($folder) 
     1121    { 
     1122        if ($_SESSION['folders'][$folder]) { 
     1123            return (array) $_SESSION['folders'][$folder]; 
     1124        } 
     1125 
     1126        return array(); 
    11991127    } 
    12001128 
     
    12031131     * Return sorted list of message UIDs 
    12041132     * 
    1205      * @param string $mailbox    Mailbox to get index from 
     1133     * @param string $folder     Folder to get index from 
    12061134     * @param string $sort_field Sort column 
    12071135     * @param string $sort_order Sort order [ASC, DESC] 
     
    12091137     * @return rcube_result_index|rcube_result_thread List of messages (UIDs) 
    12101138     */ 
    1211     public function message_index($mailbox='', $sort_field=NULL, $sort_order=NULL) 
    1212     { 
    1213         if ($this->threading) 
    1214             return $this->thread_index($mailbox, $sort_field, $sort_order); 
     1139    public function index($folder = '', $sort_field = NULL, $sort_order = NULL) 
     1140    { 
     1141        if ($this->threading) { 
     1142            return $this->thread_index($folder, $sort_field, $sort_order); 
     1143        } 
    12151144 
    12161145        $this->set_sort_order($sort_field, $sort_order); 
    12171146 
    1218         if (!strlen($mailbox)) { 
    1219             $mailbox = $this->mailbox; 
     1147        if (!strlen($folder)) { 
     1148            $folder = $this->folder; 
    12201149        } 
    12211150 
     
    12231152        if ($this->search_string) { 
    12241153            if ($this->search_threads) { 
    1225                 $this->search($mailbox, $this->search_string, $this->search_charset, $this->sort_field); 
     1154                $this->search($folder, $this->search_string, $this->search_charset, $this->sort_field); 
    12261155            } 
    12271156 
     
    12291158            if (!$this->sort_field || $this->search_sorted) { 
    12301159                if ($this->sort_field && $this->search_sort_field != $this->sort_field) { 
    1231                     $this->search($mailbox, $this->search_string, $this->search_charset, $this->sort_field); 
     1160                    $this->search($folder, $this->search_string, $this->search_charset, $this->sort_field); 
    12321161                } 
    12331162                $index = $this->search_set; 
    12341163            } 
     1164            else if (!$this->check_connection()) { 
     1165                return new rcube_result_index(); 
     1166            } 
    12351167            else { 
    1236                 $index = $this->conn->index($mailbox, $this->search_set->get(), 
    1237                     $this->sort_field, $this->skip_deleted, true, true); 
    1238             } 
    1239  
    1240             if ($this->sort_order != $index->getParameters('ORDER')) { 
     1168                $index = $this->conn->index($folder, $this->search_set->get(), 
     1169                    $this->sort_field, $this->options['skip_deleted'], true, true); 
     1170            } 
     1171 
     1172            if ($this->sort_order != $index->get_parameters('ORDER')) { 
    12411173                $index->revert(); 
    12421174            } 
     
    12471179        // check local cache 
    12481180        if ($mcache = $this->get_mcache_engine()) { 
    1249             $index = $mcache->get_index($mailbox, $this->sort_field, $this->sort_order); 
     1181            $index = $mcache->get_index($folder, $this->sort_field, $this->sort_order); 
    12501182        } 
    12511183        // fetch from IMAP server 
    12521184        else { 
    1253             $index = $this->message_index_direct( 
    1254                 $mailbox, $this->sort_field, $this->sort_order); 
     1185            $index = $this->index_direct( 
     1186                $folder, $this->sort_field, $this->sort_order); 
    12551187        } 
    12561188 
     
    12631195     * Doesn't uses cache by default. 
    12641196     * 
    1265      * @param string $mailbox    Mailbox to get index from 
     1197     * @param string $folder     Folder to get index from 
    12661198     * @param string $sort_field Sort column 
    12671199     * @param string $sort_order Sort order [ASC, DESC] 
     
    12701202     * @return rcube_result_index Sorted list of message UIDs 
    12711203     */ 
    1272     public function message_index_direct($mailbox, $sort_field = null, $sort_order = null, $skip_cache = true) 
     1204    public function index_direct($folder, $sort_field = null, $sort_order = null, $skip_cache = true) 
    12731205    { 
    12741206        if (!$skip_cache && ($mcache = $this->get_mcache_engine())) { 
    1275             $index = $mcache->get_index($mailbox, $sort_field, $sort_order); 
     1207            $index = $mcache->get_index($folder, $sort_field, $sort_order); 
    12761208        } 
    12771209        // use message index sort as default sorting 
    12781210        else if (!$sort_field) { 
    1279             if ($this->skip_deleted && !empty($this->icache['undeleted_idx']) 
    1280                 && $this->icache['undeleted_idx']->getParameters('MAILBOX') == $mailbox 
     1211            if ($this->options['skip_deleted'] && !empty($this->icache['undeleted_idx']) 
     1212                && $this->icache['undeleted_idx']->get_parameters('MAILBOX') == $folder 
    12811213            ) { 
    12821214                $index = $this->icache['undeleted_idx']; 
    12831215            } 
     1216            else if (!$this->check_connection()) { 
     1217                return new rcube_result_index(); 
     1218            } 
    12841219            else { 
    1285                 $index = $this->conn->search($mailbox, 
    1286                     'ALL' .($this->skip_deleted ? ' UNDELETED' : ''), true); 
    1287             } 
     1220                $index = $this->conn->search($folder, 
     1221                    'ALL' .($this->options['skip_deleted'] ? ' UNDELETED' : ''), true); 
     1222            } 
     1223        } 
     1224        else if (!$this->check_connection()) { 
     1225            return new rcube_result_index(); 
    12881226        } 
    12891227        // fetch complete message index 
    12901228        else { 
    12911229            if ($this->get_capability('SORT')) { 
    1292                 $index = $this->conn->sort($mailbox, $sort_field, 
    1293                     $this->skip_deleted ? 'UNDELETED' : '', true); 
    1294             } 
    1295  
    1296             if (empty($index) || $index->isError()) { 
    1297                 $index = $this->conn->index($mailbox, "1:*", $sort_field, 
    1298                     $this->skip_deleted, false, true); 
    1299             } 
    1300         } 
    1301  
    1302         if ($sort_order != $index->getParameters('ORDER')) { 
     1230                $index = $this->conn->sort($folder, $sort_field, 
     1231                    $this->options['skip_deleted'] ? 'UNDELETED' : '', true); 
     1232            } 
     1233 
     1234            if (empty($index) || $index->is_error()) { 
     1235                $index = $this->conn->index($folder, "1:*", $sort_field, 
     1236                    $this->options['skip_deleted'], false, true); 
     1237            } 
     1238        } 
     1239 
     1240        if ($sort_order != $index->get_parameters('ORDER')) { 
    13031241            $index->revert(); 
    13041242        } 
     
    13111249     * Return index of threaded message UIDs 
    13121250     * 
    1313      * @param string $mailbox    Mailbox to get index from 
     1251     * @param string $folder     Folder to get index from 
    13141252     * @param string $sort_field Sort column 
    13151253     * @param string $sort_order Sort order [ASC, DESC] 
     
    13171255     * @return rcube_result_thread Message UIDs 
    13181256     */ 
    1319     function thread_index($mailbox='', $sort_field=NULL, $sort_order=NULL) 
    1320     { 
    1321         if (!strlen($mailbox)) { 
    1322             $mailbox = $this->mailbox; 
     1257    public function thread_index($folder='', $sort_field=NULL, $sort_order=NULL) 
     1258    { 
     1259        if (!strlen($folder)) { 
     1260            $folder = $this->folder; 
    13231261        } 
    13241262 
    13251263        // we have a saved search result, get index from there 
    1326         if ($this->search_string && $this->search_threads && $mailbox == $this->mailbox) { 
     1264        if ($this->search_string && $this->search_threads && $folder == $this->folder) { 
    13271265            $threads = $this->search_set; 
    13281266        } 
    13291267        else { 
    13301268            // get all threads (default sort order) 
    1331             $threads = $this->fetch_threads($mailbox); 
     1269            $threads = $this->fetch_threads($folder); 
    13321270        } 
    13331271 
     
    13441282     * @param rcube_result_thread $threads  Threads result set 
    13451283     */ 
    1346     private function sort_threads($threads) 
    1347     { 
    1348         if ($threads->isEmpty()) { 
     1284    protected function sort_threads($threads) 
     1285    { 
     1286        if ($threads->is_empty()) { 
    13491287            return; 
    13501288        } 
     
    13551293 
    13561294        if ($this->sort_field && ($this->sort_field != 'date' || $this->get_capability('THREAD') != 'REFS')) { 
    1357             $index = $this->message_index_direct($this->mailbox, $this->sort_field, $this->sort_order, false); 
    1358  
    1359             if (!$index->isEmpty()) { 
     1295            $index = $this->index_direct($this->folder, $this->sort_field, $this->sort_order, false); 
     1296 
     1297            if (!$index->is_empty()) { 
    13601298                $threads->sort($index); 
    13611299            } 
    13621300        } 
    13631301        else { 
    1364             if ($this->sort_order != $threads->getParameters('ORDER')) { 
     1302            if ($this->sort_order != $threads->get_parameters('ORDER')) { 
    13651303                $threads->revert(); 
    13661304            } 
     
    13721310     * Invoke search request to IMAP server 
    13731311     * 
    1374      * @param  string  $mailbox    Mailbox name to search in 
     1312     * @param  string  $folder     Folder name to search in 
    13751313     * @param  string  $str        Search criteria 
    13761314     * @param  string  $charset    Search charset 
    13771315     * @param  string  $sort_field Header field to sort by 
    1378      * @access public 
     1316     * 
    13791317     * @todo: Search criteria should be provided in non-IMAP format, eg. array 
    13801318     */ 
    1381     function search($mailbox='', $str='ALL', $charset=NULL, $sort_field=NULL) 
    1382     { 
    1383         if (!$str) 
     1319    public function search($folder='', $str='ALL', $charset=NULL, $sort_field=NULL) 
     1320    { 
     1321        if (!$str) { 
    13841322            $str = 'ALL'; 
     1323        } 
     1324 
     1325        if (!strlen($folder)) { 
     1326            $folder = $this->folder; 
     1327        } 
     1328 
     1329        $results = $this->search_index($folder, $str, $charset, $sort_field); 
     1330 
     1331        $this->set_search_set(array($str, $results, $charset, $sort_field, 
     1332            $this->threading || $this->search_sorted ? true : false)); 
     1333    } 
     1334 
     1335 
     1336    /** 
     1337     * Direct (real and simple) SEARCH request (without result sorting and caching). 
     1338     * 
     1339     * @param  string  $mailbox Mailbox name to search in 
     1340     * @param  string  $str     Search string 
     1341     * 
     1342     * @return rcube_result_index  Search result (UIDs) 
     1343     */ 
     1344    public function search_once($mailbox = null, $str = 'ALL') 
     1345    { 
     1346        if (!$str) { 
     1347            return 'ALL'; 
     1348        } 
    13851349 
    13861350        if (!strlen($mailbox)) { 
     
    13881352        } 
    13891353 
    1390         $results = $this->_search_index($mailbox, $str, $charset, $sort_field); 
    1391  
    1392         $this->set_search_set(array($str, $results, $charset, $sort_field, 
    1393             $this->threading || $this->search_sorted ? true : false)); 
    1394     } 
    1395  
    1396  
    1397     /** 
    1398      * Private search method 
    1399      * 
    1400      * @param string $mailbox    Mailbox name 
     1354        if (!$this->check_connection()) { 
     1355            return new rcube_result_index(); 
     1356        } 
     1357 
     1358        $index = $this->conn->search($mailbox, $str, true); 
     1359 
     1360        return $index; 
     1361    } 
     1362 
     1363 
     1364    /** 
     1365     * protected search method 
     1366     * 
     1367     * @param string $folder     Folder name 
    14011368     * @param string $criteria   Search criteria 
    14021369     * @param string $charset    Charset 
     
    14061373     * @see rcube_imap::search() 
    14071374     */ 
    1408     private function _search_index($mailbox, $criteria='ALL', $charset=NULL, $sort_field=NULL) 
     1375    protected function search_index($folder, $criteria='ALL', $charset=NULL, $sort_field=NULL) 
    14091376    { 
    14101377        $orig_criteria = $criteria; 
    14111378 
    1412         if ($this->skip_deleted && !preg_match('/UNDELETED/', $criteria)) 
     1379        if (!$this->check_connection()) { 
     1380            if ($this->threading) { 
     1381                return new rcube_result_thread(); 
     1382            } 
     1383            else { 
     1384                return new rcube_result_index(); 
     1385            } 
     1386        } 
     1387 
     1388        if ($this->options['skip_deleted'] && !preg_match('/UNDELETED/', $criteria)) { 
    14131389            $criteria = 'UNDELETED '.$criteria; 
     1390        } 
    14141391 
    14151392        if ($this->threading) { 
    1416             $threads = $this->conn->thread($mailbox, $this->threading, $criteria, true, $charset); 
     1393            $threads = $this->conn->thread($folder, $this->threading, $criteria, true, $charset); 
    14171394 
    14181395            // Error, try with US-ASCII (RFC5256: SORT/THREAD must support US-ASCII and UTF-8, 
    14191396            // but I've seen that Courier doesn't support UTF-8) 
    1420             if ($threads->isError() && $charset && $charset != 'US-ASCII') 
    1421                 $threads = $this->conn->thread($mailbox, $this->threading, 
     1397            if ($threads->is_error() && $charset && $charset != 'US-ASCII') { 
     1398                $threads = $this->conn->thread($folder, $this->threading, 
    14221399                    $this->convert_criteria($criteria, $charset), true, 'US-ASCII'); 
     1400            } 
    14231401 
    14241402            return $threads; 
     
    14271405        if ($sort_field && $this->get_capability('SORT')) { 
    14281406            $charset  = $charset ? $charset : $this->default_charset; 
    1429             $messages = $this->conn->sort($mailbox, $sort_field, $criteria, true, $charset); 
     1407            $messages = $this->conn->sort($folder, $sort_field, $criteria, true, $charset); 
    14301408 
    14311409            // Error, try with US-ASCII (RFC5256: SORT/THREAD must support US-ASCII and UTF-8, 
    14321410            // but I've seen Courier with disabled UTF-8 support) 
    1433             if ($messages->isError() && $charset && $charset != 'US-ASCII') 
    1434                 $messages = $this->conn->sort($mailbox, $sort_field, 
     1411            if ($messages->is_error() && $charset && $charset != 'US-ASCII') { 
     1412                $messages = $this->conn->sort($folder, $sort_field, 
    14351413                    $this->convert_criteria($criteria, $charset), true, 'US-ASCII'); 
    1436  
    1437             if (!$messages->isError()) { 
     1414            } 
     1415 
     1416            if (!$messages->is_error()) { 
    14381417                $this->search_sorted = true; 
    14391418                return $messages; 
     
    14411420        } 
    14421421 
    1443         $messages = $this->conn->search($mailbox, 
     1422        $messages = $this->conn->search($folder, 
    14441423            ($charset ? "CHARSET $charset " : '') . $criteria, true); 
    14451424 
    14461425        // Error, try with US-ASCII (some servers may support only US-ASCII) 
    1447         if ($messages->isError() && $charset && $charset != 'US-ASCII') 
    1448             $messages = $this->conn->search($mailbox, 
     1426        if ($messages->is_error() && $charset && $charset != 'US-ASCII') { 
     1427            $messages = $this->conn->search($folder, 
    14491428                $this->convert_criteria($criteria, $charset), true); 
     1429        } 
    14501430 
    14511431        $this->search_sorted = false; 
    14521432 
    14531433        return $messages; 
    1454     } 
    1455  
    1456  
    1457     /** 
    1458      * Direct (real and simple) SEARCH request to IMAP server, 
    1459      * without result sorting and caching 
    1460      * 
    1461      * @param  string  $mailbox Mailbox name to search in 
    1462      * @param  string  $str     Search string 
    1463      * @param  boolean $ret_uid True if UIDs should be returned 
    1464      * 
    1465      * @return rcube_result_index  Search result (UIDs) 
    1466      */ 
    1467     function search_once($mailbox='', $str='ALL') 
    1468     { 
    1469         if (!$str) 
    1470             return 'ALL'; 
    1471  
    1472         if (!strlen($mailbox)) { 
    1473             $mailbox = $this->mailbox; 
    1474         } 
    1475  
    1476         $index = $this->conn->search($mailbox, $str, true); 
    1477  
    1478         return $index; 
    14791434    } 
    14801435 
     
    14861441     * @param  string  $charset      Original charset 
    14871442     * @param  string  $dest_charset Destination charset (default US-ASCII) 
     1443     * 
    14881444     * @return string  Search string 
    1489      * @access private 
    1490      */ 
    1491     private function convert_criteria($str, $charset, $dest_charset='US-ASCII') 
     1445     */ 
     1446    protected function convert_criteria($str, $charset, $dest_charset='US-ASCII') 
    14921447    { 
    14931448        // convert strings to US_ASCII 
     
    14981453                $string = substr($str, $string_offset - 1, $m[0]); 
    14991454                $string = rcube_charset_convert($string, $charset, $dest_charset); 
    1500                 if ($string === false) 
     1455                if ($string === false) { 
    15011456                    continue; 
     1457                } 
    15021458                $res .= substr($str, $last, $m[1] - $last - 1) . rcube_imap_generic::escape($string); 
    15031459                $last = $m[0] + $string_offset - 1; 
    15041460            } 
    1505             if ($last < strlen($str)) 
     1461            if ($last < strlen($str)) { 
    15061462                $res .= substr($str, $last, strlen($str)-$last); 
    1507         } 
    1508         else // strings for conversion not found 
     1463            } 
     1464        } 
     1465        // strings for conversion not found 
     1466        else { 
    15091467            $res = $str; 
     1468        } 
    15101469 
    15111470        return $res; 
     
    15181477     * @return array Current search set 
    15191478     */ 
    1520     function refresh_search() 
     1479    public function refresh_search() 
    15211480    { 
    15221481        if (!empty($this->search_string)) { 
     
    15311490     * Return message headers object of a specific message 
    15321491     * 
    1533      * @param int     $id       Message sequence ID or UID 
    1534      * @param string  $mailbox  Mailbox to read from 
     1492     * @param int     $id       Message UID 
     1493     * @param string  $folder   Folder to read from 
    15351494     * @param bool    $force    True to skip cache 
    15361495     * 
    15371496     * @return rcube_mail_header Message headers 
    15381497     */ 
    1539     function get_headers($uid, $mailbox = null, $force = false) 
    1540     { 
    1541         if (!strlen($mailbox)) { 
    1542             $mailbox = $this->mailbox; 
     1498    public function get_message_headers($uid, $folder = null, $force = false) 
     1499    { 
     1500        if (!strlen($folder)) { 
     1501            $folder = $this->folder; 
    15431502        } 
    15441503 
    15451504        // get cached headers 
    15461505        if (!$force && $uid && ($mcache = $this->get_mcache_engine())) { 
    1547             $headers = $mcache->get_message($mailbox, $uid); 
     1506            $headers = $mcache->get_message($folder, $uid); 
     1507        } 
     1508        else if (!$this->check_connection()) { 
     1509            $headers = false; 
    15481510        } 
    15491511        else { 
    15501512            $headers = $this->conn->fetchHeader( 
    1551                 $mailbox, $uid, true, true, $this->get_fetch_headers()); 
     1513                $folder, $uid, true, true, $this->get_fetch_headers()); 
    15521514        } 
    15531515 
     
    15611523     * 
    15621524     * @param int     $uid      Message UID to fetch 
    1563      * @param string  $mailbox  Mailbox to read from 
     1525     * @param string  $folder   Folder to read from 
    15641526     * 
    15651527     * @return object rcube_mail_header Message data 
    15661528     */ 
    1567     function get_message($uid, $mailbox = null) 
    1568     { 
    1569         if (!strlen($mailbox)) { 
    1570             $mailbox = $this->mailbox; 
     1529    public function get_message($uid, $folder = null) 
     1530    { 
     1531        if (!strlen($folder)) { 
     1532            $folder = $this->folder; 
    15711533        } 
    15721534 
     
    15781540        } 
    15791541 
    1580         $headers = $this->get_headers($uid, $mailbox); 
     1542        $headers = $this->get_message_headers($uid, $folder); 
    15811543 
    15821544        // message doesn't exist? 
    1583         if (empty($headers)) 
     1545        if (empty($headers)) { 
    15841546            return null; 
     1547        } 
    15851548 
    15861549        // structure might be cached 
    1587         if (!empty($headers->structure)) 
     1550        if (!empty($headers->structure)) { 
    15881551            return $headers; 
    1589  
    1590         $this->_msg_uid = $uid; 
     1552        } 
     1553 
     1554        $this->msg_uid = $uid; 
     1555 
     1556        if (!$this->check_connection()) { 
     1557            return $headers; 
     1558        } 
    15911559 
    15921560        if (empty($headers->bodystructure)) { 
    1593             $headers->bodystructure = $this->conn->getStructure($mailbox, $uid, true); 
     1561            $headers->bodystructure = $this->conn->getStructure($folder, $uid, true); 
    15941562        } 
    15951563 
    15961564        $structure = $headers->bodystructure; 
    15971565 
    1598         if (empty($structure)) 
     1566        if (empty($structure)) { 
    15991567            return $headers; 
     1568        } 
    16001569 
    16011570        // set message charset from message headers 
    1602         if ($headers->charset) 
     1571        if ($headers->charset) { 
    16031572            $this->struct_charset = $headers->charset; 
    1604         else 
    1605             $this->struct_charset = $this->_structure_charset($structure); 
     1573        } 
     1574        else { 
     1575            $this->struct_charset = $this->structure_charset($structure); 
     1576        } 
    16061577 
    16071578        $headers->ctype = strtolower($headers->ctype); 
     
    16191590                $structure[1] = $m[2]; 
    16201591            } 
    1621             else 
     1592            else { 
    16221593                return $headers; 
    1623         } 
    1624  
    1625         $struct = $this->_structure_part($structure, 0, '', $headers); 
     1594            } 
     1595        } 
     1596 
     1597        $struct = $this->structure_part($structure, 0, '', $headers); 
    16261598 
    16271599        // don't trust given content-type 
     
    16441616     * @param int    $count 
    16451617     * @param string $parent 
    1646      * @access private 
    1647      */ 
    1648     private function _structure_part($part, $count=0, $parent='', $mime_headers=null) 
     1618     */ 
     1619    protected function structure_part($part, $count=0, $parent='', $mime_headers=null) 
    16491620    { 
    16501621        $struct = new rcube_message_part; 
     
    16791650            // build parts list for headers pre-fetching 
    16801651            for ($i=0; $i<count($part); $i++) { 
    1681                 if (!is_array($part[$i])) 
     1652                if (!is_array($part[$i])) { 
    16821653                    break; 
     1654                } 
    16831655                // fetch message headers if message/rfc822 
    16841656                // or named part (could contain Content-Location header) 
     
    16981670            // headers for parts on all levels 
    16991671            if ($mime_part_headers) { 
    1700                 $mime_part_headers = $this->conn->fetchMIMEHeaders($this->mailbox, 
    1701                     $this->_msg_uid, $mime_part_headers); 
     1672                $mime_part_headers = $this->conn->fetchMIMEHeaders($this->folder, 
     1673                    $this->msg_uid, $mime_part_headers); 
    17021674            } 
    17031675 
    17041676            $struct->parts = array(); 
    17051677            for ($i=0, $count=0; $i<count($part); $i++) { 
    1706                 if (!is_array($part[$i])) 
     1678                if (!is_array($part[$i])) { 
    17071679                    break; 
     1680                } 
    17081681                $tmp_part_id = $struct->mime_id ? $struct->mime_id.'.'.($i+1) : $i+1; 
    1709                 $struct->parts[] = $this->_structure_part($part[$i], ++$count, $struct->mime_id, 
     1682                $struct->parts[] = $this->structure_part($part[$i], ++$count, $struct->mime_id, 
    17101683                    $mime_part_headers[$tmp_part_id]); 
    17111684            } 
     
    17431716        if (is_array($part[2])) { 
    17441717            $struct->ctype_parameters = array(); 
    1745             for ($i=0; $i<count($part[2]); $i+=2) 
     1718            for ($i=0; $i<count($part[2]); $i+=2) { 
    17461719                $struct->ctype_parameters[strtolower($part[2][$i])] = $part[2][$i+1]; 
    1747  
    1748             if (isset($struct->ctype_parameters['charset'])) 
     1720            } 
     1721 
     1722            if (isset($struct->ctype_parameters['charset'])) { 
    17491723                $struct->charset = $struct->ctype_parameters['charset']; 
     1724            } 
    17501725        } 
    17511726 
     
    17621737 
    17631738        // get part size 
    1764         if (!empty($part[6])) 
     1739        if (!empty($part[6])) { 
    17651740            $struct->size = intval($part[6]); 
     1741        } 
    17661742 
    17671743        // read part disposition 
    17681744        $di = 8; 
    1769         if ($struct->ctype_primary == 'text') $di += 1; 
    1770         else if ($struct->mimetype == 'message/rfc822') $di += 3; 
     1745        if ($struct->ctype_primary == 'text') { 
     1746            $di += 1; 
     1747        } 
     1748        else if ($struct->mimetype == 'message/rfc822') { 
     1749            $di += 3; 
     1750        } 
    17711751 
    17721752        if (is_array($part[$di]) && count($part[$di]) == 2) { 
    17731753            $struct->disposition = strtolower($part[$di][0]); 
    17741754 
    1775             if (is_array($part[$di][1])) 
    1776                 for ($n=0; $n<count($part[$di][1]); $n+=2) 
     1755            if (is_array($part[$di][1])) { 
     1756                for ($n=0; $n<count($part[$di][1]); $n+=2) { 
    17771757                    $struct->d_parameters[strtolower($part[$di][1][$n])] = $part[$di][1][$n+1]; 
     1758                } 
     1759            } 
    17781760        } 
    17791761 
     
    17821764            $struct->parts = array(); 
    17831765            for ($i=0, $count=0; $i<count($part[8]); $i++) { 
    1784                 if (!is_array($part[8][$i])) 
     1766                if (!is_array($part[8][$i])) { 
    17851767                    break; 
    1786                 $struct->parts[] = $this->_structure_part($part[8][$i], ++$count, $struct->mime_id); 
     1768                } 
     1769                $struct->parts[] = $this->structure_part($part[8][$i], ++$count, $struct->mime_id); 
    17871770            } 
    17881771        } 
     
    17931776            $struct->headers['content-id'] = $part[3]; 
    17941777 
    1795             if (empty($struct->disposition)) 
     1778            if (empty($struct->disposition)) { 
    17961779                $struct->disposition = 'inline'; 
     1780            } 
    17971781        } 
    17981782 
     
    18011785            if (empty($mime_headers)) { 
    18021786                $mime_headers = $this->conn->fetchPartHeader( 
    1803                     $this->mailbox, $this->_msg_uid, true, $struct->mime_id); 
    1804             } 
    1805  
    1806             if (is_string($mime_headers)) 
     1787                    $this->folder, $this->msg_uid, true, $struct->mime_id); 
     1788            } 
     1789 
     1790            if (is_string($mime_headers)) { 
    18071791                $struct->headers = rcube_mime::parse_headers($mime_headers) + $struct->headers; 
    1808             else if (is_object($mime_headers)) 
     1792            } 
     1793            else if (is_object($mime_headers)) { 
    18091794                $struct->headers = get_object_vars($mime_headers) + $struct->headers; 
     1795            } 
    18101796 
    18111797            // get real content-type of message/rfc822 
    18121798            if ($struct->mimetype == 'message/rfc822') { 
    18131799                // single-part 
    1814                 if (!is_array($part[8][0])) 
     1800                if (!is_array($part[8][0])) { 
    18151801                    $struct->real_mimetype = strtolower($part[8][0] . '/' . $part[8][1]); 
     1802                } 
    18161803                // multi-part 
    18171804                else { 
    1818                     for ($n=0; $n<count($part[8]); $n++) 
    1819                         if (!is_array($part[8][$n])) 
     1805                    for ($n=0; $n<count($part[8]); $n++) { 
     1806                        if (!is_array($part[8][$n])) { 
    18201807                            break; 
     1808                        } 
     1809                    } 
    18211810                    $struct->real_mimetype = 'multipart/' . strtolower($part[8][$n]); 
    18221811                } 
     
    18241813 
    18251814            if ($struct->ctype_primary == 'message' && empty($struct->parts)) { 
    1826                 if (is_array($part[8]) && $di != 8) 
    1827                     $struct->parts[] = $this->_structure_part($part[8], ++$count, $struct->mime_id); 
     1815                if (is_array($part[8]) && $di != 8) { 
     1816                    $struct->parts[] = $this->structure_part($part[8], ++$count, $struct->mime_id); 
     1817                } 
    18281818            } 
    18291819        } 
    18301820 
    18311821        // normalize filename property 
    1832         $this->_set_part_filename($struct, $mime_headers); 
     1822        $this->set_part_filename($struct, $mime_headers); 
    18331823 
    18341824        return $struct; 
     
    18411831     * @param  rcube_message_part $part    Part object 
    18421832     * @param  string             $headers Part's raw headers 
    1843      * @access private 
    1844      */ 
    1845     private function _set_part_filename(&$part, $headers=null) 
    1846     { 
    1847         if (!empty($part->d_parameters['filename'])) 
     1833     */ 
     1834    protected function set_part_filename(&$part, $headers=null) 
     1835    { 
     1836        if (!empty($part->d_parameters['filename'])) { 
    18481837            $filename_mime = $part->d_parameters['filename']; 
    1849         else if (!empty($part->d_parameters['filename*'])) 
     1838        } 
     1839        else if (!empty($part->d_parameters['filename*'])) { 
    18501840            $filename_encoded = $part->d_parameters['filename*']; 
    1851         else if (!empty($part->ctype_parameters['name*'])) 
     1841        } 
     1842        else if (!empty($part->ctype_parameters['name*'])) { 
    18521843            $filename_encoded = $part->ctype_parameters['name*']; 
     1844        } 
    18531845        // RFC2231 value continuations 
    18541846        // TODO: this should be rewrited to support RFC2231 4.1 combinations 
     
    18641856                if (!$headers) { 
    18651857                    $headers = $this->conn->fetchPartHeader( 
    1866                         $this->mailbox, $this->_msg_uid, true, $part->mime_id); 
     1858                        $this->folder, $this->msg_uid, true, $part->mime_id); 
    18671859                } 
    18681860                $filename_mime = ''; 
     
    18831875                if (!$headers) { 
    18841876                    $headers = $this->conn->fetchPartHeader( 
    1885                             $this->mailbox, $this->_msg_uid, true, $part->mime_id); 
     1877                            $this->folder, $this->msg_uid, true, $part->mime_id); 
    18861878                } 
    18871879                $filename_encoded = ''; 
     
    19021894                if (!$headers) { 
    19031895                    $headers = $this->conn->fetchPartHeader( 
    1904                         $this->mailbox, $this->_msg_uid, true, $part->mime_id); 
     1896                        $this->folder, $this->msg_uid, true, $part->mime_id); 
    19051897                } 
    19061898                $filename_mime = ''; 
     
    19211913                if (!$headers) { 
    19221914                    $headers = $this->conn->fetchPartHeader( 
    1923                         $this->mailbox, $this->_msg_uid, true, $part->mime_id); 
     1915                        $this->folder, $this->msg_uid, true, $part->mime_id); 
    19241916                } 
    19251917                $filename_encoded = ''; 
     
    19321924        } 
    19331925        // read 'name' after rfc2231 parameters as it may contains truncated filename (from Thunderbird) 
    1934         else if (!empty($part->ctype_parameters['name'])) 
     1926        else if (!empty($part->ctype_parameters['name'])) { 
    19351927            $filename_mime = $part->ctype_parameters['name']; 
     1928        } 
    19361929        // Content-Disposition 
    1937         else if (!empty($part->headers['content-description'])) 
     1930        else if (!empty($part->headers['content-description'])) { 
    19381931            $filename_mime = $part->headers['content-description']; 
    1939         else 
     1932        } 
     1933        else { 
    19401934            return; 
     1935        } 
    19411936 
    19421937        // decode filename 
    19431938        if (!empty($filename_mime)) { 
    1944             if (!empty($part->charset)) 
     1939            if (!empty($part->charset)) { 
    19451940                $charset = $part->charset; 
    1946             else if (!empty($this->struct_charset)) 
     1941            } 
     1942            else if (!empty($this->struct_charset)) { 
    19471943                $charset = $this->struct_charset; 
    1948             else 
     1944            } 
     1945            else { 
    19491946                $charset = rc_detect_encoding($filename_mime, $this->default_charset); 
     1947            } 
    19501948 
    19511949            $part->filename = rcube_mime::decode_mime_string($filename_mime, $charset); 
     
    19671965     * 
    19681966     * @param  array $structure Message structure 
     1967     * 
    19691968     * @return string Charset name 
    1970      * @access private 
    1971      */ 
    1972     private function _structure_charset($structure) 
     1969     */ 
     1970    protected function structure_charset($structure) 
    19731971    { 
    19741972        while (is_array($structure)) { 
    1975             if (is_array($structure[2]) && $structure[2][0] == 'charset') 
     1973            if (is_array($structure[2]) && $structure[2][0] == 'charset') { 
    19761974                return $structure[2][1]; 
     1975            } 
    19771976            $structure = $structure[0]; 
    19781977        } 
     
    19921991     * @return string Message/part body if not printed 
    19931992     */ 
    1994     function get_message_part($uid, $part=1, $o_part=NULL, $print=NULL, $fp=NULL, $skip_charset_conv=false) 
    1995     { 
     1993    public function get_message_part($uid, $part=1, $o_part=NULL, $print=NULL, $fp=NULL, $skip_charset_conv=false) 
     1994    { 
     1995        if (!$this->check_connection()) { 
     1996            return null; 
     1997        } 
     1998 
    19961999        // get part data if not provided 
    19972000        if (!is_object($o_part)) { 
    1998             $structure = $this->conn->getStructure($this->mailbox, $uid, true); 
     2001            $structure = $this->conn->getStructure($this->folder, $uid, true); 
    19992002            $part_data = rcube_imap_generic::getStructurePartData($structure, $part); 
    20002003 
     
    20072010 
    20082011        if ($o_part && $o_part->size) { 
    2009             $body = $this->conn->handlePartBody($this->mailbox, $uid, true, 
     2012            $body = $this->conn->handlePartBody($this->folder, $uid, true, 
    20102013                $part ? $part : 'TEXT', $o_part->encoding, $print, $fp); 
    20112014        } 
     
    20252028                if (!$o_part->charset || strtoupper($o_part->charset) == 'US-ASCII') { 
    20262029                    // try to extract charset information from HTML meta tag (#1488125) 
    2027                     if ($o_part->ctype_secondary == 'html' && preg_match('/<meta[^>]+charset=([a-z0-9-_]+)/i', $body, $m)) 
     2030                    if ($o_part->ctype_secondary == 'html' && preg_match('/<meta[^>]+charset=([a-z0-9-_]+)/i', $body, $m)) { 
    20282031                        $o_part->charset = strtoupper($m[1]); 
    2029                     else 
     2032                    } 
     2033                    else { 
    20302034                        $o_part->charset = $this->default_charset; 
     2035                    } 
    20312036                } 
    20322037                $body = rcube_charset_convert($body, $o_part->charset); 
     
    20352040 
    20362041        return $body; 
    2037     } 
    2038  
    2039  
    2040     /** 
    2041      * Fetch message body of a specific message from the server 
    2042      * 
    2043      * @param  int    $uid  Message UID 
    2044      * @return string $part Message/part body 
    2045      * @see    rcube_imap::get_message_part() 
    2046      */ 
    2047     function get_body($uid, $part=1) 
    2048     { 
    2049         $headers = $this->get_headers($uid); 
    2050         return rcube_charset_convert($this->get_message_part($uid, $part, NULL), 
    2051             $headers->charset ? $headers->charset : $this->default_charset); 
    20522042    } 
    20532043 
     
    20612051     * @return string Message source string 
    20622052     */ 
    2063     function get_raw_body($uid, $fp=null) 
    2064     { 
    2065         return $this->conn->handlePartBody($this->mailbox, $uid, 
     2053    public function get_raw_body($uid, $fp=null) 
     2054    { 
     2055        if (!$this->check_connection()) { 
     2056            return null; 
     2057        } 
     2058 
     2059        return $this->conn->handlePartBody($this->folder, $uid, 
    20662060            true, null, null, false, $fp); 
    20672061    } 
     
    20722066     * 
    20732067     * @param int $uid  Message UID 
     2068     * 
    20742069     * @return string Message headers string 
    20752070     */ 
    2076     function get_raw_headers($uid) 
    2077     { 
    2078         return $this->conn->fetchPartHeader($this->mailbox, $uid, true); 
     2071    public function get_raw_headers($uid) 
     2072    { 
     2073        if (!$this->check_connection()) { 
     2074            return null; 
     2075        } 
     2076 
     2077        return $this->conn->fetchPartHeader($this->folder, $uid, true); 
    20792078    } 
    20802079 
     
    20822081    /** 
    20832082     * Sends the whole message source to stdout 
    2084      * 
    2085      * @param int $uid Message UID 
    2086      */ 
    2087     function print_raw_body($uid) 
    2088     { 
    2089         $this->conn->handlePartBody($this->mailbox, $uid, true, NULL, NULL, true); 
     2083     */ 
     2084    public function print_raw_body($uid) 
     2085    { 
     2086        if (!$this->check_connection()) { 
     2087            return; 
     2088        } 
     2089 
     2090        $this->conn->handlePartBody($this->folder, $uid, true, NULL, NULL, true); 
    20902091    } 
    20912092 
     
    20962097     * @param mixed   $uids       Message UIDs as array or comma-separated string, or '*' 
    20972098     * @param string  $flag       Flag to set: SEEN, UNDELETED, DELETED, RECENT, ANSWERED, DRAFT, MDNSENT 
    2098      * @param string  $mailbox    Folder name 
     2099     * @param string  $folder    Folder name 
    20992100     * @param boolean $skip_cache True to skip message cache clean up 
    21002101     * 
    21012102     * @return boolean  Operation status 
    21022103     */ 
    2103     function set_flag($uids, $flag, $mailbox=null, $skip_cache=false) 
    2104     { 
    2105         if (!strlen($mailbox)) { 
    2106             $mailbox = $this->mailbox; 
     2104    public function set_flag($uids, $flag, $folder=null, $skip_cache=false) 
     2105    { 
     2106        if (!strlen($folder)) { 
     2107            $folder = $this->folder; 
     2108        } 
     2109 
     2110        if (!$this->check_connection()) { 
     2111            return false; 
    21072112        } 
    21082113 
    21092114        $flag = strtoupper($flag); 
    2110         list($uids, $all_mode) = $this->_parse_uids($uids, $mailbox); 
    2111  
    2112         if (strpos($flag, 'UN') === 0) 
    2113             $result = $this->conn->unflag($mailbox, $uids, substr($flag, 2)); 
    2114         else 
    2115             $result = $this->conn->flag($mailbox, $uids, $flag); 
     2115        list($uids, $all_mode) = $this->parse_uids($uids); 
     2116 
     2117        if (strpos($flag, 'UN') === 0) { 
     2118            $result = $this->conn->unflag($folder, $uids, substr($flag, 2)); 
     2119        } 
     2120        else { 
     2121            $result = $this->conn->flag($folder, $uids, $flag); 
     2122        } 
    21162123 
    21172124        if ($result) { 
     
    21212128                $status = strpos($flag, 'UN') !== 0; 
    21222129                $mflag  = preg_replace('/^UN/', '', $flag); 
    2123                 $mcache->change_flag($mailbox, $all_mode ? null : explode(',', $uids), 
     2130                $mcache->change_flag($folder, $all_mode ? null : explode(',', $uids), 
    21242131                    $mflag, $status); 
    21252132            } 
     
    21272134            // clear cached counters 
    21282135            if ($flag == 'SEEN' || $flag == 'UNSEEN') { 
    2129                 $this->_clear_messagecount($mailbox, 'SEEN'); 
    2130                 $this->_clear_messagecount($mailbox, 'UNSEEN'); 
     2136                $this->clear_messagecount($folder, 'SEEN'); 
     2137                $this->clear_messagecount($folder, 'UNSEEN'); 
    21312138            } 
    21322139            else if ($flag == 'DELETED') { 
    2133                 $this->_clear_messagecount($mailbox, 'DELETED'); 
     2140                $this->clear_messagecount($folder, 'DELETED'); 
    21342141            } 
    21352142        } 
     
    21402147 
    21412148    /** 
    2142      * Remove message flag for one or several messages 
    2143      * 
    2144      * @param mixed  $uids    Message UIDs as array or comma-separated string, or '*' 
    2145      * @param string $flag    Flag to unset: SEEN, DELETED, RECENT, ANSWERED, DRAFT, MDNSENT 
    2146      * @param string $mailbox Folder name 
    2147      * 
    2148      * @return int   Number of flagged messages, -1 on failure 
    2149      * @see set_flag 
    2150      */ 
    2151     function unset_flag($uids, $flag, $mailbox=null) 
    2152     { 
    2153         return $this->set_flag($uids, 'UN'.$flag, $mailbox); 
    2154     } 
    2155  
    2156  
    2157     /** 
    2158      * Append a mail message (source) to a specific mailbox 
    2159      * 
    2160      * @param string  $mailbox Target mailbox 
     2149     * Append a mail message (source) to a specific folder 
     2150     * 
     2151     * @param string  $folder  Target folder 
    21612152     * @param string  $message The message source string or filename 
    21622153     * @param string  $headers Headers string if $message contains only the body 
     
    21652156     * @return int|bool Appended message UID or True on success, False on error 
    21662157     */ 
    2167     function save_message($mailbox, &$message, $headers='', $is_file=false) 
    2168     { 
    2169         if (!strlen($mailbox)) { 
    2170             $mailbox = $this->mailbox; 
    2171         } 
    2172  
    2173         // make sure mailbox exists 
    2174         if ($this->mailbox_exists($mailbox)) { 
    2175             if ($is_file) 
    2176                 $saved = $this->conn->appendFromFile($mailbox, $message, $headers); 
    2177             else 
    2178                 $saved = $this->conn->append($mailbox, $message); 
     2158    public function save_message($folder, &$message, $headers='', $is_file=false) 
     2159    { 
     2160        if (!strlen($folder)) { 
     2161            $folder = $this->folder; 
     2162        } 
     2163 
     2164        // make sure folder exists 
     2165        if ($this->folder_exists($folder)) { 
     2166            if ($is_file) { 
     2167                $saved = $this->conn->appendFromFile($folder, $message, $headers); 
     2168            } 
     2169            else { 
     2170                $saved = $this->conn->append($folder, $message); 
     2171            } 
    21792172        } 
    21802173 
    21812174        if ($saved) { 
    2182             // increase messagecount of the target mailbox 
    2183             $this->_set_messagecount($mailbox, 'ALL', 1); 
     2175            // increase messagecount of the target folder 
     2176            $this->set_messagecount($folder, 'ALL', 1); 
    21842177        } 
    21852178 
     
    21892182 
    21902183    /** 
    2191      * Move a message from one mailbox to another 
     2184     * Move a message from one folder to another 
    21922185     * 
    21932186     * @param mixed  $uids      Message UIDs as array or comma-separated string, or '*' 
    2194      * @param string $to_mbox   Target mailbox 
    2195      * @param string $from_mbox Source mailbox 
     2187     * @param string $to_mbox   Target folder 
     2188     * @param string $from_mbox Source folder 
     2189     * 
    21962190     * @return boolean True on success, False on error 
    21972191     */ 
    2198     function move_message($uids, $to_mbox, $from_mbox='') 
     2192    public function move_message($uids, $to_mbox, $from_mbox='') 
    21992193    { 
    22002194        if (!strlen($from_mbox)) { 
    2201             $from_mbox = $this->mailbox; 
     2195            $from_mbox = $this->folder; 
    22022196        } 
    22032197 
     
    22062200        } 
    22072201 
    2208         list($uids, $all_mode) = $this->_parse_uids($uids, $from_mbox); 
     2202        list($uids, $all_mode) = $this->parse_uids($uids); 
    22092203 
    22102204        // exit if no message uids are specified 
    2211         if (empty($uids)) 
     2205        if (empty($uids)) { 
    22122206            return false; 
    2213  
    2214         // make sure mailbox exists 
    2215         if ($to_mbox != 'INBOX' && !$this->mailbox_exists($to_mbox)) { 
     2207        } 
     2208 
     2209        if (!$this->check_connection()) { 
     2210            return false; 
     2211        } 
     2212 
     2213        // make sure folder exists 
     2214        if ($to_mbox != 'INBOX' && !$this->folder_exists($to_mbox)) { 
    22162215            if (in_array($to_mbox, $this->default_folders)) { 
    2217                 if (!$this->create_mailbox($to_mbox, true)) { 
     2216                if (!$this->create_folder($to_mbox, true)) { 
    22182217                    return false; 
    22192218                } 
     
    22372236 
    22382237        // send expunge command in order to have the moved message 
    2239         // really deleted from the source mailbox 
     2238        // really deleted from the source folder 
    22402239        if ($moved) { 
    2241             $this->_expunge($from_mbox, false, $uids); 
    2242             $this->_clear_messagecount($from_mbox); 
    2243             $this->_clear_messagecount($to_mbox); 
     2240            $this->expunge_message($uids, $from_mbox, false); 
     2241            $this->clear_messagecount($from_mbox); 
     2242            $this->clear_messagecount($to_mbox); 
    22442243        } 
    22452244        // moving failed 
     
    22532252 
    22542253            // remove message ids from search set 
    2255             if ($this->search_set && $from_mbox == $this->mailbox) { 
     2254            if ($this->search_set && $from_mbox == $this->folder) { 
    22562255                // threads are too complicated to just remove messages from set 
    2257                 if ($this->search_threads || $all_mode) 
     2256                if ($this->search_threads || $all_mode) { 
    22582257                    $this->refresh_search(); 
    2259                 else 
     2258                } 
     2259                else { 
    22602260                    $this->search_set->filter(explode(',', $uids)); 
     2261                } 
    22612262            } 
    22622263 
     
    22712272 
    22722273    /** 
    2273      * Copy a message from one mailbox to another 
     2274     * Copy a message from one folder to another 
    22742275     * 
    22752276     * @param mixed  $uids      Message UIDs as array or comma-separated string, or '*' 
    2276      * @param string $to_mbox   Target mailbox 
    2277      * @param string $from_mbox Source mailbox 
     2277     * @param string $to_mbox   Target folder 
     2278     * @param string $from_mbox Source folder 
     2279     * 
    22782280     * @return boolean True on success, False on error 
    22792281     */ 
    2280     function copy_message($uids, $to_mbox, $from_mbox='') 
     2282    public function copy_message($uids, $to_mbox, $from_mbox='') 
    22812283    { 
    22822284        if (!strlen($from_mbox)) { 
    2283             $from_mbox = $this->mailbox; 
    2284         } 
    2285  
    2286         list($uids, $all_mode) = $this->_parse_uids($uids, $from_mbox); 
     2285            $from_mbox = $this->folder; 
     2286        } 
     2287 
     2288        list($uids, $all_mode) = $this->parse_uids($uids); 
    22872289 
    22882290        // exit if no message uids are specified 
     
    22912293        } 
    22922294 
    2293         // make sure mailbox exists 
    2294         if ($to_mbox != 'INBOX' && !$this->mailbox_exists($to_mbox)) { 
     2295        if (!$this->check_connection()) { 
     2296            return false; 
     2297        } 
     2298 
     2299        // make sure folder exists 
     2300        if ($to_mbox != 'INBOX' && !$this->folder_exists($to_mbox)) { 
    22952301            if (in_array($to_mbox, $this->default_folders)) { 
    2296                 if (!$this->create_mailbox($to_mbox, true)) { 
     2302                if (!$this->create_folder($to_mbox, true)) { 
    22972303                    return false; 
    22982304                } 
     
    23072313 
    23082314        if ($copied) { 
    2309             $this->_clear_messagecount($to_mbox); 
     2315            $this->clear_messagecount($to_mbox); 
    23102316        } 
    23112317 
     
    23152321 
    23162322    /** 
    2317      * Mark messages as deleted and expunge mailbox 
     2323     * Mark messages as deleted and expunge them 
    23182324     * 
    23192325     * @param mixed  $uids    Message UIDs as array or comma-separated string, or '*' 
    2320      * @param string $mailbox Source mailbox 
     2326     * @param string $folder  Source folder 
    23212327     * 
    23222328     * @return boolean True on success, False on error 
    23232329     */ 
    2324     function delete_message($uids, $mailbox='') 
    2325     { 
    2326         if (!strlen($mailbox)) { 
    2327             $mailbox = $this->mailbox; 
    2328         } 
    2329  
    2330         list($uids, $all_mode) = $this->_parse_uids($uids, $mailbox); 
     2330    public function delete_message($uids, $folder='') 
     2331    { 
     2332        if (!strlen($folder)) { 
     2333            $folder = $this->folder; 
     2334        } 
     2335 
     2336        list($uids, $all_mode) = $this->parse_uids($uids); 
    23312337 
    23322338        // exit if no message uids are specified 
    2333         if (empty($uids)) 
     2339        if (empty($uids)) { 
    23342340            return false; 
    2335  
    2336         $deleted = $this->conn->flag($mailbox, $uids, 'DELETED'); 
     2341        } 
     2342 
     2343        if (!$this->check_connection()) { 
     2344            return false; 
     2345        } 
     2346 
     2347        $deleted = $this->conn->flag($folder, $uids, 'DELETED'); 
    23372348 
    23382349        if ($deleted) { 
    23392350            // send expunge command in order to have the deleted message 
    2340             // really deleted from the mailbox 
    2341             $this->_expunge($mailbox, false, $uids); 
    2342             $this->_clear_messagecount($mailbox); 
    2343             unset($this->uid_id_map[$mailbox]); 
     2351            // really deleted from the folder 
     2352            $this->expunge_message($uids, $folder, false); 
     2353            $this->clear_messagecount($folder); 
     2354            unset($this->uid_id_map[$folder]); 
    23442355 
    23452356            // unset threads internal cache 
     
    23472358 
    23482359            // remove message ids from search set 
    2349             if ($this->search_set && $mailbox == $this->mailbox) { 
     2360            if ($this->search_set && $folder == $this->folder) { 
    23502361                // threads are too complicated to just remove messages from set 
    2351                 if ($this->search_threads || $all_mode) 
     2362                if ($this->search_threads || $all_mode) { 
    23522363                    $this->refresh_search(); 
    2353                 else 
     2364                } 
     2365                else { 
    23542366                    $this->search_set->filter(explode(',', $uids)); 
     2367                } 
    23552368            } 
    23562369 
    23572370            // remove cached messages 
    2358             $this->clear_message_cache($mailbox, $all_mode ? null : explode(',', $uids)); 
     2371            $this->clear_message_cache($folder, $all_mode ? null : explode(',', $uids)); 
    23592372        } 
    23602373 
     
    23642377 
    23652378    /** 
    2366      * Clear all messages in a specific mailbox 
    2367      * 
    2368      * @param string $mailbox Mailbox name 
    2369      * 
    2370      * @return int Above 0 on success 
    2371      */ 
    2372     function clear_mailbox($mailbox=null) 
    2373     { 
    2374         if (!strlen($mailbox)) { 
    2375             $mailbox = $this->mailbox; 
    2376         } 
    2377  
    2378         // SELECT will set messages count for clearFolder() 
    2379         if ($this->conn->select($mailbox)) { 
    2380             $cleared = $this->conn->clearFolder($mailbox); 
    2381         } 
    2382  
    2383         // make sure the cache is cleared as well 
    2384         if ($cleared) { 
    2385             $this->clear_message_cache($mailbox); 
    2386             $a_mailbox_cache = $this->get_cache('messagecount'); 
    2387             unset($a_mailbox_cache[$mailbox]); 
    2388             $this->update_cache('messagecount', $a_mailbox_cache); 
    2389         } 
    2390  
    2391         return $cleared; 
    2392     } 
    2393  
    2394  
    2395     /** 
    23962379     * Send IMAP expunge command and clear cache 
    23972380     * 
    2398      * @param string  $mailbox     Mailbox name 
     2381     * @param mixed   $uids        Message UIDs as array or comma-separated string, or '*' 
     2382     * @param string  $folder      Folder name 
    23992383     * @param boolean $clear_cache False if cache should not be cleared 
    24002384     * 
    2401      * @return boolean True on success 
    2402      */ 
    2403     function expunge($mailbox='', $clear_cache=true) 
    2404     { 
    2405         if (!strlen($mailbox)) { 
    2406             $mailbox = $this->mailbox; 
    2407         } 
    2408  
    2409         return $this->_expunge($mailbox, $clear_cache); 
    2410     } 
    2411  
    2412  
    2413     /** 
    2414      * Send IMAP expunge command and clear cache 
    2415      * 
    2416      * @param string  $mailbox     Mailbox name 
    2417      * @param boolean $clear_cache False if cache should not be cleared 
    2418      * @param mixed   $uids        Message UIDs as array or comma-separated string, or '*' 
    2419      * @return boolean True on success 
    2420      * @access private 
    2421      * @see rcube_imap::expunge() 
    2422      */ 
    2423     private function _expunge($mailbox, $clear_cache=true, $uids=NULL) 
    2424     { 
    2425         if ($uids && $this->get_capability('UIDPLUS')) 
    2426             list($uids, $all_mode) = $this->_parse_uids($uids, $mailbox); 
    2427         else 
     2385     * @return boolean True on success, False on failure 
     2386     */ 
     2387    public function expunge_message($uids, $folder = null, $clear_cache = true) 
     2388    { 
     2389        if ($uids && $this->get_capability('UIDPLUS')) { 
     2390            list($uids, $all_mode) = $this->parse_uids($uids); 
     2391        } 
     2392        else { 
    24282393            $uids = null; 
    2429  
    2430         // force mailbox selection and check if mailbox is writeable 
     2394        } 
     2395 
     2396        if (!strlen($folder)) { 
     2397            $folder = $this->folder; 
     2398        } 
     2399 
     2400        if (!$this->check_connection()) { 
     2401            return false; 
     2402        } 
     2403 
     2404        // force folder selection and check if folder is writeable 
    24312405        // to prevent a situation when CLOSE is executed on closed 
    2432         // or EXPUNGE on read-only mailbox 
    2433         $result = $this->conn->select($mailbox); 
     2406        // or EXPUNGE on read-only folder 
     2407        $result = $this->conn->select($folder); 
    24342408        if (!$result) { 
    24352409            return false; 
    24362410        } 
     2411 
    24372412        if (!$this->conn->data['READ-WRITE']) { 
    2438             $this->conn->setError(rcube_imap_generic::ERROR_READONLY, "Mailbox is read-only"); 
     2413            $this->conn->setError(rcube_imap_generic::ERROR_READONLY, "Folder is read-only"); 
    24392414            return false; 
    24402415        } 
    24412416 
    24422417        // CLOSE(+SELECT) should be faster than EXPUNGE 
    2443         if (empty($uids) || $all_mode) 
     2418        if (empty($uids) || $all_mode) { 
    24442419            $result = $this->conn->close(); 
    2445         else 
    2446             $result = $this->conn->expunge($mailbox, $uids); 
     2420        } 
     2421        else { 
     2422            $result = $this->conn->expunge($folder, $uids); 
     2423        } 
    24472424 
    24482425        if ($result && $clear_cache) { 
    2449             $this->clear_message_cache($mailbox, $all_mode ? null : explode(',', $uids)); 
    2450             $this->_clear_messagecount($mailbox); 
     2426            $this->clear_message_cache($folder, $all_mode ? null : explode(',', $uids)); 
     2427            $this->clear_messagecount($folder); 
    24512428        } 
    24522429 
    24532430        return $result; 
    2454     } 
    2455  
    2456  
    2457     /** 
    2458      * Parse message UIDs input 
    2459      * 
    2460      * @param mixed  $uids    UIDs array or comma-separated list or '*' or '1:*' 
    2461      * @param string $mailbox Mailbox name 
    2462      * @return array Two elements array with UIDs converted to list and ALL flag 
    2463      * @access private 
    2464      */ 
    2465     private function _parse_uids($uids, $mailbox) 
    2466     { 
    2467         if ($uids === '*' || $uids === '1:*') { 
    2468             if (empty($this->search_set)) { 
    2469                 $uids = '1:*'; 
    2470                 $all = true; 
    2471             } 
    2472             // get UIDs from current search set 
    2473             else { 
    2474                 $uids = join(',', $this->search_set->get()); 
    2475             } 
    2476         } 
    2477         else { 
    2478             if (is_array($uids)) 
    2479                 $uids = join(',', $uids); 
    2480  
    2481             if (preg_match('/[^0-9,]/', $uids)) 
    2482                 $uids = ''; 
    2483         } 
    2484  
    2485         return array($uids, (bool) $all); 
    24862431    } 
    24872432 
     
    24922437 
    24932438    /** 
    2494      * Public method for listing subscribed folders 
     2439     * Public method for listing subscribed folders. 
    24952440     * 
    24962441     * @param   string  $root      Optional root folder 
     
    25012446     * 
    25022447     * @return  array   List of folders 
    2503      * @access  public 
    2504      */ 
    2505     function list_mailboxes($root='', $name='*', $filter=null, $rights=null, $skip_sort=false) 
     2448     */ 
     2449    public function list_folders_subscribed($root='', $name='*', $filter=null, $rights=null, $skip_sort=false) 
    25062450    { 
    25072451        $cache_key = $root.':'.$name; 
     
    25182462        } 
    25192463 
    2520         $a_mboxes = $this->_list_mailboxes($root, $name, $filter, $rights); 
     2464        $a_mboxes = $this->_list_folders_subscribed($root, $name, $filter, $rights); 
    25212465 
    25222466        if (!is_array($a_mboxes)) { 
     
    25342478        } 
    25352479 
    2536         // sort mailboxes (always sort for cache) 
     2480        // sort folders (always sort for cache) 
    25372481        if (!$skip_sort || $this->cache) { 
    2538             $a_mboxes = $this->_sort_mailbox_list($a_mboxes); 
    2539         } 
    2540  
    2541         // write mailboxlist to cache 
     2482            $a_mboxes = $this->sort_folder_list($a_mboxes); 
     2483        } 
     2484 
     2485        // write folders list to cache 
    25422486        $this->update_cache($cache_key, $a_mboxes); 
    25432487 
     
    25472491 
    25482492    /** 
    2549      * Private method for mailbox listing (LSUB) 
     2493     * protected method for folders listing (LSUB) 
    25502494     * 
    25512495     * @param   string  $root   Optional root folder 
     
    25552499     * 
    25562500     * @return  array   List of subscribed folders 
    2557      * @see     rcube_imap::list_mailboxes() 
    2558      * @access  private 
    2559      */ 
    2560     private function _list_mailboxes($root='', $name='*', $filter=null, $rights=null) 
     2501     * @see     rcube_imap::list_folders_subscribed() 
     2502     */ 
     2503    protected function _list_folders_subscribed($root='', $name='*', $filter=null, $rights=null) 
    25612504    { 
    25622505        $a_defaults = $a_out = array(); 
    25632506 
    2564         // Give plugins a chance to provide a list of mailboxes 
    2565         $data = rcmail::get_instance()->plugins->exec_hook('mailboxes_list', 
     2507        // Give plugins a chance to provide a list of folders 
     2508        $data = rcmail::get_instance()->plugins->exec_hook('folders_list', 
    25662509            array('root' => $root, 'name' => $name, 'filter' => $filter, 'mode' => 'LSUB')); 
    25672510 
     
    25692512            $a_folders = $data['folders']; 
    25702513        } 
    2571         else if (!$this->conn->connected()) { 
     2514        else if (!$this->check_connection()) { 
    25722515           return null; 
    25732516        } 
     
    25772520            // #1486225: Some dovecot versions returns wrong result using LIST-EXTENDED 
    25782521            if (!$config->get('imap_force_lsub') && $this->get_capability('LIST-EXTENDED')) { 
    2579                 // This will also set mailbox options, LSUB doesn't do that 
     2522                // This will also set folder options, LSUB doesn't do that 
    25802523                $a_folders = $this->conn->listMailboxes($root, $name, 
    25812524                    NULL, array('SUBSCRIBED')); 
     
    26042547                        ) { 
    26052548                            // Some servers returns \Noselect for existing folders 
    2606                             if (!$this->mailbox_exists($folder)) { 
     2549                            if (!$this->folder_exists($folder)) { 
    26072550                                $this->conn->unsubscribe($folder); 
    26082551                                unset($a_folders[$idx]); 
     
    26232566 
    26242567    /** 
    2625      * Get a list of all folders available on the IMAP server 
     2568     * Get a list of all folders available on the server 
    26262569     * 
    26272570     * @param string  $root      IMAP root dir 
     
    26332576     * @return array Indexed array with folder names 
    26342577     */ 
    2635     function list_unsubscribed($root='', $name='*', $filter=null, $rights=null, $skip_sort=false) 
     2578    public function list_folders($root='', $name='*', $filter=null, $rights=null, $skip_sort=false) 
    26362579    { 
    26372580        $cache_key = $root.':'.$name; 
     
    26482591        } 
    26492592 
    2650         // Give plugins a chance to provide a list of mailboxes 
    2651         $data = rcmail::get_instance()->plugins->exec_hook('mailboxes_list', 
     2593        // Give plugins a chance to provide a list of folders 
     2594        $data = rcmail::get_instance()->plugins->exec_hook('folders_list', 
    26522595            array('root' => $root, 'name' => $name, 'filter' => $filter, 'mode' => 'LIST')); 
    26532596 
     
    26572600        else { 
    26582601            // retrieve list of folders from IMAP server 
    2659             $a_mboxes = $this->_list_unsubscribed($root, $name); 
     2602            $a_mboxes = $this->_list_folders($root, $name); 
    26602603        } 
    26612604 
     
    26702613 
    26712614        // cache folder attributes 
    2672         if ($root == '' && $name == '*' && empty($filter)) { 
     2615        if ($root == '' && $name == '*' && empty($filter) && !empty($this->conn->data)) { 
    26732616            $this->update_cache('mailboxes.attributes', $this->conn->data['LIST']); 
    26742617        } 
     
    26812624        // filter folders and sort them 
    26822625        if (!$skip_sort) { 
    2683             $a_mboxes = $this->_sort_mailbox_list($a_mboxes); 
    2684         } 
    2685  
    2686         // write mailboxlist to cache 
     2626            $a_mboxes = $this->sort_folder_list($a_mboxes); 
     2627        } 
     2628 
     2629        // write folders list to cache 
    26872630        $this->update_cache($cache_key, $a_mboxes); 
    26882631 
     
    26922635 
    26932636    /** 
    2694      * Private method for mailbox listing (LIST) 
     2637     * protected method for folders listing (LIST) 
    26952638     * 
    26962639     * @param   string  $root   Optional root folder 
     
    26982641     * 
    26992642     * @return  array   List of folders 
    2700      * @see     rcube_imap::list_unsubscribed() 
    2701      */ 
    2702     private function _list_unsubscribed($root='', $name='*') 
    2703     { 
     2643     * @see     rcube_imap::list_folders() 
     2644     */ 
     2645    protected function _list_folders($root='', $name='*') 
     2646    { 
     2647        if (!$this->check_connection()) { 
     2648            return null; 
     2649        } 
     2650 
    27042651        $result = $this->conn->listMailboxes($root, $name); 
    27052652 
     
    27582705     * Filter the given list of folders according to access rights 
    27592706     */ 
    2760     private function filter_rights($a_folders, $rights) 
     2707    protected function filter_rights($a_folders, $rights) 
    27612708    { 
    27622709        $regex = '/('.$rights.')/'; 
    27632710        foreach ($a_folders as $idx => $folder) { 
    27642711            $myrights = join('', (array)$this->my_rights($folder)); 
    2765             if ($myrights !== null && !preg_match($regex, $myrights)) 
     2712            if ($myrights !== null && !preg_match($regex, $myrights)) { 
    27662713                unset($a_folders[$idx]); 
     2714            } 
    27672715        } 
    27682716 
     
    27772725     * @return mixed Quota info or False if not supported 
    27782726     */ 
    2779     function get_quota() 
    2780     { 
    2781         if ($this->get_capability('QUOTA')) 
     2727    public function get_quota() 
     2728    { 
     2729        if ($this->get_capability('QUOTA')) { 
    27822730            return $this->conn->getQuota(); 
     2731        } 
    27832732 
    27842733        return false; 
     
    27872736 
    27882737    /** 
    2789      * Get mailbox size (size of all messages in a mailbox) 
    2790      * 
    2791      * @param string $mailbox Mailbox name 
    2792      * 
    2793      * @return int Mailbox size in bytes, False on error 
    2794      */ 
    2795     function get_mailbox_size($mailbox) 
    2796     { 
     2738     * Get folder size (size of all messages in a folder) 
     2739     * 
     2740     * @param string $folder Folder name 
     2741     * 
     2742     * @return int Folder size in bytes, False on error 
     2743     */ 
     2744    public function folder_size($folder) 
     2745    { 
     2746        if (!$this->check_connection()) { 
     2747            return 0; 
     2748        } 
     2749 
    27972750        // @TODO: could we try to use QUOTA here? 
    2798         $result = $this->conn->fetchHeaderIndex($mailbox, '1:*', 'SIZE', false); 
    2799  
    2800         if (is_array($result)) 
     2751        $result = $this->conn->fetchHeaderIndex($folder, '1:*', 'SIZE', false); 
     2752 
     2753        if (is_array($result)) { 
    28012754            $result = array_sum($result); 
     2755        } 
    28022756 
    28032757        return $result; 
     
    28062760 
    28072761    /** 
    2808      * Subscribe to a specific mailbox(es) 
    2809      * 
    2810      * @param array $a_mboxes Mailbox name(s) 
     2762     * Subscribe to a specific folder(s) 
     2763     * 
     2764     * @param array $folders Folder name(s) 
     2765     * 
    28112766     * @return boolean True on success 
    28122767     */ 
    2813     function subscribe($a_mboxes) 
    2814     { 
    2815         if (!is_array($a_mboxes)) 
    2816             $a_mboxes = array($a_mboxes); 
    2817  
     2768    public function subscribe($folders) 
     2769    { 
    28182770        // let this common function do the main work 
    2819         return $this->_change_subscription($a_mboxes, 'subscribe'); 
    2820     } 
    2821  
    2822  
    2823     /** 
    2824      * Unsubscribe mailboxes 
    2825      * 
    2826      * @param array $a_mboxes Mailbox name(s) 
     2771        return $this->change_subscription($folders, 'subscribe'); 
     2772    } 
     2773 
     2774 
     2775    /** 
     2776     * Unsubscribe folder(s) 
     2777     * 
     2778     * @param array $a_mboxes Folder name(s) 
     2779     * 
    28272780     * @return boolean True on success 
    28282781     */ 
    2829     function unsubscribe($a_mboxes) 
    2830     { 
    2831         if (!is_array($a_mboxes)) 
    2832             $a_mboxes = array($a_mboxes); 
    2833  
     2782    public function unsubscribe($folders) 
     2783    { 
    28342784        // let this common function do the main work 
    2835         return $this->_change_subscription($a_mboxes, 'unsubscribe'); 
    2836     } 
    2837  
    2838  
    2839     /** 
    2840      * Create a new mailbox on the server and register it in local cache 
    2841      * 
    2842      * @param string  $mailbox   New mailbox name 
    2843      * @param boolean $subscribe True if the new mailbox should be subscribed 
     2785        return $this->change_subscription($folders, 'unsubscribe'); 
     2786    } 
     2787 
     2788 
     2789    /** 
     2790     * Create a new folder on the server and register it in local cache 
     2791     * 
     2792     * @param string  $folder    New folder name 
     2793     * @param boolean $subscribe True if the new folder should be subscribed 
    28442794     * 
    28452795     * @return boolean True on success 
    28462796     */ 
    2847     function create_mailbox($mailbox, $subscribe=false) 
    2848     { 
    2849         $result = $this->conn->createFolder($mailbox); 
     2797    public function create_folder($folder, $subscribe=false) 
     2798    { 
     2799        if (!$this->check_connection()) { 
     2800            return false; 
     2801        } 
     2802 
     2803        $result = $this->conn->createFolder($folder); 
    28502804 
    28512805        // try to subscribe it 
     
    28542808            $this->clear_cache('mailboxes', true); 
    28552809 
    2856             if ($subscribe) 
    2857                 $this->subscribe($mailbox); 
     2810            if ($subscribe) { 
     2811                $this->subscribe($folder); 
     2812            } 
    28582813        } 
    28592814 
     
    28632818 
    28642819    /** 
    2865      * Set a new name to an existing mailbox 
    2866      * 
    2867      * @param string $mailbox  Mailbox to rename 
    2868      * @param string $new_name New mailbox name 
     2820     * Set a new name to an existing folder 
     2821     * 
     2822     * @param string $folder   Folder to rename 
     2823     * @param string $new_name New folder name 
    28692824     * 
    28702825     * @return boolean True on success 
    28712826     */ 
    2872     function rename_mailbox($mailbox, $new_name) 
     2827    public function rename_folder($folder, $new_name) 
    28732828    { 
    28742829        if (!strlen($new_name)) { 
     
    28762831        } 
    28772832 
     2833        if (!$this->check_connection()) { 
     2834            return false; 
     2835        } 
     2836 
    28782837        $delm = $this->get_hierarchy_delimiter(); 
    28792838 
    28802839        // get list of subscribed folders 
    2881         if ((strpos($mailbox, '%') === false) && (strpos($mailbox, '*') === false)) { 
    2882             $a_subscribed = $this->_list_mailboxes('', $mailbox . $delm . '*'); 
    2883             $subscribed   = $this->mailbox_exists($mailbox, true); 
     2840        if ((strpos($folder, '%') === false) && (strpos($folder, '*') === false)) { 
     2841            $a_subscribed = $this->_list_folders_subscribed('', $folder . $delm . '*'); 
     2842            $subscribed   = $this->folder_exists($folder, true); 
    28842843        } 
    28852844        else { 
    2886             $a_subscribed = $this->_list_mailboxes(); 
    2887             $subscribed   = in_array($mailbox, $a_subscribed); 
    2888         } 
    2889  
    2890         $result = $this->conn->renameFolder($mailbox, $new_name); 
     2845            $a_subscribed = $this->_list_folders_subscribed(); 
     2846            $subscribed   = in_array($folder, $a_subscribed); 
     2847        } 
     2848 
     2849        $result = $this->conn->renameFolder($folder, $new_name); 
    28912850 
    28922851        if ($result) { 
    28932852            // unsubscribe the old folder, subscribe the new one 
    28942853            if ($subscribed) { 
    2895                 $this->conn->unsubscribe($mailbox); 
     2854                $this->conn->unsubscribe($folder); 
    28962855                $this->conn->subscribe($new_name); 
    28972856            } 
    28982857 
    2899             // check if mailbox children are subscribed 
     2858            // check if folder children are subscribed 
    29002859            foreach ($a_subscribed as $c_subscribed) { 
    2901                 if (strpos($c_subscribed, $mailbox.$delm) === 0) { 
     2860                if (strpos($c_subscribed, $folder.$delm) === 0) { 
    29022861                    $this->conn->unsubscribe($c_subscribed); 
    2903                     $this->conn->subscribe(preg_replace('/^'.preg_quote($mailbox, '/').'/', 
     2862                    $this->conn->subscribe(preg_replace('/^'.preg_quote($folder, '/').'/', 
    29042863                        $new_name, $c_subscribed)); 
    29052864 
     
    29102869 
    29112870            // clear cache 
    2912             $this->clear_message_cache($mailbox); 
     2871            $this->clear_message_cache($folder); 
    29132872            $this->clear_cache('mailboxes', true); 
    29142873        } 
     
    29192878 
    29202879    /** 
    2921      * Remove mailbox from server 
    2922      * 
    2923      * @param string $mailbox Mailbox name 
     2880     * Remove folder from server 
     2881     * 
     2882     * @param string $folder Folder name 
    29242883     * 
    29252884     * @return boolean True on success 
    29262885     */ 
    2927     function delete_mailbox($mailbox) 
     2886    function delete_folder($folder) 
    29282887    { 
    29292888        $delm = $this->get_hierarchy_delimiter(); 
    29302889 
     2890        if (!$this->check_connection()) { 
     2891            return false; 
     2892        } 
     2893 
    29312894        // get list of folders 
    2932         if ((strpos($mailbox, '%') === false) && (strpos($mailbox, '*') === false)) 
    2933             $sub_mboxes = $this->list_unsubscribed('', $mailbox . $delm . '*'); 
    2934         else 
     2895        if ((strpos($folder, '%') === false) && (strpos($folder, '*') === false)) { 
     2896            $sub_mboxes = $this->list_unsubscribed('', $folder . $delm . '*'); 
     2897        } 
     2898        else { 
    29352899            $sub_mboxes = $this->list_unsubscribed(); 
     2900        } 
    29362901 
    29372902        // send delete command to server 
    2938         $result = $this->conn->deleteFolder($mailbox); 
     2903        $result = $this->conn->deleteFolder($folder); 
    29392904 
    29402905        if ($result) { 
    2941             // unsubscribe mailbox 
    2942             $this->conn->unsubscribe($mailbox); 
     2906            // unsubscribe folder 
     2907            $this->conn->unsubscribe($folder); 
    29432908 
    29442909            foreach ($sub_mboxes as $c_mbox) { 
    2945                 if (strpos($c_mbox, $mailbox.$delm) === 0) { 
     2910                if (strpos($c_mbox, $folder.$delm) === 0) { 
    29462911                    $this->conn->unsubscribe($c_mbox); 
    29472912                    if ($this->conn->deleteFolder($c_mbox)) { 
     
    29512916            } 
    29522917 
    2953             // clear mailbox-related cache 
    2954             $this->clear_message_cache($mailbox); 
     2918            // clear folder-related cache 
     2919            $this->clear_message_cache($folder); 
    29552920            $this->clear_cache('mailboxes', true); 
    29562921        } 
     
    29632928     * Create all folders specified as default 
    29642929     */ 
    2965     function create_default_folders() 
     2930    public function create_default_folders() 
    29662931    { 
    29672932        // create default folders if they do not exist 
    29682933        foreach ($this->default_folders as $folder) { 
    2969             if (!$this->mailbox_exists($folder)) 
    2970                 $this->create_mailbox($folder, true); 
    2971             else if (!$this->mailbox_exists($folder, true)) 
     2934            if (!$this->folder_exists($folder)) { 
     2935                $this->create_folder($folder, true); 
     2936            } 
     2937            else if (!$this->folder_exists($folder, true)) { 
    29722938                $this->subscribe($folder); 
     2939            } 
    29732940        } 
    29742941    } 
     
    29782945     * Checks if folder exists and is subscribed 
    29792946     * 
    2980      * @param string   $mailbox      Folder name 
     2947     * @param string   $folder       Folder name 
    29812948     * @param boolean  $subscription Enable subscription checking 
    29822949     * 
    29832950     * @return boolean TRUE or FALSE 
    29842951     */ 
    2985     function mailbox_exists($mailbox, $subscription=false) 
    2986     { 
    2987         if ($mailbox == 'INBOX') { 
     2952    public function folder_exists($folder, $subscription=false) 
     2953    { 
     2954        if ($folder == 'INBOX') { 
    29882955            return true; 
    29892956        } 
     
    29912958        $key  = $subscription ? 'subscribed' : 'existing'; 
    29922959 
    2993         if (is_array($this->icache[$key]) && in_array($mailbox, $this->icache[$key])) 
     2960        if (is_array($this->icache[$key]) && in_array($folder, $this->icache[$key])) { 
    29942961            return true; 
     2962        } 
     2963 
     2964        if (!$this->check_connection()) { 
     2965            return false; 
     2966        } 
    29952967 
    29962968        if ($subscription) { 
    2997             $a_folders = $this->conn->listSubscribed('', $mailbox); 
     2969            $a_folders = $this->conn->listSubscribed('', $folder); 
    29982970        } 
    29992971        else { 
    3000             $a_folders = $this->conn->listMailboxes('', $mailbox); 
    3001         } 
    3002  
    3003         if (is_array($a_folders) && in_array($mailbox, $a_folders)) { 
    3004             $this->icache[$key][] = $mailbox; 
     2972            $a_folders = $this->conn->listMailboxes('', $folder); 
     2973        } 
     2974 
     2975        if (is_array($a_folders) && in_array($folder, $a_folders)) { 
     2976            $this->icache[$key][] = $folder; 
    30052977            return true; 
    30062978        } 
     
    30132985     * Returns the namespace where the folder is in 
    30142986     * 
    3015      * @param string $mailbox Folder name 
     2987     * @param string $folder Folder name 
    30162988     * 
    30172989     * @return string One of 'personal', 'other' or 'shared' 
    3018      * @access public 
    3019      */ 
    3020     function mailbox_namespace($mailbox) 
    3021     { 
    3022         if ($mailbox == 'INBOX') { 
     2990     */ 
     2991    public function folder_namespace($folder) 
     2992    { 
     2993        if ($folder == 'INBOX') { 
    30232994            return 'personal'; 
    30242995        } 
     
    30282999                foreach ($namespace as $ns) { 
    30293000                    if ($len = strlen($ns[0])) { 
    3030                         if (($len > 1 && $mailbox == substr($ns[0], 0, -1)) 
    3031                             || strpos($mailbox, $ns[0]) === 0 
     3001                        if (($len > 1 && $folder == substr($ns[0], 0, -1)) 
     3002                            || strpos($folder, $ns[0]) === 0 
    30323003                        ) { 
    30333004                            return $type; 
     
    30483019     * of the folders tree. 
    30493020     * 
    3050      * @param string $mailbox Folder name 
     3021     * @param string $folder Folder name 
    30513022     * @param string $mode    Mode name (out/in) 
    30523023     * 
    30533024     * @return string Folder name 
    30543025     */ 
    3055     function mod_mailbox($mailbox, $mode = 'out') 
    3056     { 
    3057         if (!strlen($mailbox)) { 
    3058             return $mailbox; 
     3026    public function mod_folder($folder, $mode = 'out') 
     3027    { 
     3028        if (!strlen($folder)) { 
     3029            return $folder; 
    30593030        } 
    30603031 
     
    30633034 
    30643035        if (!$prefix_len) { 
    3065             return $mailbox; 
     3036            return $folder; 
    30663037        } 
    30673038 
    30683039        // remove prefix for output 
    30693040        if ($mode == 'out') { 
    3070             if (substr($mailbox, 0, $prefix_len) === $prefix) { 
    3071                 return substr($mailbox, $prefix_len); 
     3041            if (substr($folder, 0, $prefix_len) === $prefix) { 
     3042                return substr($folder, $prefix_len); 
    30723043            } 
    30733044        } 
    30743045        // add prefix for input (e.g. folder creation) 
    30753046        else { 
    3076             return $prefix . $mailbox; 
    3077         } 
    3078  
    3079         return $mailbox; 
     3047            return $prefix . $folder; 
     3048        } 
     3049 
     3050        return $folder; 
    30803051    } 
    30813052 
     
    30843055     * Gets folder attributes from LIST response, e.g. \Noselect, \Noinferiors 
    30853056     * 
    3086      * @param string $mailbox Folder name 
     3057     * @param string $folder Folder name 
    30873058     * @param bool   $force   Set to True if attributes should be refreshed 
    30883059     * 
    30893060     * @return array Options list 
    30903061     */ 
    3091     function mailbox_attributes($mailbox, $force=false) 
     3062    public function folder_attributes($folder, $force=false) 
    30923063    { 
    30933064        // get attributes directly from LIST command 
    3094         if (!empty($this->conn->data['LIST']) && is_array($this->conn->data['LIST'][$mailbox])) { 
    3095             $opts = $this->conn->data['LIST'][$mailbox]; 
     3065        if (!empty($this->conn->data['LIST']) && is_array($this->conn->data['LIST'][$folder])) { 
     3066            $opts = $this->conn->data['LIST'][$folder]; 
    30963067        } 
    30973068        // get cached folder attributes 
    30983069        else if (!$force) { 
    30993070            $opts = $this->get_cache('mailboxes.attributes'); 
    3100             $opts = $opts[$mailbox]; 
     3071            $opts = $opts[$folder]; 
    31013072        } 
    31023073 
    31033074        if (!is_array($opts)) { 
    3104             $this->conn->listMailboxes('', $mailbox); 
    3105             $opts = $this->conn->data['LIST'][$mailbox]; 
     3075            if (!$this->check_connection()) { 
     3076                return array(); 
     3077            } 
     3078 
     3079            $this->conn->listMailboxes('', $folder); 
     3080            $opts = $this->conn->data['LIST'][$folder]; 
    31063081        } 
    31073082 
     
    31113086 
    31123087    /** 
    3113      * Gets connection (and current mailbox) data: UIDVALIDITY, EXISTS, RECENT, 
     3088     * Gets connection (and current folder) data: UIDVALIDITY, EXISTS, RECENT, 
    31143089     * PERMANENTFLAGS, UIDNEXT, UNSEEN 
    31153090     * 
    3116      * @param string $mailbox Folder name 
     3091     * @param string $folder Folder name 
    31173092     * 
    31183093     * @return array Data 
    31193094     */ 
    3120     function mailbox_data($mailbox) 
    3121     { 
    3122         if (!strlen($mailbox)) 
    3123             $mailbox = $this->mailbox !== null ? $this->mailbox : 'INBOX'; 
    3124  
    3125         if ($this->conn->selected != $mailbox) { 
    3126             if ($this->conn->select($mailbox)) 
    3127                 $this->mailbox = $mailbox; 
    3128             else 
     3095    public function folder_data($folder) 
     3096    { 
     3097        if (!strlen($folder)) { 
     3098            $folder = $this->folder !== null ? $this->folder : 'INBOX'; 
     3099        } 
     3100 
     3101        if ($this->conn->selected != $folder) { 
     3102            if (!$this->check_connection()) { 
     3103                return array(); 
     3104            } 
     3105 
     3106            if ($this->conn->select($folder)) { 
     3107                $this->folder = $folder; 
     3108            } 
     3109            else { 
    31293110                return null; 
     3111            } 
    31303112        } 
    31313113 
     
    31343116        // add (E)SEARCH result for ALL UNDELETED query 
    31353117        if (!empty($this->icache['undeleted_idx']) 
    3136             && $this->icache['undeleted_idx']->getParameters('MAILBOX') == $mailbox 
     3118            && $this->icache['undeleted_idx']->get_parameters('MAILBOX') == $folder 
    31373119        ) { 
    31383120            $data['UNDELETED'] = $this->icache['undeleted_idx']; 
     
    31463128     * Returns extended information about the folder 
    31473129     * 
    3148      * @param string $mailbox Folder name 
     3130     * @param string $folder Folder name 
    31493131     * 
    31503132     * @return array Data 
    31513133     */ 
    3152     function mailbox_info($mailbox) 
    3153     { 
    3154         if ($this->icache['options'] && $this->icache['options']['name'] == $mailbox) { 
     3134    public function folder_info($folder) 
     3135    { 
     3136        if ($this->icache['options'] && $this->icache['options']['name'] == $folder) { 
    31553137            return $this->icache['options']; 
    31563138        } 
     
    31623144        // check if the folder is a namespace prefix 
    31633145        if (!empty($namespace)) { 
    3164             $mbox = $mailbox . $this->delimiter; 
     3146            $mbox = $folder . $this->delimiter; 
    31653147            foreach ($namespace as $ns) { 
    31663148                if (!empty($ns)) { 
     
    31763158        // check if the folder is other user virtual-root 
    31773159        if (!$options['is_root'] && !empty($namespace) && !empty($namespace['other'])) { 
    3178             $parts = explode($this->delimiter, $mailbox); 
     3160            $parts = explode($this->delimiter, $folder); 
    31793161            if (count($parts) == 2) { 
    31803162                $mbox = $parts[0] . $this->delimiter; 
     
    31883170        } 
    31893171 
    3190         $options['name']       = $mailbox; 
    3191         $options['attributes'] = $this->mailbox_attributes($mailbox, true); 
    3192         $options['namespace']  = $this->mailbox_namespace($mailbox); 
    3193         $options['rights']     = $acl && !$options['is_root'] ? (array)$this->my_rights($mailbox) : array(); 
    3194         $options['special']    = in_array($mailbox, $this->default_folders); 
     3172        $options['name']       = $folder; 
     3173        $options['attributes'] = $this->folder_attributes($folder, true); 
     3174        $options['namespace']  = $this->folder_namespace($folder); 
     3175        $options['rights']     = $acl && !$options['is_root'] ? (array)$this->my_rights($folder) : array(); 
     3176        $options['special']    = in_array($folder, $this->default_folders); 
    31953177 
    31963178        // Set 'noselect' and 'norename' flags 
     
    32273209     * Synchronizes messages cache. 
    32283210     * 
    3229      * @param string $mailbox Folder name 
    3230      */ 
    3231     public function mailbox_sync($mailbox) 
     3211     * @param string $folder Folder name 
     3212     */ 
     3213    public function folder_sync($folder) 
    32323214    { 
    32333215        if ($mcache = $this->get_mcache_engine()) { 
    3234             $mcache->synchronize($mailbox); 
     3216            $mcache->synchronize($folder); 
    32353217        } 
    32363218    } 
     
    32423224     * @return string Space-separated list of header names 
    32433225     */ 
    3244     private function get_fetch_headers() 
    3245     { 
    3246         $headers = explode(' ', $this->fetch_add_headers); 
    3247         $headers = array_map('strtoupper', $headers); 
    3248  
    3249         if ($this->messages_caching || $this->get_all_headers) 
     3226    protected function get_fetch_headers() 
     3227    { 
     3228        if (!empty($this->options['fetch_headers'])) { 
     3229            $headers = explode(' ', $this->options['fetch_headers']); 
     3230            $headers = array_map('strtoupper', $headers); 
     3231        } 
     3232        else { 
     3233            $headers = array(); 
     3234        } 
     3235 
     3236        if ($this->messages_caching || $this->options['all_headers']) { 
    32503237            $headers = array_merge($headers, $this->all_headers); 
     3238        } 
    32513239 
    32523240        return implode(' ', array_unique($headers)); 
     
    32593247 
    32603248    /** 
    3261      * Changes the ACL on the specified mailbox (SETACL) 
    3262      * 
    3263      * @param string $mailbox Mailbox name 
     3249     * Changes the ACL on the specified folder (SETACL) 
     3250     * 
     3251     * @param string $folder  Folder name 
    32643252     * @param string $user    User name 
    32653253     * @param string $acl     ACL string 
    32663254     * 
    32673255     * @return boolean True on success, False on failure 
    3268      * 
    3269      * @access public 
    32703256     * @since 0.5-beta 
    32713257     */ 
    3272     function set_acl($mailbox, $user, $acl) 
    3273     { 
    3274         if ($this->get_capability('ACL')) 
    3275             return $this->conn->setACL($mailbox, $user, $acl); 
    3276  
    3277         return false; 
     3258    public function set_acl($folder, $user, $acl) 
     3259    { 
     3260        if (!$this->get_capability('ACL')) { 
     3261            return false; 
     3262        } 
     3263 
     3264        if (!$this->check_connection()) { 
     3265            return false; 
     3266        } 
     3267 
     3268        return $this->conn->setACL($folder, $user, $acl); 
    32783269    } 
    32793270 
     
    32823273     * Removes any <identifier,rights> pair for the 
    32833274     * specified user from the ACL for the specified 
    3284      * mailbox (DELETEACL) 
    3285      * 
    3286      * @param string $mailbox Mailbox name 
     3275     * folder (DELETEACL) 
     3276     * 
     3277     * @param string $folder  Folder name 
    32873278     * @param string $user    User name 
    32883279     * 
    32893280     * @return boolean True on success, False on failure 
    3290      * 
    3291      * @access public 
    32923281     * @since 0.5-beta 
    32933282     */ 
    3294     function delete_acl($mailbox, $user) 
    3295     { 
    3296         if ($this->get_capability('ACL')) 
    3297             return $this->conn->deleteACL($mailbox, $user); 
    3298  
    3299         return false; 
    3300     } 
    3301  
    3302  
    3303     /** 
    3304      * Returns the access control list for mailbox (GETACL) 
    3305      * 
    3306      * @param string $mailbox Mailbox name 
     3283    public function delete_acl($folder, $user) 
     3284    { 
     3285        if (!$this->get_capability('ACL')) { 
     3286            return false; 
     3287        } 
     3288 
     3289        if (!$this->check_connection()) { 
     3290            return false; 
     3291        } 
     3292 
     3293        return $this->conn->deleteACL($folder, $user); 
     3294    } 
     3295 
     3296 
     3297    /** 
     3298     * Returns the access control list for folder (GETACL) 
     3299     * 
     3300     * @param string $folder Folder name 
    33073301     * 
    33083302     * @return array User-rights array on success, NULL on error 
    3309      * @access public 
    33103303     * @since 0.5-beta 
    33113304     */ 
    3312     function get_acl($mailbox) 
    3313     { 
    3314         if ($this->get_capability('ACL')) 
    3315             return $this->conn->getACL($mailbox); 
    3316  
    3317         return NULL; 
     3305    public function get_acl($folder) 
     3306    { 
     3307        if (!$this->get_capability('ACL')) { 
     3308            return null; 
     3309        } 
     3310 
     3311        if (!$this->check_connection()) { 
     3312            return null; 
     3313        } 
     3314 
     3315        return $this->conn->getACL($folder); 
    33183316    } 
    33193317 
     
    33213319    /** 
    33223320     * Returns information about what rights can be granted to the 
    3323      * user (identifier) in the ACL for the mailbox (LISTRIGHTS) 
    3324      * 
    3325      * @param string $mailbox Mailbox name 
     3321     * user (identifier) in the ACL for the folder (LISTRIGHTS) 
     3322     * 
     3323     * @param string $folder  Folder name 
    33263324     * @param string $user    User name 
    33273325     * 
    33283326     * @return array List of user rights 
    3329      * @access public 
    33303327     * @since 0.5-beta 
    33313328     */ 
    3332     function list_rights($mailbox, $user) 
    3333     { 
    3334         if ($this->get_capability('ACL')) 
    3335             return $this->conn->listRights($mailbox, $user); 
    3336  
    3337         return NULL; 
     3329    public function list_rights($folder, $user) 
     3330    { 
     3331        if (!$this->get_capability('ACL')) { 
     3332            return null; 
     3333        } 
     3334 
     3335        if (!$this->check_connection()) { 
     3336            return null; 
     3337        } 
     3338 
     3339        return $this->conn->listRights($folder, $user); 
    33383340    } 
    33393341 
     
    33413343    /** 
    33423344     * Returns the set of rights that the current user has to 
    3343      * mailbox (MYRIGHTS) 
    3344      * 
    3345      * @param string $mailbox Mailbox name 
     3345     * folder (MYRIGHTS) 
     3346     * 
     3347     * @param string $folder Folder name 
    33463348     * 
    33473349     * @return array MYRIGHTS response on success, NULL on error 
    3348      * @access public 
    33493350     * @since 0.5-beta 
    33503351     */ 
    3351     function my_rights($mailbox) 
    3352     { 
    3353         if ($this->get_capability('ACL')) 
    3354             return $this->conn->myRights($mailbox); 
    3355  
    3356         return NULL; 
     3352    public function my_rights($folder) 
     3353    { 
     3354        if (!$this->get_capability('ACL')) { 
     3355            return null; 
     3356        } 
     3357 
     3358        if (!$this->check_connection()) { 
     3359            return null; 
     3360        } 
     3361 
     3362        return $this->conn->myRights($folder); 
    33573363    } 
    33583364 
     
    33613367     * Sets IMAP metadata/annotations (SETMETADATA/SETANNOTATION) 
    33623368     * 
    3363      * @param string $mailbox Mailbox name (empty for server metadata) 
     3369     * @param string $folder  Folder name (empty for server metadata) 
    33643370     * @param array  $entries Entry-value array (use NULL value as NIL) 
    33653371     * 
    33663372     * @return boolean True on success, False on failure 
    3367      * @access public 
    33683373     * @since 0.5-beta 
    33693374     */ 
    3370     function set_metadata($mailbox, $entries) 
    3371     { 
     3375    public function set_metadata($folder, $entries) 
     3376    { 
     3377        if (!$this->check_connection()) { 
     3378            return false; 
     3379        } 
     3380 
    33723381        if ($this->get_capability('METADATA') || 
    3373             (!strlen($mailbox) && $this->get_capability('METADATA-SERVER')) 
     3382            (!strlen($folder) && $this->get_capability('METADATA-SERVER')) 
    33743383        ) { 
    3375             return $this->conn->setMetadata($mailbox, $entries); 
     3384            return $this->conn->setMetadata($folder, $entries); 
    33763385        } 
    33773386        else if ($this->get_capability('ANNOTATEMORE') || $this->get_capability('ANNOTATEMORE2')) { 
     
    33803389                $entries[$entry] = array($ent, $attr, $value); 
    33813390            } 
    3382             return $this->conn->setAnnotation($mailbox, $entries); 
     3391            return $this->conn->setAnnotation($folder, $entries); 
    33833392        } 
    33843393 
     
    33903399     * Unsets IMAP metadata/annotations (SETMETADATA/SETANNOTATION) 
    33913400     * 
    3392      * @param string $mailbox Mailbox name (empty for server metadata) 
     3401     * @param string $folder  Folder name (empty for server metadata) 
    33933402     * @param array  $entries Entry names array 
    33943403     * 
    33953404     * @return boolean True on success, False on failure 
    3396      * 
    3397      * @access public 
    33983405     * @since 0.5-beta 
    33993406     */ 
    3400     function delete_metadata($mailbox, $entries) 
    3401     { 
     3407    public function delete_metadata($folder, $entries) 
     3408    { 
     3409        if (!$this->check_connection()) { 
     3410            return false; 
     3411        } 
     3412 
    34023413        if ($this->get_capability('METADATA') ||  
    3403             (!strlen($mailbox) && $this->get_capability('METADATA-SERVER')) 
     3414            (!strlen($folder) && $this->get_capability('METADATA-SERVER')) 
    34043415        ) { 
    3405             return $this->conn->deleteMetadata($mailbox, $entries); 
     3416            return $this->conn->deleteMetadata($folder, $entries); 
    34063417        } 
    34073418        else if ($this->get_capability('ANNOTATEMORE') || $this->get_capability('ANNOTATEMORE2')) { 
     
    34103421                $entries[$idx] = array($ent, $attr, NULL); 
    34113422            } 
    3412             return $this->conn->setAnnotation($mailbox, $entries); 
     3423            return $this->conn->setAnnotation($folder, $entries); 
    34133424        } 
    34143425 
     
    34203431     * Returns IMAP metadata/annotations (GETMETADATA/GETANNOTATION) 
    34213432     * 
    3422      * @param string $mailbox Mailbox name (empty for server metadata) 
     3433     * @param string $folder  Folder name (empty for server metadata) 
    34233434     * @param array  $entries Entries 
    34243435     * @param array  $options Command options (with MAXSIZE and DEPTH keys) 
    34253436     * 
    34263437     * @return array Metadata entry-value hash array on success, NULL on error 
    3427      * 
    3428      * @access public 
    34293438     * @since 0.5-beta 
    34303439     */ 
    3431     function get_metadata($mailbox, $entries, $options=array()) 
    3432     { 
    3433         if ($this->get_capability('METADATA') ||  
    3434             (!strlen($mailbox) && $this->get_capability('METADATA-SERVER')) 
     3440    public function get_metadata($folder, $entries, $options=array()) 
     3441    { 
     3442        if (!$this->check_connection()) { 
     3443            return null; 
     3444        } 
     3445 
     3446        if ($this->get_capability('METADATA') || 
     3447            (!strlen($folder) && $this->get_capability('METADATA-SERVER')) 
    34353448        ) { 
    3436             return $this->conn->getMetadata($mailbox, $entries, $options); 
     3449            return $this->conn->getMetadata($folder, $entries, $options); 
    34373450        } 
    34383451        else if ($this->get_capability('ANNOTATEMORE') || $this->get_capability('ANNOTATEMORE2')) { 
     
    34473460 
    34483461            // @TODO: Honor MAXSIZE and DEPTH options 
    3449             foreach ($queries as $attrib => $entry) 
    3450                 if ($result = $this->conn->getAnnotation($mailbox, $entry, $attrib)) 
     3462            foreach ($queries as $attrib => $entry) { 
     3463                if ($result = $this->conn->getAnnotation($folder, $entry, $attrib)) { 
    34513464                    $res = array_merge_recursive($res, $result); 
     3465                } 
     3466            } 
    34523467 
    34533468            return $res; 
    34543469        } 
    34553470 
    3456         return NULL; 
     3471        return null; 
    34573472    } 
    34583473 
     
    34663481     * @return array Entry-attribute list, NULL if not supported (?) 
    34673482     */ 
    3468     private function md2annotate($entry) 
     3483    protected function md2annotate($entry) 
    34693484    { 
    34703485        if (substr($entry, 0, 7) == '/shared') { 
    34713486            return array(substr($entry, 7), 'value.shared'); 
    34723487        } 
    3473         else if (substr($entry, 0, 8) == '/private') { 
     3488        else if (substr($entry, 0, 8) == '/protected') { 
    34743489            return array(substr($entry, 8), 'value.priv'); 
    34753490        } 
    34763491 
    34773492        // @TODO: log error 
    3478         return NULL; 
     3493        return null; 
    34793494    } 
    34803495 
     
    34883503     * 
    34893504     * @param string $type Cache type (@see rcmail::get_cache) 
    3490      * @access public 
    3491      */ 
    3492     function set_caching($type) 
     3505     */ 
     3506    public function set_caching($type) 
    34933507    { 
    34943508        if ($type) { 
     
    34963510        } 
    34973511        else { 
    3498             if ($this->cache) 
     3512            if ($this->cache) { 
    34993513                $this->cache->close(); 
     3514            } 
    35003515            $this->cache   = null; 
    35013516            $this->caching = false; 
     
    35063521     * Getter for IMAP cache object 
    35073522     */ 
    3508     private function get_cache_engine() 
     3523    protected function get_cache_engine() 
    35093524    { 
    35103525        if ($this->caching && !$this->cache) { 
     
    35203535     * 
    35213536     * @param string $key Cache key 
     3537     * 
    35223538     * @return mixed 
    3523      * @access public 
    3524      */ 
    3525     function get_cache($key) 
     3539     */ 
     3540    public function get_cache($key) 
    35263541    { 
    35273542        if ($cache = $this->get_cache_engine()) { 
     
    35353550     * @param string $key  Cache key 
    35363551     * @param mixed  $data Data 
    3537      * @access public 
    3538      */ 
    3539     function update_cache($key, $data) 
     3552     */ 
     3553    protected function update_cache($key, $data) 
    35403554    { 
    35413555        if ($cache = $this->get_cache_engine()) { 
     
    35503564     * @param boolean $prefix_mode Enable it to clear all keys starting 
    35513565     *                             with prefix specified in $key 
    3552      * @access public 
    3553      */ 
    3554     function clear_cache($key=null, $prefix_mode=false) 
     3566     */ 
     3567    public function clear_cache($key = null, $prefix_mode = false) 
    35553568    { 
    35563569        if ($cache = $this->get_cache_engine()) { 
     
    35693582     * @param boolean $set Flag 
    35703583     */ 
    3571     function set_messages_caching($set) 
     3584    public function set_messages_caching($set) 
    35723585    { 
    35733586        if ($set) { 
     
    35753588        } 
    35763589        else { 
    3577             if ($this->mcache) 
     3590            if ($this->mcache) { 
    35783591                $this->mcache->close(); 
     3592            } 
    35793593            $this->mcache = null; 
    35803594            $this->messages_caching = false; 
     
    35863600     * Getter for messages cache object 
    35873601     */ 
    3588     private function get_mcache_engine() 
     3602    protected function get_mcache_engine() 
    35893603    { 
    35903604        if ($this->messages_caching && !$this->mcache) { 
     
    35923606            if ($dbh = $rcmail->get_dbh()) { 
    35933607                $this->mcache = new rcube_imap_cache( 
    3594                     $dbh, $this, $rcmail->user->ID, $this->skip_deleted); 
     3608                    $dbh, $this, $rcmail->user->ID, $this->options['skip_deleted']); 
    35953609            } 
    35963610        } 
     
    36033617     * Clears the messages cache. 
    36043618     * 
    3605      * @param string $mailbox Folder name 
     3619     * @param string $folder Folder name 
    36063620     * @param array  $uids    Optional message UIDs to remove from cache 
    36073621     */ 
    3608     function clear_message_cache($mailbox = null, $uids = null) 
     3622    protected function clear_message_cache($folder = null, $uids = null) 
    36093623    { 
    36103624        if ($mcache = $this->get_mcache_engine()) { 
    3611             $mcache->clear($mailbox, $uids); 
     3625            $mcache->clear($folder, $uids); 
    36123626        } 
    36133627    } 
     
    36153629 
    36163630    /* -------------------------------- 
    3617      *         private methods 
     3631     *         protected methods 
    36183632     * --------------------------------*/ 
    36193633 
     
    36233637     * @param string $sort_field Sort column 
    36243638     * @param string $sort_order Sort order 
    3625      * @access private 
    3626      */ 
    3627     private function set_sort_order($sort_field, $sort_order) 
    3628     { 
    3629         if ($sort_field != null) 
     3639     */ 
     3640    protected function set_sort_order($sort_field, $sort_order) 
     3641    { 
     3642        if ($sort_field != null) { 
    36303643            $this->sort_field = asciiwords($sort_field); 
    3631         if ($sort_order != null) 
     3644        } 
     3645        if ($sort_order != null) { 
    36323646            $this->sort_order = strtoupper($sort_order) == 'DESC' ? 'DESC' : 'ASC'; 
    3633     } 
    3634  
    3635  
    3636     /** 
    3637      * Sort mailboxes first by default folders and then in alphabethical order 
    3638      * 
    3639      * @param array $a_folders Mailboxes list 
    3640      * @access private 
    3641      */ 
    3642     private function _sort_mailbox_list($a_folders) 
     3647        } 
     3648    } 
     3649 
     3650 
     3651    /** 
     3652     * Sort folders first by default folders and then in alphabethical order 
     3653     * 
     3654     * @param array $a_folders Folders list 
     3655     */ 
     3656    protected function sort_folder_list($a_folders) 
    36433657    { 
    36443658        $a_out = $a_defaults = $folders = array(); 
     
    36483662        // find default folders and skip folders starting with '.' 
    36493663        foreach ($a_folders as $i => $folder) { 
    3650             if ($folder[0] == '.') 
     3664            if ($folder[0] == '.') { 
    36513665                continue; 
    3652  
    3653             if (($p = array_search($folder, $this->default_folders)) !== false && !$a_defaults[$p]) 
     3666            } 
     3667 
     3668            if (($p = array_search($folder, $this->default_folders)) !== false && !$a_defaults[$p]) { 
    36543669                $a_defaults[$p] = $folder; 
    3655             else 
     3670            } 
     3671            else { 
    36563672                $folders[$folder] = rcube_charset_convert($folder, 'UTF7-IMAP'); 
     3673            } 
    36573674        } 
    36583675 
     
    36703687            $a_out[] = (string) $folder; 
    36713688            unset($folders[$key]); 
    3672             $this->_rsort($folder, $delimiter, $folders, $a_out); 
     3689            $this->rsort($folder, $delimiter, $folders, $a_out); 
    36733690        } 
    36743691 
     
    36783695 
    36793696    /** 
    3680      * @access private 
    3681      */ 
    3682     private function _rsort($folder, $delimiter, &$list, &$out) 
     3697     * Recursive method for sorting folders 
     3698     */ 
     3699    protected function rsort($folder, $delimiter, &$list, &$out) 
    36833700    { 
    36843701        while (list($key, $name) = each($list)) { 
     
    36873704                $out[] = (string) $name; 
    36883705                    unset($list[$key]); 
    3689                     $this->_rsort($name, $delimiter, $list, $out); 
     3706                    $this->rsort($name, $delimiter, $list, $out); 
    36903707                } 
    36913708        } 
     
    36983715     * 
    36993716     * @param int    $id       Message (sequence) ID 
    3700      * @param string $mailbox  Mailbox name 
     3717     * @param string $folder   Folder name 
    37013718     * 
    37023719     * @return int Message UID 
    37033720     */ 
    3704     public function id2uid($id, $mailbox = null) 
    3705     { 
    3706         if (!strlen($mailbox)) { 
    3707             $mailbox = $this->mailbox; 
    3708         } 
    3709  
    3710         if ($uid = array_search($id, (array)$this->uid_id_map[$mailbox])) { 
     3721    public function id2uid($id, $folder = null) 
     3722    { 
     3723        if (!strlen($folder)) { 
     3724            $folder = $this->folder; 
     3725        } 
     3726 
     3727        if ($uid = array_search($id, (array)$this->uid_id_map[$folder])) { 
    37113728            return $uid; 
    37123729        } 
    37133730 
    3714         $uid = $this->conn->ID2UID($mailbox, $id); 
    3715  
    3716         $this->uid_id_map[$mailbox][$uid] = $id; 
     3731        if (!$this->check_connection()) { 
     3732            return null; 
     3733        } 
     3734 
     3735        $uid = $this->conn->ID2UID($folder, $id); 
     3736 
     3737        $this->uid_id_map[$folder][$uid] = $id; 
    37173738 
    37183739        return $uid; 
     
    37213742 
    37223743    /** 
    3723      * Subscribe/unsubscribe a list of mailboxes and update local cache 
    3724      * @access private 
    3725      */ 
    3726     private function _change_subscription($a_mboxes, $mode) 
     3744     * Subscribe/unsubscribe a list of folders and update local cache 
     3745     */ 
     3746    protected function change_subscription($folders, $mode) 
    37273747    { 
    37283748        $updated = false; 
    37293749 
    3730         if (is_array($a_mboxes)) 
    3731             foreach ($a_mboxes as $i => $mailbox) { 
    3732                 $a_mboxes[$i] = $mailbox; 
    3733  
    3734                 if ($mode == 'subscribe') 
    3735                     $updated = $this->conn->subscribe($mailbox); 
    3736                 else if ($mode == 'unsubscribe') 
    3737                     $updated = $this->conn->unsubscribe($mailbox); 
    3738             } 
    3739  
    3740         // clear cached mailbox list(s) 
     3750        if (!empty($folders)) { 
     3751            if (!$this->check_connection()) { 
     3752                return false; 
     3753            } 
     3754 
     3755            foreach ((array)$folders as $i => $folder) { 
     3756                $folders[$i] = $folder; 
     3757 
     3758                if ($mode == 'subscribe') { 
     3759                    $updated = $this->conn->subscribe($folder); 
     3760                } 
     3761                else if ($mode == 'unsubscribe') { 
     3762                    $updated = $this->conn->unsubscribe($folder); 
     3763                } 
     3764            } 
     3765        } 
     3766 
     3767        // clear cached folders list(s) 
    37413768        if ($updated) { 
    37423769            $this->clear_cache('mailboxes', true); 
     
    37483775 
    37493776    /** 
    3750      * Increde/decrese messagecount for a specific mailbox 
    3751      * @access private 
    3752      */ 
    3753     private function _set_messagecount($mailbox, $mode, $increment) 
    3754     { 
     3777     * Increde/decrese messagecount for a specific folder 
     3778     */ 
     3779    protected function set_messagecount($folder, $mode, $increment) 
     3780    { 
     3781        if (!is_numeric($increment)) { 
     3782            return false; 
     3783        } 
     3784 
    37553785        $mode = strtoupper($mode); 
    3756         $a_mailbox_cache = $this->get_cache('messagecount'); 
    3757  
    3758         if (!is_array($a_mailbox_cache[$mailbox]) || !isset($a_mailbox_cache[$mailbox][$mode]) || !is_numeric($increment)) 
     3786        $a_folder_cache = $this->get_cache('messagecount'); 
     3787