Aleksander Machniak
2013-04-29 c6f5adbac33e5a14cce5c093b2b9e69ec39a52c6
program/lib/Roundcube/rcube_imap_generic.php
@@ -1065,8 +1065,8 @@
    /**
     * Executes EXPUNGE command
     *
     * @param string $mailbox  Mailbox name
     * @param string $messages Message UIDs to expunge
     * @param string       $mailbox  Mailbox name
     * @param string|array $messages Message UIDs to expunge
     *
     * @return boolean True on success, False on error
     */
@@ -1084,10 +1084,13 @@
        // Clear internal status cache
        unset($this->data['STATUS:'.$mailbox]);
        if ($messages)
            $result = $this->execute('UID EXPUNGE', array($messages), self::COMMAND_NORESPONSE);
        else
        if (!empty($messages) && $messages != '*' && $this->hasCapability('UIDPLUS')) {
            $messages = self::compressMessageSet($messages);
            $result   = $this->execute('UID EXPUNGE', array($messages), self::COMMAND_NORESPONSE);
        }
        else {
            $result = $this->execute('EXPUNGE', null, self::COMMAND_NORESPONSE);
        }
        if ($result == self::ERROR_OK) {
            $this->selected = null; // state has changed, need to reselect
@@ -1980,7 +1983,6 @@
    /**
     * Moves message(s) from one folder to another.
     * Original message(s) will be marked as deleted.
     *
     * @param string|array  $messages  Message UID(s)
     * @param string        $from      Mailbox name
@@ -1999,15 +2001,41 @@
            return false;
        }
        $r = $this->copy($messages, $from, $to);
        // use MOVE command (RFC 6851)
        if ($this->hasCapability('MOVE')) {
            // Clear last COPYUID data
            unset($this->data['COPYUID']);
        if ($r) {
            // Clear internal status cache
            unset($this->data['STATUS:'.$to]);
            unset($this->data['STATUS:'.$from]);
            $result = $this->execute('UID MOVE', array(
                $this->compressMessageSet($messages), $this->escape($to)),
                self::COMMAND_NORESPONSE);
            return ($result == self::ERROR_OK);
        }
        // use COPY + STORE +FLAGS.SILENT \Deleted + EXPUNGE
        $result = $this->copy($messages, $from, $to);
        if ($result) {
            // Clear internal status cache
            unset($this->data['STATUS:'.$from]);
            return $this->flag($from, $messages, 'DELETED');
            $result = $this->flag($from, $messages, 'DELETED');
            if ($messages == '*') {
                // CLOSE+SELECT should be faster than EXPUNGE
                $this->close();
            }
            else {
                $this->expunge($from, $messages);
            }
        }
        return $r;
        return $result;
    }
    /**
@@ -2237,24 +2265,53 @@
        return $result;
    }
    function fetchHeaders($mailbox, $message_set, $is_uid = false, $bodystr = false, $add = '')
    /**
     * Returns message(s) data (flags, headers, etc.)
     *
     * @param string $mailbox     Mailbox name
     * @param mixed  $message_set Message(s) sequence identifier(s) or UID(s)
     * @param bool   $is_uid      True if $message_set contains UIDs
     * @param bool   $bodystr     Enable to add BODYSTRUCTURE data to the result
     * @param array  $add_headers List of additional headers
     *
     * @return bool|array List of rcube_message_header elements, False on error
     */
    function fetchHeaders($mailbox, $message_set, $is_uid = false, $bodystr = false, $add_headers = array())
    {
        $query_items = array('UID', 'RFC822.SIZE', 'FLAGS', 'INTERNALDATE');
        if ($bodystr)
        $headers     = array('DATE', 'FROM', 'TO', 'SUBJECT', 'CONTENT-TYPE', 'CC', 'REPLY-TO',
            'LIST-POST', 'DISPOSITION-NOTIFICATION-TO', 'X-PRIORITY');
        if (!empty($add_headers)) {
            $add_headers = array_map('strtoupper', $add_headers);
            $headers     = array_unique(array_merge($headers, $add_headers));
        }
        if ($bodystr) {
            $query_items[] = 'BODYSTRUCTURE';
        $query_items[] = 'BODY.PEEK[HEADER.FIELDS ('
            . 'DATE FROM TO SUBJECT CONTENT-TYPE CC REPLY-TO LIST-POST DISPOSITION-NOTIFICATION-TO X-PRIORITY'
            . ($add ? ' ' . trim($add) : '')
            . ')]';
        }
        $query_items[] = 'BODY.PEEK[HEADER.FIELDS (' . implode(' ', $headers) . ')]';
        $result = $this->fetch($mailbox, $message_set, $is_uid, $query_items);
        return $result;
    }
    function fetchHeader($mailbox, $id, $uidfetch=false, $bodystr=false, $add='')
    /**
     * Returns message data (flags, headers, etc.)
     *
     * @param string $mailbox     Mailbox name
     * @param int    $id          Message sequence identifier or UID
     * @param bool   $is_uid      True if $id is an UID
     * @param bool   $bodystr     Enable to add BODYSTRUCTURE data to the result
     * @param array  $add_headers List of additional headers
     *
     * @return bool|rcube_message_header Message data, False on error
     */
    function fetchHeader($mailbox, $id, $is_uid = false, $bodystr = false, $add_headers = array())
    {
        $a = $this->fetchHeaders($mailbox, $id, $uidfetch, $bodystr, $add);
        $a = $this->fetchHeaders($mailbox, $id, $is_uid, $bodystr, $add_headers);
        if (is_array($a)) {
            return array_shift($a);
        }
@@ -2418,6 +2475,7 @@
        $key     = $this->nextTag();
        $request = $key . ($is_uid ? ' UID' : '') . " FETCH $id ($fetch_mode.PEEK[$part]$partial)";
        $result  = false;
        $found   = false;
        // send request
        if (!$this->putLine($request)) {
@@ -2437,18 +2495,25 @@
                break;
            }
            if (!preg_match('/^\* ([0-9]+) FETCH (.*)$/', $line, $m)) {
            // skip irrelevant untagged responses (we have a result already)
            if ($found || !preg_match('/^\* ([0-9]+) FETCH (.*)$/', $line, $m)) {
                continue;
            }
            $line = $m[2];
            $last = substr($line, -1);
            // handle one line response
            if ($line[0] == '(' && $last == ')') {
            if ($line[0] == '(' && substr($line, -1) == ')') {
                // tokenize content inside brackets
                $tokens = $this->tokenizeResponse(preg_replace('/(^\(|\$)/', '', $line));
                $result = count($tokens) == 1 ? $tokens[0] : false;
                $tokens = $this->tokenizeResponse(preg_replace('/(^\(|\)$)/', '', $line));
                for ($i=0; $i<count($tokens); $i+=2) {
                    if (preg_match('/^(BODY|BINARY)/i', $token)) {
                        $result = $tokens[$i+1];
                        $found  = true;
                        break;
                    }
                }
                if ($result !== false) {
                    if ($mode == 1) {
@@ -2466,6 +2531,7 @@
            else if (preg_match('/\{([0-9]+)\}$/', $line, $m)) {
                $bytes = (int) $m[1];
                $prev  = '';
                $found = true;
                while ($bytes > 0) {
                    $line = $this->readLine(8192);
@@ -3502,7 +3568,7 @@
            // if less than 255 bytes long, let's not bother
            if (!$force && strlen($messages)<255) {
                return $messages;
           }
            }
            // see if it's already been compressed
            if (strpos($messages, ':') !== false) {
@@ -3610,8 +3676,20 @@
     */
    static function strToTime($date)
    {
        // support non-standard "GMTXXXX" literal
        $date = preg_replace('/GMT\s*([+-][0-9]+)/', '\\1', $date);
        // Clean malformed data
        $date = preg_replace(
            array(
                '/GMT\s*([+-][0-9]+)/',                     // support non-standard "GMTXXXX" literal
                '/[^a-z0-9\x20\x09:+-]/i',                  // remove any invalid characters
                '/\s*(Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s*/i',   // remove weekday names
            ),
            array(
                '\\1',
                '',
                '',
            ), $date);
        $date = trim($date);
        // if date parsing fails, we have a date in non-rfc format
        // remove token from the end and try again