alecpl
2009-01-22 4f27148d400661c81005b496ac7c05b6c6ed9483
program/include/rcube_imap.php
@@ -5,7 +5,7 @@
 | program/include/rcube_imap.php                                        |
 |                                                                       |
 | This file is part of the RoundCube Webmail client                     |
 | Copyright (C) 2005-2008, RoundCube Dev. - Switzerland                 |
 | Copyright (C) 2005-2009, RoundCube Dev. - Switzerland                 |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | PURPOSE:                                                              |
@@ -66,6 +66,7 @@
  var $search_sort_field = '';  
  var $debug_level = 1;
  var $error_code = 0;
  var $options = array('imap' => 'check');
  /**
@@ -90,7 +91,7 @@
   * @return boolean  TRUE on success, FALSE on failure
   * @access public
   */
  function connect($host, $user, $pass, $port=143, $use_ssl=null, $auth_type=null)
  function connect($host, $user, $pass, $port=143, $use_ssl=null)
    {
    global $ICL_SSL, $ICL_PORT, $IMAP_USE_INTERNAL_DATE;
    
@@ -107,17 +108,7 @@
    $ICL_PORT = $port;
    $IMAP_USE_INTERNAL_DATE = false;
    // set connection options
    $options['imap'] = $auth_type ? $auth_type : 'check';
    // Setting root and delimiter before iil_Connect can save time detecting them
    // using NAMESPACE and LIST
    if (is_string($imap_root = rcmail::get_instance()->config->get('imap_root')))
        $options['rootdir'] = $imap_root;
    if($imap_delimiter = rcmail::get_instance()->config->get('imap_delimiter'))
        $options['delimiter'] = $imap_delimiter;
    $this->conn = iil_Connect($host, $user, $pass, $options);
    $this->conn = iil_Connect($host, $user, $pass, $this->options);
    $this->host = $host;
    $this->user = $user;
    $this->pass = $pass;
@@ -182,6 +173,13 @@
      iil_C_Select($this->conn, $this->mailbox);
    }
  /**
   * Set options to be used in iil_Connect()
   */
  function set_options($opt)
  {
    $this->options = array_merge($this->options, (array)$opt);
  }
  /**
   * Set a root folder for the IMAP connection.
@@ -198,6 +196,7 @@
      $root = substr($root, 0, -1);
    $this->root_dir = $root;
    $this->options['rootdir'] = $root;
    
    if (empty($this->delimiter))
      $this->get_hierarchy_delimiter();
@@ -1048,9 +1047,10 @@
   * @param int     Message ID
   * @param string  Mailbox to read from 
   * @param boolean True if $id is the message UID
   * @param boolean True if we need also BODYSTRUCTURE in headers
   * @return object Message headers representation
   */
  function get_headers($id, $mbox_name=NULL, $is_uid=TRUE)
  function get_headers($id, $mbox_name=NULL, $is_uid=TRUE, $bodystr=FALSE)
    {
    $mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $this->mailbox;
    $uid = $is_uid ? $id : $this->_id2uid($id);
@@ -1059,7 +1059,7 @@
    if ($uid && ($headers = &$this->get_cached_message($mailbox.'.msg', $uid)))
      return $headers;
    $headers = iil_C_FetchHeader($this->conn, $mailbox, $id, $is_uid);
    $headers = iil_C_FetchHeader($this->conn, $mailbox, $id, $is_uid, $bodystr);
    // write headers cache
    if ($headers)
@@ -1079,9 +1079,10 @@
   * an object structure similar to the one generated by PEAR::Mail_mimeDecode
   *
   * @param int Message UID to fetch
   * @param string Message BODYSTRUCTURE string (optional)
   * @return object rcube_message_part Message part tree or False on failure
   */
  function &get_structure($uid)
  function &get_structure($uid, $structure_str='')
    {
    $cache_key = $this->mailbox.'.msg';
    $headers = &$this->get_cached_message($cache_key, $uid, true);
@@ -1096,7 +1097,8 @@
      return FALSE;
    }
    $structure_str = iil_C_FetchStructureString($this->conn, $this->mailbox, $msg_id);
    if (!$structure_str)
      $structure_str = iil_C_FetchStructureString($this->conn, $this->mailbox, $msg_id);
    $structure = iml_GetRawStructureArray($structure_str);
    $struct = false;
@@ -1131,7 +1133,7 @@
   *
   * @access private
   */
  function &_structure_part($part, $count=0, $parent='')
  function &_structure_part($part, $count=0, $parent='', $raw_headers=null)
    {
    $struct = new rcube_message_part;
    $struct->mime_id = empty($parent) ? (string)$count : "$parent.$count";
@@ -1151,11 +1153,25 @@
          
      $struct->mimetype = 'multipart/'.$struct->ctype_secondary;
      // build parts list for headers pre-fetching
      for ($i=0, $count=0; $i<count($part); $i++)
        if (is_array($part[$i]) && count($part[$i]) > 3)
     // fetch message headers if message/rfc822 or named part (could contain Content-Location header)
     if (strtolower($part[$i][0]) == 'message' ||
       (in_array('name', (array)$part[$i][2]) && (empty($part[$i][3]) || $part[$i][3]=='NIL'))) {
       $part_headers[] = $struct->mime_id ? $struct->mime_id.'.'.$i+1 : $i+1;
       }
      // pre-fetch headers of all parts (in one command for better performance)
      if ($part_headers)
        $part_headers = iil_C_FetchMIMEHeaders($this->conn, $this->mailbox, $this->_msg_id, $part_headers);
      $struct->parts = array();
      for ($i=0, $count=0; $i<count($part); $i++)
        if (is_array($part[$i]) && count($part[$i]) > 3)
          $struct->parts[] = $this->_structure_part($part[$i], ++$count, $struct->mime_id);
          $struct->parts[] = $this->_structure_part($part[$i], ++$count, $struct->mime_id,
      $part_headers[$struct->mime_id ? $struck->mime_id.'.'.$i+1 : $i+1]);
      return $struct;
      }
    
@@ -1220,8 +1236,9 @@
    
    // fetch message headers if message/rfc822 or named part (could contain Content-Location header)
    if ($struct->ctype_primary == 'message' || ($struct->ctype_parameters['name'] && !$struct->content_id)) {
      $part_headers = iil_C_FetchPartHeader($this->conn, $this->mailbox, $this->_msg_id, $struct->mime_id);
      $struct->headers = $this->_parse_headers($part_headers) + $struct->headers;
      if (empty($raw_headers))
        $raw_headers = iil_C_FetchPartHeader($this->conn, $this->mailbox, $this->_msg_id, $struct->mime_id);
      $struct->headers = $this->_parse_headers($raw_headers) + $struct->headers;
    }
    if ($struct->ctype_primary=='message') {
@@ -1487,34 +1504,36 @@
   *
   * @param mixed  Message UIDs as array or as comma-separated string
   * @param string Flag to set: SEEN, UNDELETED, DELETED, RECENT, ANSWERED, DRAFT, MDNSENT
   * @param boolean Simulate flagging (don't set flag on IMAP server)
   * @return boolean True on success, False on failure
   */
  function set_flag($uids, $flag)
  function set_flag($uids, $flag, $fake=false)
    {
    $flag = strtoupper($flag);
    $msg_ids = array();
    if (!is_array($uids))
      $uids = explode(',',$uids);
      
    foreach ($uids as $uid) {
      $msg_ids[$uid] = $this->_uid2id($uid);
    }
    if ($flag=='UNDELETED')
      $result = iil_C_Undelete($this->conn, $this->mailbox, join(',', array_values($msg_ids)));
    else if ($flag=='UNSEEN')
      $result = iil_C_Unseen($this->conn, $this->mailbox, join(',', array_values($msg_ids)));
    else if ($flag=='UNFLAGGED')
      $result = iil_C_UnFlag($this->conn, $this->mailbox, join(',', array_values($msg_ids)), 'FLAGGED');
    else
      $result = iil_C_Flag($this->conn, $this->mailbox, join(',', array_values($msg_ids)), $flag);
    if (!$fake || $this->caching_enabled)
      foreach ($uids as $uid) {
        $msg_ids[$uid] = $this->_uid2id($uid);
      }
    if (!$fake) {
      if ($flag=='UNDELETED')
        $result = iil_C_Undelete($this->conn, $this->mailbox, join(',', array_values($msg_ids)));
      else if ($flag=='UNSEEN')
        $result = iil_C_Unseen($this->conn, $this->mailbox, join(',', array_values($msg_ids)));
      else if ($flag=='UNFLAGGED')
        $result = iil_C_UnFlag($this->conn, $this->mailbox, join(',', array_values($msg_ids)), 'FLAGGED');
      else
        $result = iil_C_Flag($this->conn, $this->mailbox, join(',', array_values($msg_ids)), $flag);
      }
    // reload message headers if cached
    $cache_key = $this->mailbox.'.msg';
    if ($this->caching_enabled)
      {
      foreach ($msg_ids as $uid => $id)
        {
    if ($this->caching_enabled) {
      $cache_key = $this->mailbox.'.msg';
      foreach ($msg_ids as $uid => $id) {
        if ($cached_headers = $this->get_cached_message($cache_key, $uid))
          {
          $this->remove_message_cache($cache_key, $id);
@@ -1528,7 +1547,7 @@
      }
    // set nr of messages that were flaged
    $count = count($msg_ids);
    $count = count($uids);
    // clear message count cache
    if ($result && $flag=='SEEN')
@@ -1551,7 +1570,6 @@
   */
  function save_message($mbox_name, &$message)
    {
    $mbox_name = stripslashes($mbox_name);
    $mailbox = $this->_mod_mailbox($mbox_name);
    // make sure mailbox exists
@@ -1578,9 +1596,7 @@
   */
  function move_message($uids, $to_mbox, $from_mbox='')
    {
    $to_mbox_in = stripslashes($to_mbox);
    $from_mbox = stripslashes($from_mbox);
    $to_mbox = $this->_mod_mailbox($to_mbox_in);
    $to_mbox = $this->_mod_mailbox($to_mbox);
    $from_mbox = $from_mbox ? $this->_mod_mailbox($from_mbox) : $this->mailbox;
    // make sure mailbox exists
@@ -1655,7 +1671,6 @@
   */
  function delete_message($uids, $mbox_name='')
    {
    $mbox_name = stripslashes($mbox_name);
    $mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $this->mailbox;
    // convert the list of uids to array
@@ -1712,7 +1727,6 @@
   */
  function clear_mailbox($mbox_name=NULL)
    {
    $mbox_name = stripslashes($mbox_name);
    $mailbox = !empty($mbox_name) ? $this->_mod_mailbox($mbox_name) : $this->mailbox;
    $msg_count = $this->_messagecount($mailbox, 'ALL');
    
@@ -1745,7 +1759,6 @@
   */
  function expunge($mbox_name='', $clear_cache=TRUE)
    {
    $mbox_name = stripslashes($mbox_name);
    $mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $this->mailbox;
    return $this->_expunge($mailbox, $clear_cache);
    }
@@ -1864,9 +1877,6 @@
    {
    $result = FALSE;
    
    // replace backslashes
    $name = preg_replace('/[\\\]+/', '-', $name);
    // reduce mailbox name to 100 chars
    $name = substr($name, 0, 100);
@@ -1895,9 +1905,6 @@
    {
    $result = FALSE;
    // replace backslashes
    $name = preg_replace('/[\\\]+/', '-', $new_name);
    // encode mailbox name and reduce it to 100 chars
    $name = substr($new_name, 0, 100);
@@ -2342,7 +2349,7 @@
    {
    if (empty($key) || !is_object($headers) || empty($headers->uid))
        return;
    // add to internal (fast) cache
    $this->cache['__single_msg'][$headers->uid] = $headers;
    $this->cache['__single_msg'][$headers->uid]->structure = $struct;
@@ -2916,7 +2923,7 @@
    // remove any newlines and carriage returns before
    $a = $this->_explode_quoted_string('[,;]', preg_replace( "/[\r\n]/", " ", $str));
    $result = array();
    foreach ($a as $key => $val)
      {
      $val = preg_replace("/([\"\w])</", "$1 <", $val);
@@ -2925,14 +2932,17 @@
      foreach ($sub_a as $k => $v)
        {
        if (strpos($v, '@') > 0)
          $result[$key]['address'] = str_replace('<', '', str_replace('>', '', $v));
   // use angle brackets in regexp to not handle names with @ sign
        if (preg_match('/^<\S+@\S+>$/', $v))
          $result[$key]['address'] = trim($v, '<>');
        else
          $result[$key]['name'] .= (empty($result[$key]['name'])?'':' ').str_replace("\"",'',stripslashes($v));
        }
        
      if (empty($result[$key]['name']))
        $result[$key]['name'] = $result[$key]['address'];
        $result[$key]['name'] = $result[$key]['address'];
      elseif (empty($result[$key]['address']))
   $result[$key]['address'] = $result[$key]['name'];
      }
    
    return $result;