thomascube
2007-12-10 fba1f5ab813f2eb4bedc5d9c4a75e77bbaa90131
program/lib/imap.inc
@@ -39,11 +39,16 @@
      - Added BCC and REFERENCE to the list of headers to fetch in iil_C_FetchHeaders()
      - Leave messageID unchanged in iil_C_FetchHeaders()
      - Avoid stripslahes in iil_Connect()
      - Escape quotes and backslashes in iil_C_Login()
      - Added patch to iil_SortHeaders() by Richard Green
      - Removed <br> from error messages (better for logging)
      - Added patch to iil_C_Sort() enabling UID SORT commands
      - Added function iil_C_ID2UID()
      - Casting date parts in iil_StrToTime() to avoid mktime() warnings
      - Also acceppt LIST responses in iil_C_ListSubscribed()
      - Sanity check of $message_set in iil_C_FetchHeaders(), iil_C_FetchHeaderIndex(), iil_C_FetchThreadHeaders()
      - Implemented UID FETCH in iil_C_FetchHeaders()
      - Abort do-loop on socket errors (fgets returns false)
      - Removed some debuggers (echo ...)
********************************************************/
@@ -91,17 +96,21 @@
   var $messageID;
   var $size;
   var $encoding;
   var $charset;
   var $ctype;
   var $flags;
   var $timestamp;
   var $f;
   var $seen;
   var $deleted;
   var $recent;
   var $answered;
   var $junk;
   var $internaldate;
   var $is_reply;
   var $references;
   var $mdn_to;
   var $mdn_sent = false;
   var $is_reply = false;
   var $seen = false;
   var $deleted = false;
   var $recent = false;
   var $answered = false;
   var $junk = false;
}
@@ -126,6 +135,8 @@
   if ($fp){
      do{
         $buffer = fgets($fp, 2048);
         if ($buffer === false)
            break;
         $line.=$buffer;
      }while($buffer[strlen($buffer)-1]!="\n");
   }
@@ -222,11 +233,14 @@
function iil_C_Login(&$conn, $user, $password){
    $password = strtr($password, array('"'=>'\\"', '\\' => '\\\\'));
    fputs($conn->fp, "a001 LOGIN $user \"$password\"\r\n");
   do{
       $line = iil_ReadReply($conn->fp);
   }while(!iil_StartsWith($line, "a001 "));
  do{
    $line = iil_ReadReply($conn->fp);
    if ($line === false)
      break;
  }while(!iil_StartsWith($line, "a001 "));
    $a=explode(" ", $line);
    if (strcmp($a[1],"OK")==0){
        $result=$conn->fp;
@@ -675,7 +689,9 @@
   if (empty($index_field)) $index_field="DATE";
   $index_field = strtoupper($index_field);
   
   if ((empty($message_set)) || ($message_set == "1:0")) return array();
   list($from_idx, $to_idx) = explode(':', $message_set);
   if (empty($message_set) || (isset($to_idx) && (int)$from_idx > (int)$to_idx))
      return false;
   
   //$fields_a["DATE"] = ($IMAP_USE_INTERNAL_DATE?6:1);
   $fields_a['DATE'] = 1;
@@ -931,7 +947,9 @@
   global $clock;
   global $index_a;
   
   if (empty($message_set)) return false;
   list($from_idx, $to_idx) = explode(':', $message_set);
   if (empty($message_set) || (isset($to_idx) && (int)$from_idx > (int)$to_idx))
      return false;
   $result = array();
   $uids = iil_C_FetchUIDs($conn, $mailbox);
@@ -1012,7 +1030,9 @@
function iil_C_BuildThreads2(&$conn, $mailbox, $message_set, &$clock){
   global $index_a;
   if (empty($message_set)) return false;
   list($from_idx, $to_idx) = explode(':', $message_set);
   if (empty($message_set) || (isset($to_idx) && (int)$from_idx > (int)$to_idx))
      return false;
   
   $result=array();
   $roots=array();
@@ -1187,15 +1207,17 @@
   return $t_index;
}
function iil_C_FetchHeaders(&$conn, $mailbox, $message_set){
function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false){
   global $IMAP_USE_INTERNAL_DATE;
   
   $c=0;
   $result=array();
   $fp = $conn->fp;
   
   if (empty($message_set)) return array();
   list($from_idx, $to_idx) = explode(':', $message_set);
   if (empty($message_set) || (isset($to_idx) && (int)$from_idx > (int)$to_idx))
      return false;
   /*  Do "SELECT" command */
   if (!iil_C_Select($conn, $mailbox)){
      $conn->error = "Couldn't select $mailbox";
@@ -1221,7 +1243,8 @@
   /* FETCH date,from,subject headers */
   $key="fh".($c++);
   $request=$key." FETCH $message_set (BODY.PEEK[HEADER.FIELDS (DATE FROM TO SUBJECT REPLY-TO IN-REPLY-TO CC BCC CONTENT-TRANSFER-ENCODING CONTENT-TYPE MESSAGE-ID REFERENCE)])\r\n";
   $prefix=$uidfetch?" UID":"";
   $request=$key.$prefix." FETCH $message_set (BODY.PEEK[HEADER.FIELDS (DATE FROM TO SUBJECT REPLY-TO IN-REPLY-TO CC BCC CONTENT-TRANSFER-ENCODING CONTENT-TYPE MESSAGE-ID REFERENCES DISPOSITION-NOTIFICATION-TO)])\r\n";
   if (!fputs($fp, $request)) return false;
   do{
@@ -1232,6 +1255,7 @@
         $result[$id]=new iilBasicHeader;
         $result[$id]->id = $id;
         $result[$id]->subject = "";
         $result[$id]->messageID = "mid:".$id;
         /*
            Start parsing headers.  The problem is, some header "lines" take up multiple lines.
            So, we'll read ahead, and if the one we're reading now is a valid header, we'll
@@ -1247,7 +1271,18 @@
               $i++;
               $lines[$i] = trim(chop($line));
            }
         }while($line[0]!=")" && strncmp($line, $key, strlen($key)));  // patch from "Maksim Rubis" <siburny@hotmail.com>
            /*
               The preg_match below works around communigate imap, which outputs " UID <number>)".
               Without this, the while statement continues on and gets the "fh0 OK completed" message.
               If this loop gets the ending message, then the outer loop does not receive it from radline on line 1249.
               This in causes the if statement on line 1278 to never be true, which causes the headers to end up missing
               If the if statement was changed to pick up the fh0 from this loop, then it causes the outer loop to spin
               An alternative might be:
               if (!preg_match("/:/",$line) && preg_match("/\)$/",$line)) break;
               however, unsure how well this would work with all imap clients.
            */
            if (preg_match("/^\s*UID [0-9]+\)$/",$line)) break;
         }while(trim($line[0])!=")" && strncmp($line, $key, strlen($key)));  // patch from "Maksim Rubis" <siburny@hotmail.com>
         
            if(strncmp($line, $key, strlen($key)))
            { 
@@ -1259,37 +1294,63 @@
         }
         //   create array with header field:data
         $headers = array();
         while ( list($lines_key, $str) = each($lines) ){
            list($field, $string) = iil_SplitHeaderLine($str);
            $field = strtolower($field);
            $headers[$field] = $string;
            switch ($field){
               case 'date';
                  $result[$id]->date = $string;
                  $result[$id]->timestamp = iil_StrToTime($string);
                  break;
               case 'from':
                  $result[$id]->from = $string;
                  break;
               case 'to':
                  $result[$id]->to = str_replace("\n", " ", $string);
                  break;
               case 'subject':
                  $result[$id]->subject = str_replace("\n", "", $string);
                  break;
               case 'reply-to':
                  $result[$id]->replyto = str_replace("\n", " ", $string);
                  break;
               case 'cc':
                  $result[$id]->cc = str_replace("\n", " ", $string);
                  break;
               case 'bcc':
                  $result[$id]->bcc = str_replace("\n", " ", $string);
                  break;
               case 'content-transfer-encoding':
                  $result[$id]->encoding = str_replace("\n", " ", $string);
                  break;
               case 'content-type':
                   $ctype_parts = explode(";", $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];
                  break;
               case 'in-reply-to':
                  $result[$id]->in_reply_to = ereg_replace("[\n<>]", '', $string);
                  break;
               case 'references':
                  $result[$id]->references = $string;
                  break;
                  case 'return-receipt-to':
                  case 'disposition-notification-to':
                  case 'x-confirm-reading-to':
                     $result[$id]->mdn_to = str_replace("\n", " ", $string);
                     break;
               case 'message-id':
                  $result[$id]->messageID = $string;
                  break;
            }
         }
         $result[$id]->date = $headers["date"];
         $result[$id]->timestamp = iil_StrToTime($headers["date"]);
         $result[$id]->from = $headers["from"];
         $result[$id]->to = str_replace("\n", " ", $headers["to"]);
         $result[$id]->subject = str_replace("\n", "", $headers["subject"]);
         $result[$id]->replyto = str_replace("\n", " ", $headers["reply-to"]);
         $result[$id]->cc = str_replace("\n", " ", $headers["cc"]);
         $result[$id]->bcc = str_replace("\n", " ", $headers["bcc"]);
         $result[$id]->encoding = str_replace("\n", " ", $headers["content-transfer-encoding"]);
         $result[$id]->ctype = str_replace("\n", " ", $headers["content-type"]);
         $result[$id]->in_reply_to = ereg_replace("[\n<>]",'', $headers['in-reply-to']);
         $result[$id]->reference = $headers["reference"];
         list($result[$id]->ctype, $ctype_add) = explode(";", $headers["content-type"]);
         if (preg_match('/charset="?([a-z0-9\-]+)"?/i', $ctype_add, $regs))
            $result[$id]->charset = $regs[1];
         $messageID = $headers["message-id"];
         if (!$messageID) "mid:".$id;
         $result[$id]->messageID = $messageID;
         }
            else {
            $a=explode(" ", $line);
            }
      }
      else {
         $a=explode(" ", $line);
      }
         
      }
   }while(strcmp($a[0], $key)!=0);
@@ -1299,7 +1360,7 @@
      Sample reply line: "* 3 FETCH (UID 2417 RFC822.SIZE 2730 FLAGS (\Seen \Deleted))"
   */
   $command_key="fh".($c++);
   $request= $command_key." FETCH $message_set (UID RFC822.SIZE FLAGS INTERNALDATE)\r\n";
   $request= $command_key.$prefix." FETCH $message_set (UID RFC822.SIZE FLAGS INTERNALDATE)\r\n";
   if (!fputs($fp, $request)) return false;
   do{
      $line=chop(iil_ReadLine($fp, 200));
@@ -1339,10 +1400,6 @@
               $flags_a = explode(" ", $flags_str);
               //echo "<!-- ID: $id FLAGS: ".implode(",", $flags_a)." //-->\n";
               
               $result[$id]->seen = false;
               $result[$id]->recent = false;
               $result[$id]->deleted = false;
               $result[$id]->answered = false;
               if (is_array($flags_a)){
                  reset($flags_a);
                  while (list($key,$val)=each($flags_a)){
@@ -1350,8 +1407,9 @@
                     else if (strcasecmp($val, "Deleted")==0) $result[$id]->deleted=true;
                     else if (strcasecmp($val, "Recent")==0) $result[$id]->recent = true;
                     else if (strcasecmp($val, "Answered")==0) $result[$id]->answered = true;
                     else if (strcasecmp($val, "\$MDNSent")==0) $result[$id]->mdn_sent = true;
                  }
                  $result[$id]->flags=$flags_str;
                  $result[$id]->flags = $flags_a;
               }
         
               // if time is gmt...   
@@ -1391,10 +1449,10 @@
}
function iil_C_FetchHeader(&$conn, $mailbox, $id){
function iil_C_FetchHeader(&$conn, $mailbox, $id, $uidfetch=false){
   $fp = $conn->fp;
   $a=iil_C_FetchHeaders($conn, $mailbox, $id);
   if (is_array($a)) return $a[$id];
   $a=iil_C_FetchHeaders($conn, $mailbox, $id, $uidfetch);
   if (is_array($a)) return array_shift($a);
   else return false;
}
@@ -1480,13 +1538,14 @@
   
   $fp = $conn->fp;
   $flags=array(
                    "SEEN"=>"\\Seen",
                    "DELETED"=>"\\Deleted",
                    "RECENT"=>"\\Recent",
                    "ANSWERED"=>"\\Answered",
                    "DRAFT"=>"\\Draft",
               "FLAGGED"=>"\\Flagged"
                   );
    "SEEN"=>"\\Seen",
    "DELETED"=>"\\Deleted",
    "RECENT"=>"\\Recent",
    "ANSWERED"=>"\\Answered",
    "DRAFT"=>"\\Draft",
    "FLAGGED"=>"\\Flagged",
    "MDNSENT"=>"\$MDNSent"
  );
   $flag=strtoupper($flag);
   $flag=$flags[$flag];
   if (iil_C_Select($conn, $mailbox)){
@@ -1755,7 +1814,7 @@
      $line=iil_ReadLine($fp, 500);
      $line=iil_MultLine($fp, $line);
      $a = explode(" ", $line);
      if (($line[0]=="*") && ($a[1]=="LSUB")){
      if (($line[0]=="*") && ($a[1]=="LSUB" || $a[1]=="LIST")){
         $line = rtrim($line);
            // split one line
         $a=iil_ExplodeQuotedString(" ", $line);
@@ -1875,7 +1934,7 @@
                $remaining = $bytes - $received;
                $line = iil_ReadLine($fp, 1024);
                $len = strlen($line);
                if ($len > $remaining) substr($line, 0, $remaining);
                if ($len > $remaining) $line = substr($line, 0, $remaining);
                $received += strlen($line);
                if ($mode==1) $result .= chop($line)."\n";
                else if ($mode==2){ echo chop($line)."\n"; flush(); }