Thomas Bruederli
2012-08-09 a8e478c07cd0a954e2d061b49a18ee9fc1552f6e
program/include/rcube_imap_generic.php
@@ -1557,6 +1557,11 @@
        }
        if (!$this->select($mailbox)) {
        }
        // RFC 5957: SORT=DISPLAY
        if (($field == 'FROM' || $field == 'TO') && $this->getCapability('SORT=DISPLAY')) {
            $field = 'DISPLAY' . $field;
            return null;
        }
@@ -2242,12 +2247,29 @@
        list($code, $response) = $this->execute($subscribed ? 'LSUB' : 'LIST', $args);
        if ($code == self::ERROR_OK) {
            $folders = array();
            while ($this->tokenizeResponse($response, 1) == '*') {
                $cmd = strtoupper($this->tokenizeResponse($response, 1));
            $folders  = array();
            $last     = 0;
            $pos      = 0;
            $response .= "\r\n";
            while ($pos = strpos($response, "\r\n", $pos+1)) {
                // literal string, not real end-of-command-line
                if ($response[$pos-1] == '}') {
                    continue;
                }
                $line = substr($response, $last, $pos - $last);
                $last = $pos + 2;
                if (!preg_match('/^\* (LIST|LSUB|STATUS) /i', $line, $m)) {
                    continue;
                }
                $cmd  = strtoupper($m[1]);
                $line = substr($line, strlen($m[0]));
                // * LIST (<options>) <delimiter> <mailbox>
                if ($cmd == 'LIST' || $cmd == 'LSUB') {
                    list($opts, $delim, $mailbox) = $this->tokenizeResponse($response, 3);
                    list($opts, $delim, $mailbox) = $this->tokenizeResponse($line, 3);
                    // Add to result array
                    if (!$lstatus) {
@@ -2257,31 +2279,25 @@
                        $folders[$mailbox] = array();
                    }
                    // Add to options array
                    if (!empty($opts)) {
                    // store LSUB options only if not empty, this way
                    // we can detect a situation when LIST doesn't return specified folder
                    if (!empty($opts) || $cmd == 'LIST') {
                        // Add to options array
                        if (empty($this->data['LIST'][$mailbox]))
                            $this->data['LIST'][$mailbox] = $opts;
                        else
                        else if (!empty($opts))
                            $this->data['LIST'][$mailbox] = array_unique(array_merge(
                                $this->data['LIST'][$mailbox], $opts));
                    }
                }
                // * STATUS <mailbox> (<result>)
                else if ($cmd == 'STATUS') {
                    list($mailbox, $status) = $this->tokenizeResponse($response, 2);
                    list($mailbox, $status) = $this->tokenizeResponse($line, 2);
                    for ($i=0, $len=count($status); $i<$len; $i += 2) {
                        list($name, $value) = $this->tokenizeResponse($status, 2);
                        $folders[$mailbox][$name] = $value;
                    }
                }
                // other untagged response line, skip it
                else {
                    $response = ltrim($response);
                    if (($position = strpos($response, "\n")) !== false)
                        $response = substr($response, $position+1);
                    else
                        $response = '';
                }
            }
@@ -2393,8 +2409,10 @@
        $len    = strlen($line);
        $result = false;
        if ($a[2] != 'FETCH') {
        }
        // handle empty "* X FETCH ()" response
        if ($line[$len-1] == ')' && $line[$len-2] != '(') {
        else if ($line[$len-1] == ')' && $line[$len-2] != '(') {
            // one line response, get everything between first and last quotes
            if (substr($line, -4, 3) == 'NIL') {
                // NIL response
@@ -3174,47 +3192,48 @@
        return false;
    }
    static function getStructurePartType($structure, $part)
    /**
     * Returns data of a message part according to specified structure.
     *
     * @param array  $structure Message structure (getStructure() result)
     * @param string $part      Message part identifier
     *
     * @return array Part data as hash array (type, encoding, charset, size)
     */
    static function getStructurePartData($structure, $part)
    {
       $part_a = self::getStructurePartArray($structure, $part);
       if (!empty($part_a)) {
          if (is_array($part_a[0]))
                return 'multipart';
          else if ($part_a[0])
                return $part_a[0];
       }
       $data   = array();
        return 'other';
    }
       if (empty($part_a)) {
            return $data;
        }
    static function getStructurePartEncoding($structure, $part)
    {
       $part_a = self::getStructurePartArray($structure, $part);
       if ($part_a) {
          if (!is_array($part_a[0]))
                return $part_a[5];
       }
        // content-type
        if (is_array($part_a[0])) {
            $data['type'] = 'multipart';
        }
        else {
            $data['type'] = strtolower($part_a[0]);
        return '';
    }
            // encoding
            $data['encoding'] = strtolower($part_a[5]);
    static function getStructurePartCharset($structure, $part)
    {
       $part_a = self::getStructurePartArray($structure, $part);
       if ($part_a) {
          if (is_array($part_a[0]))
                return '';
          else {
             if (is_array($part_a[2])) {
                $name = '';
                while (list($key, $val) = each($part_a[2]))
                        if (strcasecmp($val, 'charset') == 0)
                            return $part_a[2][$key+1];
             }
          }
       }
            // charset
            if (is_array($part_a[2])) {
               while (list($key, $val) = each($part_a[2])) {
                    if (strcasecmp($val, 'charset') == 0) {
                        $data['charset'] = $part_a[2][$key+1];
                        break;
                    }
                }
            }
        }
        return '';
        // size
        $data['size'] = intval($part_a[6]);
        return $data;
    }
    static function getStructurePartArray($a, $part)
@@ -3222,31 +3241,32 @@
       if (!is_array($a)) {
            return false;
        }
        if (empty($part)) {
          return $a;
       }
        $ctype = is_string($a[0]) && is_string($a[1]) ? $a[0] . '/' . $a[1] : '';
        if (strcasecmp($ctype, 'message/rfc822') == 0) {
            $a = $a[8];
        }
       if (strpos($part, '.') > 0) {
          $original_part = $part;
          $pos = strpos($part, '.');
          $rest = substr($original_part, $pos+1);
          $part = substr($original_part, 0, $pos);
          if ((strcasecmp($a[0], 'message') == 0) && (strcasecmp($a[1], 'rfc822') == 0)) {
             $a = $a[8];
          }
          $orig_part = $part;
          $pos       = strpos($part, '.');
          $rest      = substr($orig_part, $pos+1);
          $part      = substr($orig_part, 0, $pos);
          return self::getStructurePartArray($a[$part-1], $rest);
       }
        else if ($part>0) {
          if (!is_array($a[0]) && (strcasecmp($a[0], 'message') == 0)
                && (strcasecmp($a[1], 'rfc822') == 0)) {
             $a = $a[8];
          }
        else if ($part > 0) {
          if (is_array($a[$part-1]))
                return $a[$part-1];
          else
                return $a;
       }
        else if (($part == 0) || (empty($part))) {
          return $a;
       }
    }
    /**
     * Creates next command identifier (tag)
@@ -3390,14 +3410,9 @@
            // String atom, number, NIL, *, %
            default:
                // empty or one character
                if ($str === '') {
                // empty string
                if ($str === '' || $str === null) {
                    break 2;
                }
                if (strlen($str) < 2) {
                    $result[] = $str;
                    $str = '';
                    break;
                }
                // excluded chars: SP, CTL, ), [, ]
@@ -3496,13 +3511,16 @@
        if ($string === null) {
            return 'NIL';
        }
        if ($string === '') {
            return '""';
        }
        // atom-string (only safe characters)
        if (!$force_quotes && !preg_match('/[\x00-\x20\x22\x28-\x2A\x5B-\x5D\x7B\x7D\x80-\xFF]/', $string)) {
        if (!$force_quotes && !preg_match('/[\x00-\x20\x22\x25\x28-\x2A\x5B-\x5D\x7B\x7D\x80-\xFF]/', $string)) {
            return $string;
        }
        // quoted-string
        if (!preg_match('/[\r\n\x00\x80-\xFF]/', $string)) {
            return '"' . addcslashes($string, '\\"') . '"';