Changeset 1d51658 in github


Ignore:
Timestamp:
May 18, 2010 7:58:12 AM (3 years ago)
Author:
alecpl <alec@…>
Branches:
master, HEAD, courier-fix, dev-browser-capabilities, pdo, release-0.6, release-0.7, release-0.8
Children:
6a86d272
Parents:
30aa4cc
Message:
  • Parse untagged CAPABILITY response for LOGIN command (#1486742)
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • CHANGELOG

    r30aa4cc r1d51658  
    22=========================== 
    33 
     4- Parse untagged CAPABILITY response for LOGIN command (#1486742) 
    45- Renamed all php-cli scripts to use .sh extension 
    56- Some files from /bin + spellchecking actions moved to the new 'utils' task 
  • program/include/rcube_imap_generic.php

    r3978cbf4 r1d51658  
    3131 * 
    3232 * @package    Mail 
    33  * @author     Aleksander Machniak <alec@alec.pl>  
     33 * @author     Aleksander Machniak <alec@alec.pl> 
    3434 */ 
    3535class rcube_mail_header 
     
    8181 * 
    8282 * @package    Mail 
    83  * @author     Aleksander Machniak <alec@alec.pl>  
     83 * @author     Aleksander Machniak <alec@alec.pl> 
    8484 */ 
    8585class rcube_imap_generic 
     
    119119    { 
    120120    } 
    121                
     121 
    122122    private function putLine($string, $endln=true) 
    123123    { 
     
    128128                write_log('imap', 'C: '. rtrim($string)); 
    129129            } 
    130          
     130 
    131131        return fputs($this->fp, $string . ($endln ? "\r\n" : '')); 
    132132    } 
     
    174174                return NULL; 
    175175            } 
    176      
     176 
    177177            if (!$size) { 
    178178                    $size = 1024; 
    179179            } 
    180      
     180 
    181181            do { 
    182182                    if (feof($this->fp)) { 
    183183                            return $line ? $line : NULL; 
    184184                    } 
    185                  
     185 
    186186                $buffer = fgets($this->fp, $size); 
    187187 
     
    205205            if (preg_match('/\{[0-9]+\}$/', $line)) { 
    206206                    $out = ''; 
    207          
     207 
    208208                    preg_match_all('/(.*)\{([0-9]+)\}$/', $line, $a); 
    209209                    $bytes = $a[2][0]; 
    210210                    while (strlen($out) < $bytes) { 
    211                             $line = $this->readBytes($bytes);  
     211                            $line = $this->readBytes($bytes); 
    212212                            if ($line === NULL) 
    213213                                    break; 
     
    217217                    $line = $a[1][0] . '"' . ($escape ? $this->Escape($out) : $out) . '"'; 
    218218            } 
    219          
     219 
    220220        return $line; 
    221221    } 
     
    238238                $len = $data_len; 
    239239            } 
    240          
     240 
    241241            return $data; 
    242242    } 
    243243 
    244244    // don't use it in loops, until you exactly know what you're doing 
    245     private function readReply() 
     245    private function readReply($untagged=null) 
    246246    { 
    247247            do { 
    248248                    $line = trim($this->readLine(1024)); 
     249            // store untagged response lines 
     250                    if ($line[0] == '*') 
     251                $untagged[] = $line; 
    249252            } while ($line[0] == '*'); 
     253 
     254        if ($untagged) 
     255            $untagged = join("\n", $untagged); 
    250256 
    251257            return $line; 
     
    332338            } 
    333339 
    334             // get capabilities (only once) because initial  
     340            // get capabilities (only once) because initial 
    335341            // optional CAPABILITY response may differ 
    336342            $this->capability = array(); 
     
    349355                    } 
    350356            } while ($a[0] != 'cp01'); 
    351          
     357 
    352358            $this->capability_readed = true; 
    353359 
     
    369375        $ipad = ''; 
    370376        $opad = ''; 
    371      
     377 
    372378        // initialize ipad, opad 
    373379        for ($i=0; $i<64; $i++) { 
     
    381387            $pass .= chr(0); 
    382388        } 
    383      
     389 
    384390        // generate hash 
    385391        $hash  = md5($this->_xor($pass,$opad) . pack("H*", md5($this->_xor($pass, $ipad) . base64_decode($encChallenge)))); 
    386      
     392 
    387393        // generate reply 
    388394        $reply = base64_encode($user . ' ' . $hash); 
    389      
     395 
    390396        // send result, get reply 
    391397        $this->putLine($reply); 
    392398        $line = $this->readLine(1024); 
    393      
     399 
    394400        // process result 
    395401        $result = $this->parseResult($line); 
     
    409415        $this->putLine('a001 LOGIN "'.$this->escape($user).'" "'.$this->escape($password).'"'); 
    410416 
    411         $line = $this->readReply(); 
     417        $line = $this->readReply($untagged); 
     418 
     419        // re-set capabilities list if untagged CAPABILITY response provided 
     420            if (preg_match('/\* CAPABILITY (.+)/i', $untagged, $matches)) { 
     421                    $this->capability = explode(' ', strtoupper($matches[1])); 
     422            } 
    412423 
    413424        // process result 
     
    421432        @fclose($this->fp); 
    422433        $this->fp = false; 
    423      
     434 
    424435        $this->error    = "Authentication for $user failed (LOGIN): $line"; 
    425436        $this->errornum = $result; 
     
    434445                    return true; 
    435446            } 
    436          
     447 
    437448        if (!$this->getCapability('NAMESPACE')) { 
    438449                return false; 
    439450            } 
    440      
     451 
    441452            if (!$this->putLine("ns1 NAMESPACE")) { 
    442453            return false; 
     
    464475                return false; 
    465476            } 
    466      
     477 
    467478            $this->rootdir            = $first_userspace[0]; 
    468479            $this->delimiter          = $first_userspace[1]; 
    469480            $this->prefs['rootdir']   = substr($this->rootdir, 0, -1); 
    470481            $this->prefs['delimiter'] = $this->delimiter; 
    471          
     482 
    472483            return true; 
    473484    } 
     
    479490     * INBOX/foo -> / 
    480491     * INBOX\foo -> \ 
    481      *  
    482      * @return mixed A delimiter (string), or false.  
     492     * 
     493     * @return mixed A delimiter (string), or false. 
    483494     * @see connect() 
    484495     */ 
     
    498509                return false; 
    499510            } 
    500      
     511 
    501512            do { 
    502513                    $line = $this->readLine(500); 
     
    532543                return false; 
    533544            } 
    534      
     545 
    535546            // extract user space data (opposed to global/shared space) 
    536547            $user_space_data = $data[0]; 
     
    546557 
    547558            // extract delimiter 
    548             $delimiter = $first_userspace[1];    
     559            $delimiter = $first_userspace[1]; 
    549560 
    550561            return $delimiter; 
     
    567578 
    568579            $result = false; 
    569          
     580 
    570581            // initialize connection 
    571582            $this->error    = ''; 
     
    649660                                    return false; 
    650661                            } 
    651                          
     662 
    652663                            // Now we're authenticated, capabilities need to be reread 
    653664                            $this->clearCapability(); 
     
    676687                            // got a challenge string, try CRAM-MD5 
    677688                            $result = $this->authenticate($user, $password, substr($line,2)); 
    678                          
     689 
    679690                            // stop if server sent BYE response 
    680691                            if ($result == -3) { 
     
    682693                            } 
    683694                    } 
    684                  
     695 
    685696                    if (!is_resource($result) && $orig_method == 'CHECK') { 
    686697                            $auth_method = 'PLAIN'; 
    687698                    } 
    688699            } 
    689                  
     700 
    690701            if ($auth_method == 'PLAIN') { 
    691702                    // do plain text auth 
     
    728739                    return true; 
    729740            } 
    730      
     741 
    731742            if ($this->putLine("sel1 SELECT \"".$this->escape($mailbox).'"')) { 
    732743                    do { 
     
    764775                    $mailbox = 'INBOX'; 
    765776            } 
    766      
     777 
    767778            $this->select($mailbox); 
    768779            if ($this->selected == $mailbox) { 
     
    778789                    $this->selected = ''; 
    779790            } 
    780          
     791 
    781792            $this->select($mailbox); 
    782793            if ($this->selected == $mailbox) { 
     
    793804                $field = 'ARRIVAL'; 
    794805            } 
    795          
     806 
    796807            $fields = array('ARRIVAL' => 1,'CC' => 1,'DATE' => 1, 
    797808            'FROM' => 1, 'SIZE' => 1, 'SUBJECT' => 1, 'TO' => 1); 
     
    805816                return false; 
    806817            } 
    807      
     818 
    808819            $is_uid = $is_uid ? 'UID ' : ''; 
    809          
     820 
    810821            // message IDs 
    811822            if (is_array($add)) 
     
    829840                    } 
    830841            } while (!$this->startsWith($line, 's ', true, true)); 
    831          
     842 
    832843            $result_code = $this->parseResult($line); 
    833          
     844 
    834845            if ($result_code != 0) { 
    835846            $this->error = "Sort: $line"; 
    836847            return false; 
    837848            } 
    838          
     849 
    839850            return preg_split('/\s+/', $data, -1, PREG_SPLIT_NO_EMPTY); 
    840851    } 
     
    852863                    } 
    853864            } 
    854          
     865 
    855866            $index_field = empty($index_field) ? 'DATE' : strtoupper($index_field); 
    856          
     867 
    857868        $fields_a['DATE']         = 1; 
    858869            $fields_a['INTERNALDATE'] = 4; 
     
    878889                    return false; 
    879890            } 
    880          
     891 
    881892        // build FETCH command string 
    882893            $key     = 'fhi0'; 
     
    913924                $id     = $m[1]; 
    914925                            $flags  = NULL; 
    915                                          
     926 
    916927                            if ($skip_deleted && preg_match('/FLAGS \(([^)]+)\)/', $line, $matches)) { 
    917928                                    $flags = explode(' ', strtoupper($matches[1])); 
     
    963974            } while (!$this->startsWith($line, $key, true, true)); 
    964975 
    965             return $result;      
     976            return $result; 
    966977    } 
    967978 
    968979    private function compressMessageSet($message_set) 
    969980    { 
    970             // given a comma delimited list of independent mid's,  
     981            // given a comma delimited list of independent mid's, 
    971982            // compresses by grouping sequences together 
    972          
     983 
    973984            // if less than 255 bytes long, let's not bother 
    974985            if (strlen($message_set)<255) { 
    975986                return $message_set; 
    976987            } 
    977      
     988 
    978989            // see if it's already been compress 
    979990            if (strpos($message_set, ':') !== false) { 
    980991                return $message_set; 
    981992            } 
    982      
     993 
    983994            // separate, then sort 
    984995            $ids = explode(',', $message_set); 
    985996            sort($ids); 
    986          
     997 
    987998            $result = array(); 
    988999            $start  = $prev = $ids[0]; 
     
    10071018            $result[] = $start.':'.$prev; 
    10081019            } 
    1009      
     1020 
    10101021            // return as comma separated string 
    10111022            return implode(',', $result); 
     
    10521063        else if (empty($message_set)) 
    10531064                    $message_set = '1:*'; 
    1054          
     1065 
    10551066            return $this->fetchHeaderIndex($mailbox, $message_set, 'UID', false); 
    10561067    } 
     
    10591070    { 
    10601071            $result = array(); 
    1061          
     1072 
    10621073            if (!$this->select($mailbox)) { 
    10631074                    return false; 
     
    10901101                    $line = $this->readLine(1024); 
    10911102                    $line = $this->multLine($line); 
    1092              
     1103 
    10931104            if (!$line) 
    10941105                break; 
    1095              
     1106 
    10961107                    $a    = explode(' ', $line); 
    10971108 
    10981109                    if (($line[0] == '*') && ($a[2] == 'FETCH')) { 
    10991110                            $id = $a[1]; 
    1100              
     1111 
    11011112                            $result[$id]            = new rcube_mail_header; 
    11021113                            $result[$id]->id        = $id; 
     
    11341145 
    11351146                                            $time_str = str_replace('"', '', $time_str); 
    1136                                          
     1147 
    11371148                                            // if time is gmt... 
    11381149                                $time_str = str_replace('GMT','+0000',$time_str); 
    1139                                          
     1150 
    11401151                                            $result[$id]->internaldate = $time_str; 
    11411152                                        $result[$id]->timestamp = $this->StrToTime($time_str); 
     
    11431154                                } 
    11441155 
    1145                                 // BODYSTRUCTURE  
     1156                                // BODYSTRUCTURE 
    11461157                                    if($bodystr) { 
    11471158                                            while (!preg_match('/ BODYSTRUCTURE (.*) BODY\[HEADER.FIELDS/s', $line, $m)) { 
     
    11691180                                // process the previous line.  Otherwise, we'll keep adding the strings until we come 
    11701181                                // to the next valid header line. 
    1171          
     1182 
    11721183                            do { 
    11731184                                    $line = chop($this->readLine(300), "\r\n"); 
     
    11751186                                // The preg_match below works around communigate imap, which outputs " UID <number>)". 
    11761187                                // Without this, the while statement continues on and gets the "FH0 OK completed" message. 
    1177                                 // If this loop gets the ending message, then the outer loop does not receive it from radline on line 1249.   
     1188                                // If this loop gets the ending message, then the outer loop does not receive it from radline on line 1249. 
    11781189                                // This in causes the if statement on line 1278 to never be true, which causes the headers to end up missing 
    11791190                                    // If the if statement was changed to pick up the fh0 from this loop, then it causes the outer loop to spin 
     
    11991210                        } while ($line[0] != ')' && !$this->startsWith($line, $key, true)); 
    12001211 
    1201                         if (strncmp($line, $key, strlen($key))) {  
     1212                        if (strncmp($line, $key, strlen($key))) { 
    12021213                                // process header, fill rcube_mail_header obj. 
    12031214                                // initialize 
     
    12121223                                while ( list($lines_key, $str) = each($lines) ) { 
    12131224                                        list($field, $string) = $this->splitHeaderLine($str); 
    1214                                          
     1225 
    12151226                                        $field  = strtolower($field); 
    12161227                                        $string = preg_replace('/\n\s*/', ' ', $string); 
    1217                                              
     1228 
    12181229                                        switch ($field) { 
    12191230                                        case 'date'; 
     
    12811292                                $flags_str = preg_replace('/[\\\"]/', '', $flags_str); 
    12821293                                $flags_a   = explode(' ', $flags_str); 
    1283                                          
     1294 
    12841295                                    if (is_array($flags_a)) { 
    12851296                                //      reset($flags_a); 
     
    13441355            $c = count($a); 
    13451356            if ($c > 0) { 
    1346                      
     1357 
    13471358                        // Strategy: 
    13481359                        // First, we'll create an "index" array. 
    1349                         // Then, we'll use sort() on that array,  
     1360                        // Then, we'll use sort() on that array, 
    13501361                        // and use that to sort the main array. 
    1351                  
     1362 
    13521363                    // create "index" array 
    13531364                    $index = array(); 
     
    13671378                        $index[$key]=$data; 
    13681379                } 
    1369                  
     1380 
    13701381                    // sort index 
    13711382                $i = 0; 
     
    13761387                    } 
    13771388 
    1378                 // form new array based on index  
     1389                // form new array based on index 
    13791390                $result = array(); 
    13801391                    reset($index); 
     
    13841395                    } 
    13851396            } 
    1386          
     1397 
    13871398            return $result; 
    13881399    } 
     
    13931404            return -1; 
    13941405        } 
    1395                  
     1406 
    13961407        $c = 0; 
    13971408                $command = $messages ? "UID EXPUNGE $messages" : "EXPUNGE"; 
     
    14071418                } 
    14081419                } while (!$this->startsWith($line, 'exp1', true, true)); 
    1409                  
     1420 
    14101421                if ($this->parseResult($line) == 0) { 
    14111422                        $this->selected = ''; // state has changed, need to reselect 
     
    14211432                return -1; 
    14221433            } 
    1423      
     1434 
    14241435            $flag = $this->flags[strtoupper($flag)]; 
    1425      
     1436 
    14261437            if (!$this->select($mailbox)) { 
    14271438                return -1; 
    14281439            } 
    1429      
     1440 
    14301441        $c = 0; 
    14311442            if (!$this->putLine("flg UID STORE $messages {$mod}FLAGS ($flag)")) { 
     
    14651476                return -1; 
    14661477            } 
    1467      
     1478 
    14681479            if (!$this->select($from)) { 
    14691480            return -1; 
    14701481            } 
    1471          
     1482 
    14721483        $this->putLine("cpy1 UID COPY $messages \"".$this->escape($to)."\""); 
    14731484            $line = $this->readReply(); 
     
    15301541                    } 
    15311542            } 
    1532          
     1543 
    15331544            return $node; 
    15341545    } 
     
    15431554            $algorithm = $algorithm ? trim($algorithm) : 'REFERENCES'; 
    15441555            $criteria  = $criteria ? 'ALL '.trim($criteria) : 'ALL'; 
    1545                  
     1556 
    15461557            if (!$this->putLineC("thrd1 THREAD $algorithm $encoding $criteria")) { 
    15471558                    return false; 
     
    15631574 
    15641575        $this->error = "Thread: $line"; 
    1565             return false;        
     1576            return false; 
    15661577    } 
    15671578 
     
    15941605 
    15951606        $this->error = "Search: $line"; 
    1596             return false;        
     1607            return false; 
    15971608    } 
    15981609 
     
    16021613            return -1; 
    16031614        } 
    1604      
     1615 
    16051616        $r = $this->copy($messages, $from, $to); 
    16061617 
     
    16261637                $mailbox = '*'; 
    16271638            } 
    1628          
     1639 
    16291640            if (empty($ref) && $this->rootdir) { 
    16301641                $ref = $this->rootdir; 
    16311642            } 
    1632      
     1643 
    16331644        if ($subscribed) { 
    16341645            $key     = 'lsb'; 
     
    16451656                return false; 
    16461657            } 
    1647      
     1658 
    16481659            // get folder list 
    16491660            do { 
     
    16781689                    return false; 
    16791690            } 
    1680          
     1691 
    16811692        $result = false; 
    16821693            $parts  = (array) $parts; 
     
    16891700            foreach($parts as $part) 
    16901701                    $peeks[] = "BODY.PEEK[$part.$type]"; 
    1691          
     1702 
    16921703            $request = "$key FETCH $id (" . implode(' ', $peeks) . ')'; 
    16931704 
     
    16961707                return false; 
    16971708            } 
    1698          
     1709 
    16991710            do { 
    17001711                $line = $this->readLine(1000); 
     
    17411752                        $mode = 0; 
    17421753            } 
    1743          
     1754 
    17441755                $reply_key = '* ' . $id; 
    17451756        $result = false; 
     
    17891800                $bytes    = (int)$sizeStr; 
    17901801                        $prev     = ''; 
    1791                          
     1802 
    17921803                while ($bytes > 0) { 
    17931804                    $line = $this->readLine(1024); 
    17941805                $len  = strlen($line); 
    1795                  
     1806 
    17961807                        if ($len > $bytes) { 
    17971808                        $line = substr($line, 0, $bytes); 
     
    18121823                                        else 
    18131824                                                $prev = ''; 
    1814                                                  
     1825 
    18151826                                        if ($file) 
    18161827                                                fwrite($file, base64_decode($line)); 
     
    18481859                } 
    18491860        } 
    1850              
     1861 
    18511862        // read in anything up until last line 
    18521863                if (!$end) 
     
    19231934        $query = 'usub1 UNSUBSCRIBE "' . $this->escape($folder) . '"'; 
    19241935            $this->putLine($query); 
    1925      
     1936 
    19261937            $line = trim($this->readLine(512)); 
    19271938            return ($this->parseResult($line) == 0); 
     
    19601971                            $line = $this->readLine(); 
    19611972                } while (!$this->startsWith($line, 'a ', true, true)); 
    1962          
     1973 
    19631974                $result = ($this->parseResult($line) == 0); 
    19641975                    if (!$result) { 
     
    19771988                return false; 
    19781989            } 
    1979      
     1990 
    19801991            // open message file 
    19811992            $in_fp = false; 
     
    19831994                    $in_fp = fopen($path, 'r'); 
    19841995            } 
    1985             if (!$in_fp) {  
     1996            if (!$in_fp) { 
    19861997                    $this->error = "Couldn't open $path for reading"; 
    19871998                    return false; 
    19881999            } 
    1989          
     2000 
    19902001            $len = filesize($path); 
    19912002            if (!$len) { 
     
    20372048                    return $result; 
    20382049            } 
    2039          
     2050 
    20402051        $this->error = "Couldn't send command \"$request\""; 
    20412052            return false; 
     
    20752086            $result      = false; 
    20762087            $quota_lines = array(); 
    2077          
     2088 
    20782089            // get line(s) containing quota info 
    20792090            if ($this->putLine('QUOT1 GETQUOTAROOT "INBOX"')) { 
     
    20852096                    } while (!$this->startsWith($line, 'QUOT1', true, true)); 
    20862097            } 
    2087          
     2098 
    20882099            // return false if not found, parse if found 
    20892100            $min_free = PHP_INT_MAX; 
     
    20922103                    $parts        = explode(' ', $quota_line); 
    20932104                    $storage_part = array_search('STORAGE', $parts); 
    2094                  
     2105 
    20952106                    if (!$storage_part) 
    20962107                continue; 
    2097          
     2108 
    20982109                    $used  = intval($parts[$storage_part+1]); 
    20992110                    $total = intval($parts[$storage_part+2]); 
    2100                     $free  = $total - $used;  
    2101          
     2111                    $free  = $total - $used; 
     2112 
    21022113                    // return lowest available space from all quotas 
    2103                     if ($free < $min_free) {  
    2104                         $min_free          = $free;  
     2114                    if ($free < $min_free) { 
     2115                        $min_free          = $free; 
    21052116                            $result['used']    = $used; 
    21062117                            $result['total']   = $total; 
     
    21382149            $ts = (int) $ts; 
    21392150 
    2140             return $ts < 0 ? 0 : $ts;    
     2151            return $ts < 0 ? 0 : $ts; 
    21412152    } 
    21422153 
     
    21632174            $in_quotes = false; 
    21642175            $elem      = 0; 
    2165          
     2176 
    21662177        for ($i;$i<$len;$i++) { 
    21672178                    $c = (string)$str[$i]; 
     
    21862197                    } 
    21872198            } 
    2188              
     2199 
    21892200        return $data; 
    21902201    } 
     
    21922203    private function escape($string) 
    21932204    { 
    2194             return strtr($string, array('"'=>'\\"', '\\' => '\\\\'));  
     2205            return strtr($string, array('"'=>'\\"', '\\' => '\\\\')); 
    21952206    } 
    21962207 
    21972208    private function unEscape($string) 
    21982209    { 
    2199             return strtr($string, array('\\"'=>'"', '\\\\' => '\\'));  
     2210            return strtr($string, array('\\"'=>'"', '\\\\' => '\\')); 
    22002211    } 
    22012212 
Note: See TracChangeset for help on using the changeset viewer.