fixed formatting, sjeesh that's realy dull work. Makes me simple :(
[squirrelmail.git] / functions / imap_general.php
index 4504ce9d3634d78fdebd5a8ebd5c93386c06a258..eb044690e2484a1fd894a90ea6b923e61b2bd7b5 100755 (executable)
@@ -81,6 +81,7 @@ function sqimap_fgets($imap_stream) {
     $buffer = 4096;
     $results = '';
     $offset = 0;
+    $i=0;
     while (strpos($results, "\r\n", $offset) === false) {
         if (!($read = fgets($imap_stream, $buffer))) {
             break;
@@ -99,43 +100,121 @@ function sqimap_fgets($imap_stream) {
  * the errors will be sent back through $response and $message
  */
 
-function sqimap_read_data_list ($imap_stream, $pre, $handle_errors, &$response, &$message, $query = '') {
+function sqimap_read_data_list ($imap_stream, $tag_uid, $handle_errors, &$response, &$message, $query = '') {
     global $color, $squirrelmail_language;
     $read = '';
-    $pre_a = explode(' ',trim($pre));
-    $pre = $pre_a[0];
+    $tag_uid_a = explode(' ',trim($tag_uid));
+    $tag = $tag_uid_a[0];
     $resultlist = array();
     $data = array();
     $read = sqimap_fgets($imap_stream);
-    while (1) {
-        switch (true) { 
-            case preg_match("/^$pre (OK|BAD|NO)(.*)$/", $read, $regs):
-            case preg_match('/^\* (BYE \[ALERT\])(.*)$/', $read, $regs):
-                $response = $regs[1];
-                $message = trim($regs[2]);
-                break 2;
-            case preg_match("/^\* (OK \[PARSE\])(.*)$/", $read):
+    $i = 0;
+    while ($read) {
+        $char = $read{0};
+        switch ($char)
+        {
+        case $tag{0}:
+            /* get the command */
+            $arg = '';
+            $i = strlen($tag)+1;
+            $s = substr($read,$i);
+            if (($j = strpos($s,' ')) || ($j = strpos($s,"\n"))) {
+                $arg = substr($s,0,$j);
+            }
+            $found_tag = substr($read,0,$i-1);
+            if ($arg && $found_tag==$tag) {
+                switch ($arg)
+                {
+                case 'OK':
+                case 'BAD':
+                case 'NO':
+                case 'BYE':
+                case 'PREAUTH':
+                    $response = $arg;
+                    $message = trim(substr($read,$i+strlen($arg)));
+                    break 3;
+                default: 
+                    /* this shouldn't happen */
+                    $response = $arg;
+                    $message = trim(substr($read,$i+strlen($arg)));
+                    break 3;
+                }
+            } elseif($found_tag !== $tag) {
+                /* reset data array because we do not need this reponse */
+                $data = array();
                 $read = sqimap_fgets($imap_stream);
-                break 1;
-            case preg_match('/^\* ([0-9]+) FETCH.*/', $read, $regs):
+                break;
+            }
+            case '*':
+            if (preg_match('/^\*\s\d+\sFETCH/',$read)) {
+                /* check for literal */
+                $s = substr($read,-3);
                 $fetch_data = array();
-                $fetch_data[] = $read;
-                $read = sqimap_fgets($imap_stream);
-                while (!preg_match('/^\* [0-9]+ FETCH.*/', $read) &&
-                       !preg_match("/^$pre (OK|BAD|NO)(.*)$/", $read)) {
-                    $fetch_data[] = $read;
-                    $last = $read;
-                    $read = sqimap_fgets($imap_stream);
-                }
-                if (isset($last) && preg_match('/^\)/', $last)) {
-                    array_pop($fetch_data);
-                }
+                do { /* outer loop, continue until next untagged fetch
+                        or tagged reponse */
+                    do { /* innerloop for fetching literals. with this loop
+                            we prohibid that literal responses appear in the
+                            outer loop so we can trust the untagged and
+                            tagged info provided by $read */
+                        if ($s === "}\r\n") {
+                            $j = strrpos($read,'{');
+                            $iLit = substr($read,$j+1,-3);
+                            $fetch_data[] = $read;
+                            $sLiteral = fread($imap_stream,$iLit);
+                            /* backwards compattibility */
+                            $aLiteral = explode("\n", $sLiteral);
+                            /* release not neaded data */
+                            unset($sLiteral);
+                            foreach ($aLiteral as $line) {
+                                $fetch_data[] = $line ."\n";
+                            }
+                            /* release not neaded data */
+                            unset($aLiteral); 
+                            /* next fgets belongs to this fetch because
+                               we just got the exact literalsize and there
+                               must follow data to complete the response */
+                            $fetch_data[] = sqimap_fgets($imap_stream);
+                        } else {
+                           $fetch_data[] = $read;
+                        }
+                        /* retrieve next line and check in the while
+                           statements if it belongs to this fetch response */
+                        $read = sqimap_fgets($imap_stream);
+                        /* check for next untagged reponse and break */
+                        if ($read{0} == '*') break 2;
+                        $s = substr($read,-3);
+                    } while ($s === "}\r\n");
+                    $s = substr($read,-3);
+                } while ($read{0} !== '*' &&
+                substr($read,0,strlen($tag)) !== $tag);
                 $resultlist[] = $fetch_data;
+                /* release not neaded data */
+                unset ($fetch_data);
+            } else {
+                $s = substr($read,-3);
+                do {
+                    if ($s === "}\r\n") {
+                        $j = strrpos($read,'{');
+                        $iLit = substr($read,$j+1,-3);
+                        $data[] = $read;
+                        $data[] = fread($imap_stream,$iLit);
+                        $fetch_data[] = sqimap_fgets($imap_stream);
+                    } else {
+                        $data[] = $read;
+                    }
+                    $read = sqimap_fgets($imap_stream);
+                    if ($read{0} == '*') break;
+                    $s = substr($read,-3);
+                } while ($s === "}\r\n");
                 break 1;
-            default:
-                $data[] = $read;
-                $read = sqimap_fgets($imap_stream);
-                break 1;
+            }
+            break;
+        case '+':
+            $read = sqimap_fgets($imap_stream);
+            break;
+        default:
+            $read = sqimap_fgets($imap_stream);
+            break;
         }
     }
     if (!empty($data)) {
@@ -181,8 +260,8 @@ function sqimap_read_data_list ($imap_stream, $pre, $handle_errors, &$response,
     }
 }
 
-function sqimap_read_data ($imap_stream, $pre, $handle_errors, &$response, &$message, $query = '') {
-    $res = sqimap_read_data_list($imap_stream, $pre, $handle_errors, $response, $message, $query);
+function sqimap_read_data ($imap_stream, $tag_uid, $handle_errors, &$response, &$message, $query = '') {
+    $res = sqimap_read_data_list($imap_stream, $tag_uid, $handle_errors, $response, $message, $query);
   
     /* sqimap_read_data should be called for one response
        but since it just calls sqimap_read_data_list which 
@@ -190,13 +269,13 @@ function sqimap_read_data ($imap_stream, $pre, $handle_errors, &$response, &$mes
        and merge the $res array IF they are seperated and 
        IF it was a FETCH response. */
   
-    if (isset($res[1]) && is_array($res[1]) && isset($res[1][0]) 
-        && preg_match('/^\* \d+ FETCH/', $res[1][0])) {
-        $result = array();
-        foreach($res as $index=>$value) {
-            $result = array_merge($result, $res["$index"]);
-        }
-    }
+//    if (isset($res[1]) && is_array($res[1]) && isset($res[1][0]) 
+//        && preg_match('/^\* \d+ FETCH/', $res[1][0])) {
+//        $result = array();
+//        foreach($res as $index=>$value) {
+//            $result = array_merge($result, $res["$index"]);
+//        }
+//    }
     if (isset($result)) {
         return $result;
     }
@@ -284,7 +363,7 @@ function sqimap_login ($username, $password, $imap_server_address, $imap_port, $
       }
     } elseif ($imap_auth_mech == 'login') {
           // Original IMAP login code
-      $query = 'LOGIN "' . quoteIMAP($username) .  '" "' . quoteIMAP($password) . '"';
+      $query = 'LOGIN "' . quoteimap($username) .  '" "' . quoteimap($password) . '"';
       $read = sqimap_run_command ($imap_stream, $query, false, $response, $message);
     } elseif ($imap_auth_mech == 'plain') {
                 /* Replace this with SASL PLAIN if it ever gets implemented */
@@ -304,12 +383,12 @@ function sqimap_login ($username, $password, $imap_server_address, $imap_port, $
                 set_up_language($squirrelmail_language, true);
                 require_once(SM_PATH . 'functions/display_messages.php');
                 if ($response == 'BAD') {
-                   $string = sprintf (_("Bad request: %s")."<br>\r\n", $message);
+                    $string = sprintf (_("Bad request: %s")."<br>\r\n", $message);
                 } else {
-                   $string = sprintf (_("Unknown error: %s") . "<br>\n", $message);
+                    $string = sprintf (_("Unknown error: %s") . "<br>\n", $message);
                 }
                 if (isset($read) && is_array($read)) {
-                        $string .= '<br>' . _("Read data:") . "<br>\n";
+                    $string .= '<br>' . _("Read data:") . "<br>\n";
                     foreach ($read as $line) {
                         $string .= htmlspecialchars($line) . "<br>\n";
                     }
@@ -432,27 +511,33 @@ function sqimap_get_num_messages ($imap_stream, $mailbox) {
 }
 
 
-function parseAddress($address, $max=0, $addr_ar = array(), $group = '', $host='') {
+function parseAddress($address, $max=0, $addr_ar = array(), $group = '', $host='', $limit=0) {
     $pos = 0;
     $j = strlen($address);
     $personal = '';
     $addr = '';
     $comment = '';
-    if ($max && $max = count($addr_ar)) {
+    if ($max && $max == count($addr_ar)) {
         return $addr_ar;
     }
     while ($pos < $j) {
-        if ($max && $max = count($addr_ar)) {
+        if ($max && $max == count($addr_ar)) {
             return $addr_ar;
         }
         $char = $address{$pos};
         switch ($char) {
             case '=':
+            /* check if it is an encoded string */
                 if (preg_match('/^(=\?([^?]*)\?(Q|B)\?([^?]*)\?=)(.*)/Ui',substr($address,$pos),$reg)) {
-                    $personal = $reg[1];
-                    $pos += strlen($personal);
-                }
-                ++$pos;
+            /* add stringpart before the encoded string to the personal var */
+            if (!$personal) {
+            $personal = substr($address,0,$pos);
+            }
+                    $personal .= $reg[1];
+            $pos += strlen($reg[1]);
+                } else {
+                    ++$pos;
+        }
                 break;
             case '"': /* get the personal name */
                 ++$pos;
@@ -480,8 +565,13 @@ function parseAddress($address, $max=0, $addr_ar = array(), $group = '', $host='
             case '<':  /* get email address */
                 $addr_start = $pos;
                 $addr_end = strpos($address,'>',$addr_start);
-                $addr = substr($address,$addr_start+1,$addr_end-$addr_start-1);
-                $pos = $addr_end+1;
+                if($addr_end === FALSE) {
+                    // in case the address doesn't end, prevent loop
+                    $pos++;
+                } else {
+                    $addr = substr($address,$addr_start+1,$addr_end-$addr_start-1);
+                    $pos = $addr_end+1;
+                }
                 break;
             case '(':  /* rip off comments */
                 $addr_start = $pos;
@@ -495,6 +585,12 @@ function parseAddress($address, $max=0, $addr_ar = array(), $group = '', $host='
                 $j = strlen($address);
                 $pos = $addr_start + 1;
                 break;
+            case ';': /* we reached a non rfc2822 compliant delimiter */
+                if ($group) {
+                    $address = substr($address, 0, $pos - 1);
+            ++$pos;
+            break;
+                }
             case ',':  /* we reached a delimiter */
                 if ($addr == '') {
                     $addr = substr($address, 0, $pos);
@@ -521,12 +617,6 @@ function parseAddress($address, $max=0, $addr_ar = array(), $group = '', $host='
                 $j = strlen($address);
                 $group = '';
                 break;
-            case ';':
-                if ($group) {
-                    $address = substr($address, 0, $pos - 1);
-                }
-                ++$pos;
-                break;
             default:
                 ++$pos;
                 break;