alecpl
2008-10-07 2727053c61cac4a37a76b9e58e607acff7fc8dfb
program/lib/imap.inc
@@ -52,8 +52,6 @@
      - $ICL_SSL is not boolean anymore but contains the connection schema (ssl or tls)
      - Removed some debuggers (echo ...)
      File altered by Aleksander Machniak <alec@alec.pl>
      - RFC3501 [7.1] don't call CAPABILITY if was returned in server
        optional resposne in iil_Connect()
      - trim(chop()) replaced by trim()
      - added iil_Escape() with support for " and \ in folder names
      - support \ character in username in iil_C_Login()
@@ -62,6 +60,12 @@
      - removed hardcoded data size in iil_ReadLine() 
      - added iil_PutLine() wrapper for fputs()
      - code cleanup and identation fixes
      - removed flush() calls in iil_C_HandlePartBody() to prevent from memory leak (#1485187)
      - don't return "??" from iil_C_GetQuota()
      - RFC3501 [7.1] don't call CAPABILITY if was returned in server
        optional resposne in iil_Connect(), added iil_C_GetCapability()
      - remove 'undisclosed-recipients' string from 'To' header
      - iil_C_HandlePartBody(): added 6th argument and fixed endless loop
********************************************************/
@@ -90,6 +94,16 @@
$GLOBALS['IMAP_SERVER_TZ'] = date('Z');
$GLOBALS['IMAP_FLAGS'] = array(
    'SEEN'     => '\\Seen',
    'DELETED'  => '\\Deleted',
    'RECENT'   => '\\Recent',
    'ANSWERED' => '\\Answered',
    'DRAFT'    => '\\Draft',
    'FLAGGED'  => '\\Flagged',
    'FORWARDED' => '$Forwarded',
    'MDNSENT'  => '$MDNSent');
$iil_error;
$iil_errornum;
$iil_selected;
@@ -113,6 +127,8 @@
   var $rootdir;
   var $delimiter;
   var $capability = array();
   var $permanentflags = array();
   var $capability_readed = false;
}
/**
@@ -142,7 +158,7 @@
   var $priority;
   var $mdn_to;
   var $mdn_sent = false;
   var $is_reply = false;
   var $is_draft = false;
   var $seen = false;
   var $deleted = false;
   var $recent = false;
@@ -281,6 +297,40 @@
   return strtr($string, array('"'=>'\\"', '\\' => '\\\\')); 
}
function iil_C_GetCapability(&$conn, $name)
{
   if (in_array($name, $conn->capability)) {
      return true;
   }
   else if ($conn->capability_readed) {
      return false;
   }
   // get capabilities (only once) because initial
   // optional CAPABILITY response may differ
   $conn->capability = array();
   iil_PutLine($conn->fp, "cp01 CAPABILITY");
   do {
      $line = trim(iil_ReadLine($conn->fp, 1024));
      $a = explode(' ', $line);
      if ($line[0] == '*') {
         while (list($k, $w) = each($a)) {
            if ($w != '*' && $w != 'CAPABILITY')
                   $conn->capability[] = strtoupper($w);
         }
      }
   } while ($a[0] != 'cp01');
   $conn->capability_readed = true;
   if (in_array($name, $conn->capability)) {
      return true;
   }
   return false;
}
function iil_C_Authenticate(&$conn, $user, $pass, $encChallenge) {
    
    $ipad = '';
@@ -385,7 +435,7 @@
function iil_C_NameSpace(&$conn) {
   global $my_prefs;
   
   if (!in_array('NAMESPACE', $conn->capability)) {
   if (!iil_C_GetCapability($conn, 'NAMESPACE')) {
       return false;
   }
    
@@ -500,42 +550,24 @@
   }
   $iil_error .= "Socket connection established\r\n";
   $line       = iil_ReadLine($conn->fp, 1024);
   $line       = iil_ReadLine($conn->fp, 4096);
   // RFC3501 [7.1] optional CAPABILITY response
   // commented out, because it's not working always as should
//   if (preg_match('/\[CAPABILITY ([^]]+)\]/i', $line, $matches)) {
//      $conn->capability = explode(' ', $matches[1]);
//   } else {
      iil_PutLine($conn->fp, "cp01 CAPABILITY");
      do {
         $line = trim(iil_ReadLine($conn->fp, 1024));
   if (preg_match('/\[CAPABILITY ([^]]+)\]/i', $line, $matches)) {
      $conn->capability = explode(' ', strtoupper($matches[1]));
   }
         $conn->message .= "$line\n";
         $a = explode(' ', $line);
         if ($line[0] == '*') {
            while (list($k, $w) = each($a)) {
               if ($w != '*' && $w != 'CAPABILITY')
                   $conn->capability[] = $w;
            }
         }
      } while ($a[0] != 'cp01');
//   }
   $conn->message .= $line;
   if (strcasecmp($auth_method, "check") == 0) {
      //check for supported auth methods
      //default to plain text auth
      $auth_method = 'plain';
      //check for CRAM-MD5
      foreach ($conn->capability as $c)
         if (strcasecmp($c, 'AUTH=CRAM_MD5') == 0 ||
            strcasecmp($c, 'AUTH=CRAM-MD5') == 0) {
            $auth_method = 'auth';
            break;
         }
      if (iil_C_GetCapability($conn, 'AUTH=CRAM-MD5') || iil_C_GetCapability($conn, 'AUTH=CRAM_MD5')) {
         $auth_method = 'auth';
      }
      else {
         //default to plain text auth
         $auth_method = 'plain';
      }
   }
   if (strcasecmp($auth_method, 'auth') == 0) {
@@ -668,15 +700,15 @@
}
function iil_ExplodeQuotedString($delimiter, $string) {
   $quotes=explode('"', $string);
   $quotes = explode('"', $string);
   while ( list($key, $val) = each($quotes)) {
      if (($key % 2) == 1) {
         $quotes[$key] = str_replace($delimiter, "_!@!_", $quotes[$key]);
          }
   }
   $string=implode('"', $quotes);
   $string = implode('"', $quotes);
   
   $result=explode($delimiter, $string);
   $result = explode($delimiter, $string);
   while ( list($key, $val) = each($result) ) {
      $result[$key] = str_replace('_!@!_', $delimiter, $result[$key]);
   }
@@ -716,7 +748,7 @@
      return false;
   }
   if (strcmp($conn->selected, $mailbox) == 0) {
          return true;
      return true;
   }
    
   iil_C_LoadCache($conn, $mailbox);
@@ -729,9 +761,12 @@
            if (strcasecmp($a[2], 'EXISTS') == 0) {
               $conn->exists = (int) $a[1];
            }
                     if (strcasecmp($a[2], 'RECENT') == 0) {
                         $conn->recent = (int) $a[1];
                     }
            if (strcasecmp($a[2], 'RECENT') == 0) {
               $conn->recent = (int) $a[1];
            }
         }
         else if (preg_match('/\[?PERMANENTFLAGS\s+\(([^\)]+)\)\]/U', $line, $match)) {
            $conn->permanentflags = explode(' ', $match[1]);
         }
      } while (!iil_StartsWith($line, 'sel1'));
@@ -1643,7 +1678,7 @@
                  $result[$id]->from = $string;
                  break;
               case 'to':
                  $result[$id]->to = $string;
                  $result[$id]->to = preg_replace('/undisclosed-recipients:[;,]*/', '', $string);
                  break;
               case 'subject':
                  $result[$id]->subject = $string;
@@ -1757,6 +1792,8 @@
                         $result[$id]->answered = true;
                     } else if (strcasecmp($val, '$Forwarded') == 0) {
                         $result[$id]->forwarded = true;
                     } else if (strcasecmp($val, 'Draft') == 0) {
                         $result[$id]->is_draft = true;
                     } else if (strcasecmp($val, '$MDNSent') == 0) {
                         $result[$id]->mdn_sent = true;
                     } else if (strcasecmp($val, 'Flagged') == 0) {
@@ -1909,15 +1946,7 @@
   }
    
   $fp    = $conn->fp;
   $flags = array(
        'SEEN'     => '\\Seen',
        'DELETED'  => '\\Deleted',
        'RECENT'   => '\\Recent',
        'ANSWERED' => '\\Answered',
        'DRAFT'    => '\\Draft',
        'FLAGGED'  => '\\Flagged',
        'FORWARDED' => '$Forwarded',
        'MDNSENT'  => '$MDNSent');
   $flags = $GLOBALS['IMAP_FLAGS'];
        
   $flag = strtoupper($flag);
   $flag = $flags[$flag];
@@ -1990,11 +2019,9 @@
function iil_C_CountUnseen(&$conn, $folder) {
   $index = iil_C_Search($conn, $folder, 'ALL UNSEEN');
   if (is_array($index)) {
      $str = implode(',', $index);
      if (empty($str)) {
          return false;
          }
      return count($index);
      if (($cnt = count($index)) && $index[0] != '') {
         return $cnt;
      }
   }
   return false;
}
@@ -2002,11 +2029,7 @@
function iil_C_UID2ID(&$conn, $folder, $uid) {
   if ($uid > 0) {
      $id_a = iil_C_Search($conn, $folder, "UID $uid");
      if (is_array($id_a)) {
         $count = count($id_a);
         if ($count > 1) {
             return false;
              }
      if (is_array($id_a) && count($id_a) == 1) {
         return $id_a[0];
      }
   }
@@ -2325,19 +2348,19 @@
   return $result;
}
function iil_C_HandlePartBody(&$conn, $mailbox, $id, $part, $mode) {
function iil_C_HandlePartBody(&$conn, $mailbox, $id, $part, $mode, $file=NULL) {
   /* modes:
        1: return string
        1: return string (or write to $file pointer)
        2: print
        3: base64 and print
        3: base64 and print (or write to $file pointer)
   */
   
   $fp     = $conn->fp;
   $result = false;
   if (($part == 0) || empty($part)) {
       $part = 'TEXT';
      $part = 'TEXT';
   }
   if (iil_C_Select($conn, $mailbox)) {
          $reply_key = '* ' . $id;
        
@@ -2371,8 +2394,11 @@
                   if ($mode == 2) {
                      echo $result;
                   } else if ($mode == 3) {
                      echo base64_decode($result);
                   }
            if ($file)
               fwrite($file, base64_decode($result));
                     else
               echo base64_decode($result);
         }
          } else if ($line[$len-1] == '}') {
                   //multi-line request, find sizes of content and receive that many bytes
              $from     = strpos($line, '{') + 1;
@@ -2380,34 +2406,47 @@
              $len      = $to - $from;
                   $sizeStr  = substr($line, $from, $len);
              $bytes    = (int)$sizeStr;
                   $received = 0;
              while ($received < $bytes) {
                     $remaining = $bytes - $received;
                      $line      = iil_ReadLine($fp, 1024);
              while ($bytes > 0) {
                          $line      = iil_ReadLine($fp, 1024);
                     $len       = strlen($line);
                
                      if ($len > $remaining) {
                             $line = substr($line, 0, $remaining);
                      if ($len > $bytes) {
                             $line = substr($line, 0, $bytes);
                      }
                     $received += strlen($line);
                     $bytes -= strlen($line);
                      if ($mode == 1) {
                             $result .= rtrim($line, "\t\r\n\0\x0B") . "\n";
               if ($file)
                  fwrite($file, rtrim($line, "\t\r\n\0\x0B") . "\n");
                             else
                  $result .= rtrim($line, "\t\r\n\0\x0B") . "\n";
                      } else if ($mode == 2) {
                             echo rtrim($line, "\t\r\n\0\x0B") . "\n"; flush();
                             echo rtrim($line, "\t\r\n\0\x0B") . "\n";
                      } else if ($mode == 3) {
                        echo base64_decode($line); flush();
                     }
               if ($file)
                  fwrite($file, base64_decode($line));
                        else
                  echo base64_decode($line);
            }
              }
          }
           // read in anything up until 'til last line
           // read in anything up until last line
      do {
              $line = iil_ReadLine($fp, 1024);
      } while (!iil_StartsWith($line, $key));
        
      if ($mode == 3 && $file) {
         return true;
      }
          if ($result) {
             $result = rtrim($result, "\t\r\n\0\x0B");
              return $result; // substr($result, 0, strlen($result)-1);
         if ($file) {
            fwrite($file, $result);
            return true;
         }
         return $result; // substr($result, 0, strlen($result)-1);
          }
          
      return false;
@@ -2416,13 +2455,18 @@
   }
    
   if ($mode==1) {
      if ($file) {
         fwrite($file, $result);
         return true;
      }
          return $result;
   }
   return $received;
   return false;
}
function iil_C_FetchPartBody(&$conn, $mailbox, $id, $part) {
   return iil_C_HandlePartBody($conn, $mailbox, $id, $part, 1);
function iil_C_FetchPartBody(&$conn, $mailbox, $id, $part, $file=NULL) {
   return iil_C_HandlePartBody($conn, $mailbox, $id, $part, 1, $file);
}
function iil_C_PrintPartBody(&$conn, $mailbox, $id, $part) {
@@ -2562,12 +2606,14 @@
   
   if (iil_C_Select($conn, $folder)) {
      $key = 'F1247';
      if (iil_PutLine($fp, "$key FETCH $id (BODYSTRUCTURE)")) {
         do {
            $line = iil_ReadLine($fp, 5000);
            $line = iil_MultLine($fp, $line);
            $result .= $line;
            list(, $index, $cmd, $rest) = explode(' ', $line);
            if ($cmd != 'FETCH' || $index == $id || preg_match("/^$key/", $line))
               $result .= $line;
         } while (!preg_match("/^$key/", $line));
         $result = trim(substr($result, strpos($result, 'BODYSTRUCTURE')+13, -(strlen($result)-strrpos($result, $key)+1)));
@@ -2610,13 +2656,9 @@
      $parts        = explode(' ', $quota_line);
      $storage_part = array_search('STORAGE', $parts);
      if ($storage_part > 0) {
         $result = array();
         $used   = $parts[$storage_part+1];
         $total  = $parts[$storage_part+2];
         $result['used']    = $used;
         $result['total']   = (empty($total)?"??":$total);
         $result['percent'] = (empty($total)?"??":round(($used/$total)*100));
         $result['used']    = intval($parts[$storage_part+1]);
         $result['total']   = intval($parts[$storage_part+2]);
         $result['percent'] = min(100, round(($result['used']/max(1,$result['total']))*100));
         $result['free']    = 100 - $result['percent'];
      }
   }