alecpl
2010-03-05 2d08c50fd78e8ae74f27a2418f7909b18ae2bf42
program/lib/imap.inc
@@ -234,7 +234,7 @@
   $line = '';
   if (!$fp) {
          return $line;
          return NULL;
   }
    
   if (!$size) {
@@ -242,6 +242,10 @@
   }
    
   do {
      if (feof($fp)) {
         return $line ? $line : NULL;
      }
          $buffer = fgets($fp, $size);
          if ($buffer === false) {
@@ -264,6 +268,8 @@
      $bytes = $a[2][0];
      while (strlen($out) < $bytes) {
         $line = iil_ReadBytes($fp, $bytes); 
         if ($line === NULL)
            break;
         $out .= $line;
      }
@@ -276,7 +282,8 @@
   global $my_prefs;
   $data = '';
   $len  = 0;
   do {
   while ($len < $bytes && !feof($fp))
   {
      $d = fread($fp, $bytes-$len);
      if (!empty($my_prefs['debug_mode']))
         write_log('imap', 'S: '. $d);
@@ -286,7 +293,7 @@
                  break; //nothing was read -> exit to avoid apache lockups
          }
          $len = $data_len;
   } while ($len < $bytes);
   };
   
   return $data;
}
@@ -303,13 +310,14 @@
function iil_ParseResult($string) {
   $a = explode(' ', trim($string));
   if (count($a) >= 2) {
      if (strcasecmp($a[1], 'OK') == 0) {
      $res = strtoupper($a[1]);
      if ($res == 'OK') {
         return 0;
      } else if (strcasecmp($a[1], 'NO') == 0) {
      } else if ($res == 'NO') {
         return -1;
      } else if (strcasecmp($a[1], 'BAD') == 0) {
      } else if ($res == 'BAD') {
         return -2;
      } else if (strcasecmp($a[1], 'BYE') == 0) {
      } else if ($res == 'BYE') {
         return -3;
      }
   }
@@ -341,7 +349,6 @@
   }
   if ($error && preg_match('/^\* (BYE|BAD) /i', $string)) {
      return true;
   }
   return false;
}
@@ -554,8 +561,8 @@
   // set some imap options
   if (is_array($options)) {
      foreach($options as $optkey => $optval) {
         if ($optkey == 'imap') {
            $auth_method = $optval;
         if ($optkey == 'auth_method') {
            $auth_method = strtoupper($optval);
         } else if ($optkey == 'rootdir') {
                $my_prefs['rootdir'] = $optval;
         } else if ($optkey == 'delimiter') {
@@ -567,7 +574,7 @@
   }
   if (empty($auth_method))
          $auth_method = 'check';
          $auth_method = 'CHECK';
      
   $message = "INITIAL: $auth_method\n";
      
@@ -612,7 +619,7 @@
      $host = $ICL_SSL . '://' . $host;
   }
   $conn->fp = fsockopen($host, $ICL_PORT, $errno, $errstr, 10);
   $conn->fp = @fsockopen($host, $ICL_PORT, $errno, $errstr, 10);
   if (!$conn->fp) {
          $iil_error = "Could not connect to $host at port $ICL_PORT: $errstr";
          $iil_errornum = -2;
@@ -620,7 +627,7 @@
   }
   stream_set_timeout($conn->fp, 10);
   $line = stream_get_line($conn->fp, 8192, "\r\n");
   $line = trim(fgets($conn->fp, 8192));
   if ($my_prefs['debug_mode'] && $line)
      write_log('imap', 'S: '. $line);
@@ -665,54 +672,47 @@
           }
   }
   if (strcasecmp($auth_method, "check") == 0) {
      //check for supported auth methods
   $orig_method = $auth_method;
   if ($auth_method == 'CHECK') {
      // check for supported auth methods
      if (iil_C_GetCapability($conn, 'AUTH=CRAM-MD5') || iil_C_GetCapability($conn, 'AUTH=CRAM_MD5')) {
         $auth_method = 'auth';
         $auth_method = 'AUTH';
      }
      else {
         //default to plain text auth
         $auth_method = 'plain';
         // default to plain text auth
         $auth_method = 'PLAIN';
      }
   }
   if (strcasecmp($auth_method, 'auth') == 0) {
      $conn->message .= "Trying CRAM-MD5\n";
      //do CRAM-MD5 authentication
   if ($auth_method == 'AUTH') {
      // do CRAM-MD5 authentication
      iil_PutLine($conn->fp, "a000 AUTHENTICATE CRAM-MD5");
      $line = trim(iil_ReadLine($conn->fp, 1024));
      $conn->message .= "$line\n";
      if ($line[0] == '+') {
         $conn->message .= 'Got challenge: ' . htmlspecialchars($line) . "\n";
         //got a challenge string, try CRAM-5
         // got a challenge string, try CRAM-MD5
         $result = iil_C_Authenticate($conn, $user, $password, substr($line,2));
              
         // stop if server sent BYE response
         if($result == -3) {
         if ($result == -3) {
                     $iil_error = $conn->error;
                     $iil_errornum = $conn->errorNum;
            return false;
         }
         $conn->message .= "Tried CRAM-MD5: $result \n";
      } else {
         $conn->message .='No challenge ('.htmlspecialchars($line)."), try plain\n";
         $auth = 'plain';
      }
      if (!is_resource($result) && $orig_method == 'CHECK') {
         $auth_method = 'PLAIN';
      }
   }
      
   if ((!$result)||(strcasecmp($auth, "plain") == 0)) {
      //do plain text auth
   if ($auth_method == 'PLAIN') {
      // do plain text auth
      $result = iil_C_Login($conn, $user, $password);
      $conn->message .= "Tried PLAIN: $result \n";
   }
   $conn->message .= $auth;
   if (!is_int($result)) {
   if (is_resource($result)) {
      iil_C_Namespace($conn);
      return $conn;
   } else {
@@ -724,7 +724,8 @@
function iil_Close(&$conn) {
   if (iil_PutLine($conn->fp, "I LOGOUT")) {
      fgets($conn->fp, 1024);
      if (!feof($conn->fp))
         fgets($conn->fp, 1024);
      fclose($conn->fp);
      $conn->fp = false;
   }
@@ -779,7 +780,7 @@
   if (empty($mailbox)) {
      return false;
   }
   if (strcmp($conn->selected, $mailbox) == 0) {
   if ($conn->selected == $mailbox) {
      return true;
   }
    
@@ -788,10 +789,11 @@
         $line = chop(iil_ReadLine($conn->fp, 300));
         $a = explode(' ', $line);
         if (count($a) == 3) {
            if (strcasecmp($a[2], 'EXISTS') == 0) {
            $token = strtoupper($a[2]);
            if ($token == 'EXISTS') {
               $conn->exists = (int) $a[1];
            }
            else if (strcasecmp($a[2], 'RECENT') == 0) {
            else if ($token == 'RECENT') {
               $conn->recent = (int) $a[1];
            }
         }
@@ -799,8 +801,6 @@
            $conn->permanentflags = explode(' ', $match[1]);
         }
      } while (!iil_StartsWith($line, 'sel1', true));
      $a = explode(' ', $line);
      if (strcasecmp($a[1], 'OK') == 0) {
         $conn->selected = $mailbox;
@@ -915,7 +915,7 @@
   return preg_split('/\s+/', $data, -1, PREG_SPLIT_NO_EMPTY);
}
function iil_C_FetchHeaderIndex(&$conn, $mailbox, $message_set, $index_field='', $skip_deleted=true) {
function iil_C_FetchHeaderIndex(&$conn, $mailbox, $message_set, $index_field='', $skip_deleted=true, $uidfetch=false) {
   list($from_idx, $to_idx) = explode(':', $message_set);
   if (empty($message_set) ||
@@ -949,19 +949,22 @@
   
   // build FETCH command string
   $key     = 'fhi0';
   $cmd     = $uidfetch ? 'UID FETCH' : 'FETCH';
   $deleted = $skip_deleted ? ' FLAGS' : '';
   if ($mode == 1)
      $request = " FETCH $message_set (BODY.PEEK[HEADER.FIELDS ($index_field)]$deleted)";
   if ($mode == 1 && $index_field == 'DATE')
      $request = " $cmd $message_set (INTERNALDATE BODY.PEEK[HEADER.FIELDS (DATE)]$deleted)";
   else if ($mode == 1)
      $request = " $cmd $message_set (BODY.PEEK[HEADER.FIELDS ($index_field)]$deleted)";
   else if ($mode == 2) {
      if ($index_field == 'SIZE')
         $request = " FETCH $message_set (RFC822.SIZE$deleted)";
         $request = " $cmd $message_set (RFC822.SIZE$deleted)";
      else
         $request = " FETCH $message_set ($index_field$deleted)";
         $request = " $cmd $message_set ($index_field$deleted)";
   } else if ($mode == 3)
      $request = " FETCH $message_set (FLAGS)";
      $request = " $cmd $message_set (FLAGS)";
   else // 4
      $request = " FETCH $message_set (INTERNALDATE$deleted)";
      $request = " $cmd $message_set (INTERNALDATE$deleted)";
   $request = $key . $request;
@@ -987,15 +990,23 @@
            }
         }
         if ($mode == 1) {
            if (preg_match('/BODY\[HEADER\.FIELDS \("?(DATE|FROM|REPLY-TO|SENDER|TO|SUBJECT)"?\)\] (.*)/', $line, $matches)) {
               $value = preg_replace(array('/^"*[a-z]+:/i', '/\s+$/sm'), array('', ''), $matches[2]);
         if ($mode == 1 && $index_field == 'DATE') {
            if (preg_match('/BODY\[HEADER\.FIELDS \("*DATE"*\)\] (.*)/', $line, $matches)) {
               $value = preg_replace(array('/^"*[a-z]+:/i'), '', $matches[1]);
               $value = trim($value);
               if ($index_field == 'DATE') {
                  $result[$id] = iil_StrToTime($value);
               } else {
                  $result[$id] = $value;
               }
               $result[$id] = iil_StrToTime($value);
            }
            // non-existent/empty Date: header, use INTERNALDATE
            if (empty($result[$id])) {
               if (preg_match('/INTERNALDATE "([^"]+)"/', $line, $matches))
                  $result[$id] = iil_StrToTime($matches[1]);
               else
                  $result[$id] = 0;
            }
         } else if ($mode == 1) {
            if (preg_match('/BODY\[HEADER\.FIELDS \("?(FROM|REPLY-TO|SENDER|TO|SUBJECT)"?\)\] (.*)/', $line, $matches)) {
               $value = preg_replace(array('/^"*[a-z]+:/i', '/\s+$/sm'), array('', ''), $matches[2]);
               $result[$id] = trim($value);
            } else {
               $result[$id] = '';
            }
@@ -1439,7 +1450,8 @@
   $request .= "BODY.PEEK[HEADER.FIELDS ";
   $request .= "(DATE FROM TO SUBJECT REPLY-TO IN-REPLY-TO CC BCC ";
   $request .= "CONTENT-TRANSFER-ENCODING CONTENT-TYPE MESSAGE-ID ";
   $request .= "REFERENCES DISPOSITION-NOTIFICATION-TO X-PRIORITY".$add.")])";
   $request .= "REFERENCES DISPOSITION-NOTIFICATION-TO X-PRIORITY ";
   $request .= "X-REPLY-UID X-FORWARD-UID".$add.")])";
   if (!iil_PutLine($fp, $request)) {
      return false;
@@ -1477,13 +1489,13 @@
            $parts_count = count($a);
            if ($parts_count>=6) {
               for ($i=0; $i<$parts_count; $i=$i+2) {
                  if (strcasecmp($a[$i],'UID') == 0)
                  if ($a[$i] == 'UID')
                     $result[$id]->uid = $a[$i+1];
                  else if (strcasecmp($a[$i],'RFC822.SIZE') == 0)
                  else if ($a[$i] == 'RFC822.SIZE')
                     $result[$id]->size = $a[$i+1];
                  else if (strcasecmp($a[$i],'INTERNALDATE') == 0)
                  else if ($a[$i] == 'INTERNALDATE')
                     $time_str = $a[$i+1];
                  else if (strcasecmp($a[$i],'FLAGS') == 0)
                  else if ($a[$i] == 'FLAGS')
                     $flags_str = $a[$i+1];
               }
@@ -1510,11 +1522,11 @@
            preg_match('/ BODY\[HEADER.FIELDS \(.*?\)\]\s*(.*)$/s', $line, $m);
            $reslines = explode("\n", trim($m[1], '"'));
            // re-parse (see below)
            foreach ($reslines as $line) {
               if (ord($line[0])<=32) {
                  $lines[$ln] .= (empty($lines[$ln])?'':"\n").trim($line);
            foreach ($reslines as $resln) {
               if (ord($resln[0])<=32) {
                  $lines[$ln] .= (empty($lines[$ln])?'':"\n").trim($resln);
               } else {
                  $lines[++$ln] = trim($line);
                  $lines[++$ln] = trim($resln);
               }
            }
         }
@@ -1553,7 +1565,7 @@
               $lines[++$ln] = trim($line);
            }
         // patch from "Maksim Rubis" <siburny@hotmail.com>
         } while (trim($line[0]) != ')' && strncmp($line, $key, strlen($key)));
         } while ($line[0] != ')' && !iil_StartsWith($line, $key, true));
         if (strncmp($line, $key, strlen($key))) { 
            // process header, fill iilBasicHeader obj.
@@ -1601,13 +1613,10 @@
                  $result[$id]->encoding = $string;
                  break;
               case 'content-type':
                  $ctype_parts = explode(";", $string);
                  $ctype_parts = preg_split('/[; ]/', $string);
                  $result[$id]->ctype = array_shift($ctype_parts);
                  foreach ($ctype_parts as $ctype_add) {
                     if (preg_match('/charset="?([a-z0-9\-\.\_]+)"?/i',
                        $ctype_add, $regs)) {
                        $result[$id]->charset = $regs[1];
                     }
                  if (preg_match('/charset\s*=\s*"?([a-z0-9\-\.\_]+)"?/i', $string, $regs)) {
                     $result[$id]->charset = $regs[1];
                  }
                  break;
               case 'in-reply-to':
@@ -1644,23 +1653,24 @@
            $flags_a   = explode(' ', $flags_str);
               
            if (is_array($flags_a)) {
               reset($flags_a);
               while (list(,$val)=each($flags_a)) {
                  if (strcasecmp($val,'Seen') == 0) {
            //   reset($flags_a);
               foreach($flags_a as $flag) {
                  $flag = strtoupper($flag);
                  if ($flag == 'SEEN') {
                      $result[$id]->seen = true;
                  } else if (strcasecmp($val, 'Deleted') == 0) {
                      $result[$id]->deleted=true;
                  } else if (strcasecmp($val, 'Recent') == 0) {
                  } else if ($flag == 'DELETED') {
                      $result[$id]->deleted = true;
                  } else if ($flag == 'RECENT') {
                      $result[$id]->recent = true;
                  } else if (strcasecmp($val, 'Answered') == 0) {
                  } else if ($flag == 'ANSWERED') {
                     $result[$id]->answered = true;
                  } else if (strcasecmp($val, '$Forwarded') == 0) {
                  } else if ($flag == '$FORWARDED') {
                     $result[$id]->forwarded = true;
                  } else if (strcasecmp($val, 'Draft') == 0) {
                  } else if ($flag == 'DRAFT') {
                     $result[$id]->is_draft = true;
                  } else if (strcasecmp($val, '$MDNSent') == 0) {
                  } else if ($flag == '$MDNSENT') {
                     $result[$id]->mdn_sent = true;
                  } else if (strcasecmp($val, 'Flagged') == 0) {
                  } else if ($flag == 'FLAGGED') {
                           $result[$id]->flagged = true;
                  }
               }
@@ -1668,7 +1678,7 @@
            }
         }
      }
   } while (strcmp($a[0], $key) != 0);
   } while (!iil_StartsWith($line, $key, true));
   return $result;
}
@@ -2139,7 +2149,7 @@
   return (iil_ParseResult($line) == 0);
}
function iil_C_FetchMIMEHeaders(&$conn, $mailbox, $id, $parts) {
function iil_C_FetchMIMEHeaders(&$conn, $mailbox, $id, $parts, $mime=true) {
   
   $fp     = $conn->fp;
@@ -2152,10 +2162,11 @@
   $key = 'fmh0';
   $peeks = '';
   $idx = 0;
        $type = $mime ? 'MIME' : 'HEADER';
   // format request
   foreach($parts as $part)
      $peeks[] = "BODY.PEEK[$part.MIME]";
      $peeks[] = "BODY.PEEK[$part.$type]";
   
   $request = "$key FETCH $id (" . implode(' ', $peeks) . ')';
@@ -2168,9 +2179,9 @@
           $line = iil_ReadLine($fp, 1000);
           $line = iil_MultLine($fp, $line);
      if (preg_match('/BODY\[([0-9\.]+)\.MIME\]/', $line, $matches)) {
      if (preg_match('/BODY\[([0-9\.]+)\.'.$type.'\]/', $line, $matches)) {
         $idx = $matches[1];
         $result[$idx] = preg_replace('/^(\* '.$id.' FETCH \()?\s*BODY\['.$idx.'\.MIME\]\s+/', '', $line);
         $result[$idx] = preg_replace('/^(\* '.$id.' FETCH \()?\s*BODY\['.$idx.'\.'.$type.'\]\s+/', '', $line);
         $result[$idx] = trim($result[$idx], '"');
             $result[$idx] = rtrim($result[$idx], "\t\r\n\0\x0B");
          }
@@ -2277,7 +2288,7 @@
               }
               else
                  $prev = '';
               if ($file)
                  fwrite($file, base64_decode($line));
                        else if ($print)
@@ -2313,7 +2324,6 @@
            }
              }
          }
           // read in anything up until last line
      if (!$end)
         do {
@@ -2321,18 +2331,17 @@
         } while (!iil_StartsWith($line, $key, true));
          if ($result) {
             $result = rtrim($result, "\t\r\n\0\x0B");
         if ($file) {
            fwrite($file, $result);
         } else if ($print) {
            echo $result;
         } else
            return $result; // substr($result, 0, strlen($result)-1);
            return $result;
         return true;
          }
   }
   return false;
}
@@ -2411,7 +2420,7 @@
   return false;
}
function iil_C_AppendFromFile(&$conn, $folder, $path) {
function iil_C_AppendFromFile(&$conn, $folder, $path, $headers=null, $separator="\n\n") {
   if (!$folder) {
       return false;
   }
@@ -2431,7 +2440,12 @@
   if (!$len) {
      return false;
   }
        if ($headers) {
                $headers = preg_replace('/[\r\n]+$/', '', $headers);
                $len += strlen($headers) + strlen($separator);
        }
   //send APPEND command
   $request    = 'a APPEND "' . iil_Escape($folder) . '" (\\Seen) {' . $len . '}';
   if (iil_PutLine($fp, $request)) {
@@ -2443,16 +2457,21 @@
         return false;
      }
      //send file
                // send headers with body separator
                if ($headers) {
         iil_PutLine($fp, $headers . $separator, false);
                }
      // send file
      while (!feof($in_fp)) {
         $buffer      = fgets($in_fp, 4096);
         $buffer = fgets($in_fp, 4096);
         iil_PutLine($fp, $buffer, false);
      }
      fclose($in_fp);
      iil_PutLine($fp, ''); // \r\n
      //read response
      // read response
      do {
         $line = iil_ReadLine($fp);
      } while (!iil_StartsWith($line, 'a ', true));