Location: PHPKode > projects > crVCL PHP Framework > crvcl/mail.lib.php
<?PHP

/*

The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/MPL-1.1.html or see MPL-1.1.txt in directory "license"

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
the specific language governing rights and limitations under the License.

The Initial Developers of the Original Code are: 
Copyright (c) 2003-2011, CR-Solutions (http://www.cr-solutions.net), Ricardo Cescon
All Rights Reserved.

Contributor(s): Ricardo Cescon

crVCL PHP Framework Version 2.3
*/


############################################################
if(!defined("MAIL_LIB")){
   define ("MAIL_LIB", 1);
############################################################
require("define.lib.php");
require("tools.lib.php");
require("logger.lib.php");
//-------------------------------------------------------------------------------------------------------------------------------------
/**
 * class to send mail´s as text/html with attachment´s
 * support mail() from php and standard smtp with auth.
 */
class mail
{
// private
   var $m_logger = null;
	var $m_smtp_connection = null;
	var $m_mime = array(
		'hqx'	=> "application/macbinhex40",
		'pdf'	=> "application/pdf",
		'pgp'	=> "application/pgp",
		'ps'	=> "application/postscript",
		'eps'	=> "application/postscript",
		'ai'	=> "application/postscript",
		'rtf'	=> "application/rtf",
		'xls'	=> "application/vnd.ms-excel",
		'pps'	=> "application/vnd.ms-powerpoint",
		'ppt'	=> "application/vnd.ms-powerpoint",
		'ppz'	=> "application/vnd.ms-powerpoint",
		'doc'	=> "application/vnd.ms-word",
		'dot'	=> "application/vnd.ms-word",
		'wrd'	=> "application/vnd.ms-word",
		'tgz'	=> "application/x-gtar",
		'gtar'	=> "application/x-gtar",
		'gz'	=> "application/x-gzip",
		'php'	=> "application/x-httpd-php",
		'php3'	=> "application/x-httpd-php",
		'js'	=> "application/x-javascript",
		'msi'	=> "application/x-msi",
		'swf'	=> "application/x-shockwave-flash",
		'rf'	=> "application/x-shockwave-flash",
		'tar'	=> "application/x-tar",
		'zip'	=> "application/zip",
		'au'	=> "audio/basic",
		'mid'	=> "audio/midi",
		'midi'	=> "audio/midi",
		'kar'	=> "audio/midi",
		'mp2'	=> "audio/mpeg",
		'mp3'	=> "audio/mpeg",
		'mpga'	=> "audio/mpeg",
		'voc'	=> "audio/voc",
		'vox'	=> "audio/voxware",
		'aif'	=> "audio/x-aiff",
		'aiff'	=> "audio/x-aiff",
		'aifc'	=> "audio/x-aiff",
		'wma'	=> "audio/x-ms-wma",
		'ra'	=> "audio/x-pn-realaudio",
		'ram'	=> "audio/x-pn-realaudio",
		'rm'	=> "audio/x-pn-realaudio",
		'ogg'	=> "audio/x-vorbis",
		'wav'	=> "audio/wav",
		'bmp'	=> "image/bmp",
		'dib'	=> "image/bmp",
		'gif'	=> "image/gif",
		'jpg'	=> "image/jpeg",
		'jpe'	=> "image/jpeg",
		'jpeg'	=> "image/jpeg",
		'jfif'	=> "image/jpeg",
		'pcx'	=> "image/pcx",
		'png'	=> "image/png",
		'tif'	=> "image/tiff",
		'tiff'	=> "image/tiff",
		'ico'	=> "image/x-icon",
		'pct'	=> "image/x-pict",
		'txt'	=> "text/plain",
		'htm'	=> "text/html",
		'html'	=> "text/html",
		'xml'	=> "text/xml",
		'xsl'	=> "text/xml",
		'dtd'	=> "text/xml-dtd",
		'css'	=> "text/css",
		'c'		=> "text/x-c",
		'c++'	=> "text/x-c",
		'cc'	=> "text/x-c",
		'cpp'	=> "text/x-c",
		'cxx'	=> "text/x-c",
		'h'		=> "text/x-h",
		'h++'	=> "text/x-h",
		'hh'	=> "text/x-h",
		'hpp'	=> "text/x-h",
		'mpg'	=> "video/mpeg",
		'mpe'	=> "video/mpeg",
		'mpeg'	=> "video/mpeg",
		'qt'	=> "video/quicktime",
		'mov'	=> "video/quicktime",
		'avi'	=> "video/x-ms-video",
		'wm'	=> "video/x-ms-wm",
		'wmv'	=> "video/x-ms-wmv",
		'wmx'	=> "video/x-ms-wmx",
		''		=> "application/octet-stream",
	);
// public
	/**
	 * errorcode
	 *
	 * @var int
	 */
	var $m_error = 0;
	/**
	 * error message
	 *
	 * @var string
	 */
	var $m_errormsg = "";
  /**
   * sender
   *
   * @var string
   */
   var $m_from = "";
  /**
   * subject of mail
   *
   * @var string
   */
	var $m_subject;
	/**
	 * receivers
	 *
	 * @var string
	 */
	var $m_to = "";
	/**
	 * receivers
	 *
	 * @var string
	 */
	var $m_cc = "";
	/**
	 * receivers
	 *
	 * @var string
	 */
	var $m_bcc = "";
	/**
	 * msg of mail
	 *
	 * @var string as text or html
	 */	
	var $m_msg = "";
	/**
	 * receivers for answers
	 *
	 * @var string
	 */
	var $m_reply_to = "";
	/**
	 * return path for undelivered emails
	 *
	 * @var string
	 */
	var $m_return_path = "";
	/**
	 * alternative msg of html mail
	 *
	 * @var string as text
	 */
	var $m_msg_alt = "";
	/**
	 * files to attach => /home/user/docu.pdf or docu.pdf|/home/user/docu.pdf  (use , to separate)
	 *
	 * @var string
	 */
	var $m_attachment = "";
	/**
	 * type of mail
	 *
	 * @var string sample: "text"  or  "html"
	 */
	var $m_type = "text";
	/**
	 * name of mailer
	 *
	 * @var string sample: "php".phpversion()
	 */
	var $m_mailer = "";
	/**
	 * charset allowed "ISO-8859-1" or "UFT-8";
	 *
	 * @var string
	 */
	var $m_charset = "UTF-8";
	/**
	 * transfer encoding
	 *
	 * @var string
	 */
	var $m_encoding = "8bit"; // on ISO-8859-1, on UTF-8 will be forced quoted-printable for text mail
	/**
	 * char´s to seperate header
	 *
	 * @var string
	 */
	var $m_line_seperator = "\r\n";
	/**
	 * is smtp set, the class use own mail functions otherwise mail() from php
	 *
	 * @var string
	 */
	var $m_smtp = "";
	/**
	 * port of smtp
	 *
	 * @var int
	 */
	var $m_smtp_port = 25;
	/**
	 * user for smtp auth.
	 *
	 * @var string
	 */
	var $m_smtp_usr = "";
	/**
	 * pw of smtp auth.
	 *
	 * @var string
	 */
	var $m_smtp_pw = "";
	/**
	 * size before trace file will set to zero
	 *
	 * @var mixed
	 */
	var $m_trace_delAfter = "1024K";
	/**
	 * path for trace file
	 *
	 * @var string
	 */
	var $m_trace_path = "";
	/**
	 * filename of tracefile
	 *
	 * @var string
	 */
	var $m_trace_file = "";
	/**
	 * host name for HELO / EHLO default is servername
	 *
	 * @var string
	 */
	var $m_host = "";
	/**
	 * connection timeout
	 *
	 * @var int
	 */
	var $m_timeout_s = 5;
	/**
	 * socket timeout
	 *
	 * @var int
	 */
	var $m_socket_timeout_s = 5;
   /**
	 * enable critical section for write trace files
	 *
	 * @var string
	 */
	var $m_trace_critical_section_id = null;
	/**
	 * path to share the critical section for write trace files
	 *
	 * @var string
	 */
	var $m_trace_critical_section_path = "./";
	/**
	 * max lock time for zombie processes
	 *
	 * @var int
	 */
	var $m_trace_critical_section_maxlock_ms = 1000;
	/**
	 * sleep for retry enter critical section 
	 *
	 * @var int
	 */
	var $m_trace_critical_section_sleep_ms = 10;
   /**
	 * write the trace to a SQLite file instead of a text file
	 *
	 * @var bool
	 */
	var $m_trace_sqlite = false;
//-------------------------------------------------------------------------------------------------------------------------------------
// constructor
    function mail(){
       if(isset($GLOBALS["CRVCL"]["CHARSET"])){
          if(strtoupper($GLOBALS["CRVCL"]["CHARSET"]) == "UTF-8"){
             $this->m_charset = $GLOBALS["CRVCL"]["CHARSET"];
          }else{
             $this->m_charset = 'ISO-8859-1';
          }
       }
       
       $this->m_logger = new Logger();
    }
//-------------------------------------------------------------------------------------------------------------------------------------
    function __destruct(){
       $this->smtp_disconnect();
    }
//-------------------------------------------------------------------------------------------------------------------------------------
   function getLogger(){
      return $this->m_logger;
   }    
//-------------------------------------------------------------------------------------------------------------------------------------
// private
   function writeTrace($s, $header=""){
      $path = $this->m_trace_path;
      $file = $this->m_trace_file;
      $del = $this->m_trace_delAfter;
      $crit_id = $this->m_trace_critical_section_id;
      $crit_path = $this->m_trace_critical_section_path;
      $crit_maxlock = $this->m_trace_critical_section_maxlock_ms;
      $crit_sleep = $this->m_trace_critical_section_sleep_ms;
      
      if(!empty($path) || !empty($file)){
   		if(empty($file)){
   			$file = "mail.lib.trc";
   		}
         $logger = $this->getLogger();   
         $logger->setOutputFile($path, $file, $del);
         $logger->setOutputFile_CriticalSectionId($crit_id, $crit_path, 
                                                  $crit_maxlock, $crit_sleep);
         $logger->enableOutputFile(true, $this->m_trace_sqlite);
         $logger->enableHeaderOutput(true);
         if(!empty($header)){$header = " - ".$header;}
         $logger->log(LOG_LEVEL_DEBUG, $s, " ip: ".$this->m_smtp.$header);
      }     
	}
//-------------------------------------------------------------------------------------------------------------------------------------
	function smtp_connect(){
		$this->smtp_disconnect();

		$olderr = error_reporting(0);
		$this->m_smtp_connection = fsockopen($this->m_smtp, $this->m_smtp_port, $this->m_error, $this->m_errormsg, $this->m_timeout_s);
		error_reporting($olderr);
		if(!$this->m_smtp_connection){
			return false;
		}
		socket_set_timeout($this->m_smtp_connection, $this->m_socket_timeout_s, 0);

		$ret = $this->smtp_receive();

		$cmd = 'HELO';
      if(strpos(strtoupper($ret),"ESMTP") !== false){
         $cmd = 'EHLO';
      }

      if(empty($this->m_host)){
         $this->m_host = $_SERVER['SERVER_NAME'];
      }

		$this->smtp_send($cmd." ".$this->m_host);
		$ret = $this->smtp_receive();
		if(substr(trim($ret), 0, 3) !== '250'){
			$this->m_error = substr(trim($ret), 0, 3);
			$this->m_errormsg = substr(trim($ret), 3);
			return false;
		}
		$this->m_error = 0;
		$this->m_errormsg = $cmd;
		return true;
	}
//-------------------------------------------------------------------------------------------------------------------------------------
	function smtp_disconnect(){	 
		if($this->m_smtp_connection){		   		
			fclose($this->m_smtp_connection);
			$this->m_smtp_connection = null;
		}
	}
//-------------------------------------------------------------------------------------------------------------------------------------
	function smtp_receive(){
			$return = '';
			$line   = '';
			if($this->m_smtp_connection){
			   $stick = gettickcount();			   
				while(strpos($line, "\r\n") === false || substr($line,3,1) !== ' '){				
					$line    = fgets($this->m_smtp_connection, SOCKET_CHUNK_SIZE);
					if($line === false){break;}
					$return .= $line;
					if((gettickcount()-$stick) > ($this->m_socket_timeout_s*1000)-500){
					   $this->m_error = -1;
                  $this->m_errormsg = "receive timeout, no more packets after ".$this->m_socket_timeout_s." sec.";
                  return false;					                     
					}
				}
				$this->writeTrace($return, "receive");
				return $return;
			}else
				return false;
	}
//-------------------------------------------------------------------------------------------------------------------------------------
	function smtp_send($string){
			if($this->m_smtp_connection){
			   $string .= "\r\n";			   			   
			   
			   $chunk_size = TCP_PACKET_SIZE;
			   $bytes_total = 0;		
			   			   	   
			   while($string != ""){			   
			      $packet = substr($string, 0, $chunk_size);
			      $string = substr($string, $chunk_size);     
			   
   			   $len = strlen($packet);			   
   			   $bytes = fwrite($this->m_smtp_connection, $packet, $len);   			   		      			   
   			   
   			   if($bytes === false){
   			      $string .= '!!! ERROR !!! write to socket failed'.CRLF;
   			   }else if($bytes != $len && !empty($packet)){
   			      $string .= '!!! ERROR !!! only '.$bytes.' from '.$len.' written to socket'.CRLF;   			      
   			      $bytes_total += $bytes;
   			   }else{
   			      $bytes_total += $bytes;
   			   }
   			      			      			      			   
   			   $this->writeTrace($string, "send");
			   }   
				
			   return $bytes_total;
			}else{
				return false;
			}
		}
//-------------------------------------------------------------------------------------------------------------------------------------
	function smtp_auth(){
		if($this->m_smtp_connection && $this->m_smtp_usr){

			$this->smtp_send('AUTH LOGIN');
			$ret = $this->smtp_receive();
			$this->m_error = (int)substr(trim($ret), 0, 3);
			if($this->m_error !== 334){
				$this->m_errormsg = substr(trim($ret), 3);
				return false;
			}

			$this->smtp_send(base64_encode($this->m_smtp_usr));
			$ret = $this->smtp_receive();
			$this->m_error = (int)substr(trim($ret), 0, 3);
			if($this->m_error !== 334){
				$this->m_errormsg = substr(trim($ret), 3);
				return false;
			}

			$this->smtp_send(base64_encode($this->m_smtp_pw));
			$ret = $this->smtp_receive();
			$this->m_error = (int)substr(trim($ret), 0, 3);
			if($this->m_error !== 235){
				$this->m_errormsg = substr(trim($ret), 3);
				return false;
			}

		}
		$this->m_error = 0;
		$this->m_errormsg = $this->m_errormsg = substr(trim($ret), 3);
		return true;
	}
//-------------------------------------------------------------------------------------------------------------------------------------
	function smtp_from(){
		if($this->m_smtp_connection){
			$from = $this->m_from;
		   if(strpos($from, ">") !== false){
            $from = preg_split("/>/", $from);
         }else{
            $from = preg_split("/,/", $from);
         }
			for($i = 0; $i < count($from); $i++){
				if(($pos = strpos($from[$i], "<")) !== false){
					$from[$i] = substr($from[$i], $pos+1);
					if(($pos = strpos($from[$i], ">")) !== false){
					   $from[$i] = substr($from[$i], 0, $pos-1);
					}else{
					   $from[$i] = substr($from[$i], 0);
					}
				}else if(($pos = strpos($from[$i], "[")) !== false){
					$from[$i] = substr($from[$i], $pos+1);
					if(($pos = strpos($from[$i], "]")) !== false){
					   $from[$i] = substr($from[$i], 0, $pos-1);
					}else{
					   $from[$i] = substr($from[$i], 0);
					}
				}

				$this->smtp_send('MAIL FROM:<'.$from[$i].'>');
				$ret = $this->smtp_receive();
				$this->m_error = (int)substr(trim($ret), 0, 3);
				if($this->m_error !== 250){
					$this->m_errormsg = substr(trim($ret), 3);
					return false;
				}
			}
			$this->m_error = 0;
		   $this->m_errormsg = substr(trim($ret), 3);
		}
		return true;
	}
//-------------------------------------------------------------------------------------------------------------------------------------
	function smtp_to(){
	   $ret = '';
		if($this->m_smtp_connection){
			$to = $this->m_to;
		   if(strpos($to, ">") !== false){
            $to = preg_split("/>/", $to);
         }else{
            $to = preg_split("/,/", $to);
         }
			for($i = 0; $i < count($to); $i++){
			   if(empty($to[$i])){continue;}
				if(($pos = strpos($to[$i], "<")) !== false){
					$to[$i] = substr($to[$i], $pos+1);
					if(($pos = strpos($to[$i], ">")) !== false){
					   $to[$i] = substr($to[$i], 0, $pos-1);
					}else{
					   $to[$i] = substr($to[$i], 0);
					}
				}else if(($pos = strpos($to[$i], "[")) !== false){
					$to[$i] = substr($to[$i], $pos+1);
					if(($pos = strpos($to[$i], "]")) !== false){
					   $to[$i] = substr($to[$i], 0, $pos-1);
					}else{
					   $to[$i] = substr($to[$i], 0);
					}
				}

				$this->smtp_send('RCPT TO:<'.$to[$i].'>');
				$ret = $this->smtp_receive();
				$this->m_error = (int)substr(trim($ret), 0, 3);
				if($this->m_error !== 250){
					$this->m_errormsg = substr(trim($ret), 3);
					return false;
				}
			}
			$this->m_error = 0;
		   $this->m_errormsg = substr(trim($ret), 3);
		}
		return true;
	}
//-------------------------------------------------------------------------------------------------------------------------------------
	function smtp_cc(){
		if($this->m_smtp_connection && !empty($this->m_cc)){
			$cc = $this->m_cc;
		   if(strpos($cc, ">") !== false){
            $cc = preg_split("/>/", $cc);
         }else{
            $cc = preg_split("/,/", $cc);
         }
			for($i = 0; $i < count($cc); $i++){
			   if(empty($cc[$i])){continue;}
				if(($pos = strpos($cc[$i], "<")) !== false){
					$cc[$i] = substr($cc[$i], $pos+1);
					if(($pos = strpos($cc[$i], ">")) !== false){
					   $cc[$i] = substr($cc[$i], 0, $pos-1);
					}else{
					   $cc[$i] = substr($cc[$i], 0);
					}
				}else if(($pos = strpos($cc[$i], "[")) !== false){
					$cc[$i] = substr($cc[$i], $pos+1);
					if(($pos = strpos($cc[$i], "]")) !== false){
					   $cc[$i] = substr($cc[$i], 0, $pos-1);
					}else{
					   $cc[$i] = substr($cc[$i], 0);
					}
				}

				$this->smtp_send('RCPT TO:<'.$cc[$i].'>');
				$ret = $this->smtp_receive();
				$this->m_error = (int)substr(trim($ret), 0, 3);
				if($this->m_error !== 250){
					$this->m_errormsg = substr(trim($ret), 3);
					return false;
				}
			}
			$this->m_error = 0;
		   $this->m_errormsg = substr(trim($ret), 3);
		}
		return true;
	}
//-------------------------------------------------------------------------------------------------------------------------------------
	function smtp_bcc(){
		if($this->m_smtp_connection && !empty($this->m_bcc)){
			$bcc = $this->m_bcc;
		   if(strpos($bcc, ">") !== false){
            $bcc = preg_split("/>/", $bcc);
         }else{
            $bcc = preg_split("/,/", $bcc);
         }
			for($i = 0; $i < count($bcc); $i++){
			   if(empty($bcc[$i])){continue;}
				if(($pos = strpos($bcc[$i], "<")) !== false){
					$bcc[$i] = substr($bcc[$i], $pos+1);
					if(($pos = strpos($bcc[$i], ">")) !== false){
					   $bcc[$i] = substr($bcc[$i], 0, $pos-1);
					}else{
					   $bcc[$i] = substr($bcc[$i], 0);
					}
				}else if(($pos = strpos($bcc[$i], "[")) !== false){
					$bcc[$i] = substr($bcc[$i], $pos+1);
					if(($pos = strpos($bcc[$i], "]")) !== false){
					   $bcc[$i] = substr($bcc[$i], 0, $pos-1);
					}else{
					   $bcc[$i] = substr($bcc[$i], 0);
					}
				}

				$this->smtp_send('RCPT TO:<'.$bcc[$i].'>');
				$ret = $this->smtp_receive();
				$this->m_error = (int)substr(trim($ret), 0, 3);
				if($this->m_error !== 250){
					$this->m_errormsg = substr(trim($ret), 3);
					return false;
				}
			}
			$this->m_error = 0;
		   $this->m_errormsg = substr(trim($ret), 3);
		}
		return true;
	}
//-------------------------------------------------------------------------------------------------------------------------------------
	function smtp_data(){
		if($this->m_smtp_connection){
			$this->smtp_send('DATA');
			$ret = $this->smtp_receive();
			$this->m_error = (int)substr(trim($ret), 0, 3);
			if($this->m_error !== 354){
				$this->m_errormsg = substr(trim($ret), 3);
				return false;
			}
		}
		$this->m_error = 0;
		$this->m_errormsg = substr(trim($ret), 3);
		return true;
	}	
//-------------------------------------------------------------------------------------------------------------------------------------
// public
   /**
    * send the msg
    *
    * @return bool
    */
	function send(){
      if(empty($this->m_msg_alt))
	      $this->m_msg_alt = $this->m_msg;				
	      
	   $this->m_msg_alt = html2text($this->m_msg_alt);				   
      
		$wordwarp = "\r\n";
		if(strpos($this->m_msg,"\r\n") !== false){
			$wordwarp = "\r\n";
		}else if(strpos($this->m_msg,"\n") !== false){
			$wordwarp = "\n";
		}else if(strpos($this->m_msg,"\r") !== false){
			$wordwarp = "\r";
		}
		$this->m_msg =	wordwrap($this->m_msg, 200, $wordwarp);

		$wordwarp = "\r\n";
		if(strpos($this->m_msg_alt,"\r\n") !== false){
			$wordwarp = "\r\n";
		}else if(strpos($this->m_msg_alt,"\n") !== false){
			$wordwarp = "\n";
		}else if(strpos($this->m_msg_alt,"\r") !== false){
			$wordwarp = "\r";
		}
		$this->m_msg_alt =	wordwrap($this->m_msg_alt, 70, $wordwarp);


		$this->m_to = str_replace(";", ",", $this->m_to);
		$this->m_cc = str_replace(";", ",", $this->m_cc);
		$this->m_bcc = str_replace(";", ",", $this->m_bcc);
		$this->m_attachment = str_replace(";", ",", $this->m_attachment);

		if(right($this->m_to, 1) == ","){
		   $this->m_to = substr($this->m_to, 0, strlen($this->m_to)-1);
		}
		if(right($this->m_cc, 1) == ","){
		   $this->m_cc = substr($this->m_cc, 0, strlen($this->m_cc)-1);
		}
		if(right($this->m_bcc, 1) == ","){
		   $this->m_bcc = substr($this->m_bcc, 0, strlen($this->m_bcc)-1);
		}
		if(right($this->m_attachment, 1) == ","){
		   $this->m_attachment = substr($this->m_attachment, 0, strlen($this->m_attachment)-1);
		}      		
		
		$this->m_charset = strtolower($this->m_charset);
		
		$body  = "";
		if(strtolower($this->m_type) == "html"){
			$body .= "<html>";
			$body .= "<head>";
			$body .= "<title>".$this->m_subject."</title>";
			$body .= "</head>";
			$body .= "<body>";
		}
		
		$body .= $this->m_msg;
		if(strtolower($this->m_type) == "html"){
			$body .= "</body>" . $this->m_line_seperator;
			$body .= "</html>" . $this->m_line_seperator;
		}

				
		if($this->m_charset == "utf-8"){
		   $this->m_encoding = 'quoted-printable';
		   
		   if(strtolower($this->m_type) == "html"){
		      $this->m_encoding = 'base64';
		      $body = utf8_fix($body);		      
		   }else{
		     $body = utf8_fix($body);		     
		     $body = quoted_printable_encode($body);		     
		   }		   		   
		}
		
		
		$header	= "";
		$message	= "";

		$header .= "From:".$this->m_from . $this->m_line_seperator;

		if(empty($this->m_reply_to)){
		   $this->m_reply_to = $this->m_from;
		}
		if(empty($this->m_return_path)){
		   $this->m_return_path = $this->m_reply_to;
		}
		
		##############
      if(($pos = strpos($this->m_reply_to, "<")) !== false){
			$this->m_reply_to = substr($this->m_reply_to, $pos+1);
			if(($pos = strpos($this->m_reply_to, ">")) !== false){
			   $this->m_reply_to = substr($this->m_reply_to, 0, $pos-1);
			}else{
			   $this->m_reply_to = substr($this->m_reply_to, 0);
			}
		}else if(($pos = strpos($this->m_reply_to, "[")) !== false){
			$this->m_reply_to = substr($this->m_reply_to, $pos+1);
			if(($pos = strpos($this->m_reply_to, "]")) !== false){
			   $this->m_reply_to = substr($this->m_reply_to, 0, $pos-1);
			}else{
			   $this->m_reply_to = substr($this->m_reply_to, 0);
			}
		}
		#
		if(($pos = strpos($this->m_return_path, "<")) !== false){
			$this->m_return_path = substr($this->m_return_path, $pos+1);
			if(($pos = strpos($this->m_return_path, ">")) !== false){
			   $this->m_return_path = substr($this->m_return_path, 0, $pos-1);
			}else{
			   $this->m_return_path = substr($this->m_return_path, 0);
			}
		}else if(($pos = strpos($this->m_return_path, "[")) !== false){
			$this->m_return_path = substr($this->m_return_path, $pos+1);
			if(($pos = strpos($this->m_return_path, "]")) !== false){
			   $this->m_return_path = substr($this->m_return_path, 0, $pos-1);
			}else{
			   $this->m_return_path = substr($this->m_return_path, 0);
			}
		}
		##############
		
		$header .= "Reply-To:".$this->m_reply_to . $this->m_line_seperator;
		$header .= "Return-Path:".$this->m_return_path . $this->m_line_seperator;

		$header .= "To:".$this->m_to . $this->m_line_seperator;

		if(!empty($this->m_cc)){
			$header .= "Cc:" . $this->m_cc . $this->m_line_seperator;
		}
		
		$header .= "Date:".date("r") . $this->m_line_seperator;

		$mailer = $this->m_mailer;
		if(empty($mailer)){
			$mailer = "PHP/".phpversion();
		}

		if(!isset($GLOBALS["CRVCL"]["EXCLUSIVE_LICENSE"])){$GLOBALS["CRVCL"]["EXCLUSIVE_LICENSE"]=false;}
      if($GLOBALS["CRVCL"]["EXCLUSIVE_LICENSE"] == false){ // only allowed to set true for Initial Developers or Contributors with exclusive license
	      $mailer .= " (crVCL PHP Framework ".CRVCL_VERSION." - Mail)";
      }

		$header .= "Subject:".$this->m_subject . $this->m_line_seperator;


		$header .= "X-Mailer:".$mailer . $this->m_line_seperator;

		$header .= "MIME-Version:1.0" . $this->m_line_seperator;

		$boundary_mixed = "crVCL-Mail-".str_replace(" ", "-", CRVCL_VERSION)."-Mixed--".md5(uniqid(time()));
		$boundary_alternative = "crVCL-Mail-".str_replace(" ", "-", CRVCL_VERSION)."-Alternative--".md5(uniqid(time()));

		if(!empty($this->m_attachment)){
		   $header .= "Content-Type:multipart/mixed;boundary=".$boundary_mixed . $this->m_line_seperator . $this->m_line_seperator;
         $header .= "This is a multi-part message in MIME format" . $this->m_line_seperator . $this->m_line_seperator;
		}else if(strtolower($this->m_type) == "html"){
         $header .= "Content-Type:multipart/alternative;boundary=".$boundary_alternative . $this->m_line_seperator . $this->m_line_seperator;
		}else{
	      $header .= "Content-Type:text/plain;charset=\"" . $this->m_charset . "\"" . $this->m_line_seperator;
	      if($this->m_charset == 'utf-8'){
	         $header .= "Content-Transfer-Encoding: " . $this->m_encoding . $this->m_line_seperator;			
	      }
	      $header .= $this->m_line_seperator;			   
		}

		if(strtolower($this->m_type) == "html" && !empty($this->m_attachment)){
		   $message .= "--".$boundary_mixed . $this->m_line_seperator;
         $message .= "Content-Type:multipart/alternative;boundary=".$boundary_alternative . $this->m_line_seperator . $this->m_line_seperator;
		}

		if(strtolower($this->m_type) == "html"){
         $message .= "--".$boundary_alternative . $this->m_line_seperator;
		}

		if(strtolower($this->m_type) == "html"){
			$message .= "Content-Type:text/plain;charset=\"" . $this->m_charset . "\"" . $this->m_line_seperator;
			$message .= "Content-Transfer-Encoding: " . $this->m_encoding . $this->m_line_seperator . $this->m_line_seperator;			
			if(strtolower($this->m_encoding) == "base64"){
			   $message .= base64_encode($this->m_msg_alt) . $this->m_line_seperator . $this->m_line_seperator;
			}else{
			   $message .= $this->m_msg_alt . $this->m_line_seperator . $this->m_line_seperator;
			}

			$message .= "--".$boundary_alternative . $this->m_line_seperator;
			$message .= "Content-Type:text/html;charset=\"" . $this->m_charset . "\"" . $this->m_line_seperator;
			if(strtolower($this->m_encoding) == "base64"){
			   $message .= "Content-Transfer-Encoding: " . $this->m_encoding . $this->m_line_seperator . $this->m_line_seperator;
			   $body = base64_encode($body);
			}
			$message .= $body . $this->m_line_seperator . $this->m_line_seperator;
			$message .= "--".$boundary_alternative . "--" . $this->m_line_seperator . $this->m_line_seperator;
		}else if(!empty($this->m_attachment)){
		   $message .= "--".$boundary_mixed . $this->m_line_seperator;
		   $message .= "Content-Type:text/plain;charset=\"" . $this->m_charset . "\"" . $this->m_line_seperator;
			$message .= "Content-Transfer-Encoding: " . $this->m_encoding . $this->m_line_seperator . $this->m_line_seperator;
			if(strtolower($this->m_encoding) == "base64"){
			   $message .= base64_encode($body) . $this->m_line_seperator . $this->m_line_seperator;
			}else{
			   $message .= $body . $this->m_line_seperator . $this->m_line_seperator;
			}
	   }else{
		   $message .= $body . $this->m_line_seperator;
		}


		if(!empty($this->m_attachment)){
			$attachment = preg_split("/,/", $this->m_attachment);
         $files = count($attachment);
        if($files > 0){
           for($i = 0; $i < $files; $i++){
               $file = $attachment[$i];
               $fname = "";
               if(strpos($file, "|") !== false){
                  $fname = strcut($file, "|");
                  $file = strrcut($file, "|", true);
               }else{
                  $fname = strrcut($attachment[$i],"/",true);
               }
               $ext = strrcut($file,".",true);
                                                            
            	$file = file_get_contents($file);
            	if(is_string($file)){	               
	               $mime = "application/octet-stream";
            	   if(isset($this->m_mime[strtolower($ext)])){
            			$mime = $this->m_mime[strtolower($ext)];
            	   }
	               $message .= "--".$boundary_mixed . $this->m_line_seperator;
	               $message .= "Content-Type:".$mime.";name=". $fname . $this->m_line_seperator;
	               $message .= "Content-Transfer-Encoding:base64" . $this->m_line_seperator;
	               $message .= "Content-Disposition:attachment;filename=" . $fname . $this->m_line_seperator  . $this->m_line_seperator;
	               $message .= chunk_split(base64_encode($file)) . $this->m_line_seperator . $this->m_line_seperator;
	               $file = "";
            	}
           }
        }
		}

		if(!empty($this->m_attachment) || (strtolower($this->m_type) == "html" && !empty($this->m_msg_alt))){
			$message .= "--".$boundary_mixed."--" . $this->m_line_seperator . $this->m_line_seperator;
		}

		$ret = false;
		if(empty($this->m_smtp)){
			$to = $this->m_to;
		   $to = preg_split("/,/", $to);
			for($i = 0; $i < count($to); $i++){
				$p1 = 0;
				$p2 = strlen($to[$i]);
				if(strpos($to[$i], "<") !== false){
					$p1 = strpos($to[$i], "<")+1;
					$p2 = strpos($to[$i], ">")-$p1;
				}

				$olderr = error_reporting(0);
				if(mail("", "", "", $header.$message)){
				//if(mail("", $this->m_subject, "", $header.$message)){
					$ret = true;
					$this->m_error = "0";
					$this->m_errormsg = "mail sended";
				}else{
					$this->m_error = "-1";
					$this->m_errormsg = "send mail failed (php)";
				}
				error_reporting($olderr);
			}

		}else{
			  if($this->smtp_connect()){
			  		if($this->smtp_auth()){
			  			if($this->smtp_from()){
			  				if($this->smtp_to() && $this->smtp_cc() && $this->smtp_bcc()){
			  					if($this->smtp_data()){			  					   			  					   
				  					$this->smtp_send($header.$message);
				  					$this->smtp_send("\r\n.\r\n");
									$ret = $this->smtp_receive();
					            $this->m_error = intval(substr(trim($ret), 0, 3));
					            if($this->m_error !== 250){					            	
										$this->m_errormsg = substr(trim($ret), 3);
										$ret = false;
										$this->smtp_send("QUIT");
		                        $this->smtp_receive();		               									   
					            }else{			
					               $this->smtp_send("QUIT");
		                        $ret = $this->smtp_receive();		               									   
		                        
						            $ret = true;
										$this->m_error = "0";
										$this->m_errormsg = substr(trim($ret), 3);
					            }					            					            
			  					}
			  				}
			  			}
			  		}
			  }
		}
		return $ret;
	}
}
//-------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------
class imap
{
// private
   var $m_logger = null;
   var $m_uid = null;
   var $m_socket = null;
   var $m_login = false;
   var $m_mailbox = "";
// public
   /**
    * imap host
    *
    * @var string
    */
   var $m_host = "";
	/**
	 * port of imap
	 *
	 * @var int
	 */
	var $m_port = 143;
	/**
	 * user for imap auth.
	 *
	 * @var string
	 */
	var $m_usr = "";
	/**
	 * pw of imap auth.
	 *
	 * @var string
	 */
	var $m_pw = "";
   /**
	 * errorcode
	 *
	 * @var int
	 */
	var $m_error = 0;
	/**
	 * error message
	 *
	 * @var string
	 */
	var $m_errormsg = "";
	/**
	 * connection timeout
	 *
	 * @var int
	 */
	var $m_timeout_s = 5;
	/**
	 * socket timeout
	 *
	 * @var int
	 */
	var $m_socket_timeout_s = 5;
	/**
	 * size before trace file will set to zero
	 *
	 * @var mixed
	 */
	var $m_trace_delAfter = "1024K";
	/**
	 * path for trace file
	 *
	 * @var string
	 */
	var $m_trace_path = "";
	/**
	 * filename of tracefile
	 *
	 * @var string
	 */
	var $m_trace_file = "";
	/**
	 * enable critical section for write trace files
	 *
	 * @var string
	 */
	var $m_trace_critical_section_id = null;
	/**
	 * path to share the critical section for write trace files
	 *
	 * @var string
	 */
	var $m_trace_critical_section_path = "./";
	/**
	 * max lock time for zombie processes
	 *
	 * @var int
	 */
	var $m_trace_critical_section_maxlock_ms = 1000;
	/**
	 * sleep for retry enter critical section 
	 *
	 * @var int
	 */
	var $m_trace_critical_section_sleep_ms = 10;
	/**
	 * charset allowed "ISO-8859-1" or "UFT-8";
	 *
	 * @var string
	 */
	var $m_charset_decode = "UTF-8";
	/**
	 * write the trace to a SQLite file instead of a text file
	 *
	 * @var bool
	 */
	var $m_trace_sqlite = false;
//-------------------------------------------------------------------------------------------------------------------------------------
// constructor
    function imap(){
      if(isset($GLOBALS["CRVCL"]["CHARSET"])){
         if(strtoupper($GLOBALS["CRVCL"]["CHARSET"]) == "UTF-8"){
            $this->m_charset_decode = $GLOBALS["CRVCL"]["CHARSET"];
         }else{
            $this->m_charset_decode = 'ISO-8859-1';
         }
      }
      $this->m_logger = new Logger();
      $this->m_uid = uniqid("crVCL_IMAP");
    }
//-------------------------------------------------------------------------------------------------------------------------------------
    function __destruct(){
       $this->free();
    }
//-------------------------------------------------------------------------------------------------------------------------------------
// private
   function free(){
      $this->logout();
      $this->disconnect();
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   function getLogger(){
      return $this->m_logger;
   }   
//-------------------------------------------------------------------------------------------------------------------------------------
   function writeTrace($s, $header=""){
      $path = $this->m_trace_path;
      $file = $this->m_trace_file;
      $del = $this->m_trace_delAfter;
      $crit_id = $this->m_trace_critical_section_id;
      $crit_path = $this->m_trace_critical_section_path;
      $crit_maxlock = $this->m_trace_critical_section_maxlock_ms;
      $crit_sleep = $this->m_trace_critical_section_sleep_ms;
      
      if(!empty($path) || !empty($file)){
   		if(empty($file)){
   			$file = "imap.lib.trc";
   		}
         $logger = $this->getLogger();   
         $logger->setOutputFile($path, $file, $del);
         $logger->setOutputFile_CriticalSectionId($crit_id, $crit_path, 
                                                  $crit_maxlock, $crit_sleep);
         $logger->enableOutputFile(true, $this->m_trace_sqlite);
         $logger->enableHeaderOutput(true);
         if(!empty($header)){$header = " - ".$header;}
         $logger->log(LOG_LEVEL_DEBUG, $s, " ip: ".$this->m_host.$header);
      }             
	}
//-------------------------------------------------------------------------------------------------------------------------------------
   function receive(){
			$return = '';
			$line   = '   ';
			if($this->m_socket){
			   $stick = gettickcount();			   
				while(strpos($line, "\r\n") === false || strlen($line) >= 2 && strpos($line, $this->m_uid) === false){								   					
				   $line = fgets($this->m_socket, SOCKET_CHUNK_SIZE);						
					
					//echo $line."<br>";
					if($line === false){break;}					
					$return .= $line;					
					if((gettickcount()-$stick) > ($this->m_socket_timeout_s*1000)-500){
					   $this->m_error = -1;
                  $this->m_errormsg = "receive timeout, no more packets after ".$this->m_socket_timeout_s." sec.";
                  return false;					   
					}
				}
				$this->writeTrace($return, "receive");
				return $return;
			}else
				return false;
   }      
//-------------------------------------------------------------------------------------------------------------------------------------
	function send($string){
			if($this->m_socket){
			   $this->writeTrace($string, "send");
			   
				return fwrite($this->m_socket, $string."\r\n", strlen($string)+2);
				
			}else{
				return false;
			}
		}
//-------------------------------------------------------------------------------------------------------------------------------------
// public
   function connect(){
      $olderr = error_reporting(0);
		$this->m_socket = fsockopen($this->m_host, $this->m_port, $this->m_error, $this->m_errormsg, $this->m_timeout_s);
		error_reporting($olderr);
		if(!$this->m_socket){
			return false;
		}
		socket_set_timeout($this->m_socket, $this->m_socket_timeout_s, 0);

		$ret = $this->receive();

		if(strpos($ret, "* OK") === false){
		   $this->m_error = -1;
		   $this->m_errormsg = "connect faild";
		   return false;
		}


		$this->m_error = 0;
		$this->m_errormsg = "connect ok";
		return true;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
	function disconnect(){
		if($this->m_socket){
			fclose($this->m_socket);
			$this->m_socket = null;
		}
	}
//-------------------------------------------------------------------------------------------------------------------------------------
/**
 * used if imap server need authentication instead of login  (SASL)
 *
 * @param string $str   sample: LOGIN
 * @param string $str1  sample: myuser
 * @param string $str2  sample: mypw
 * @return bool
 */
function aut($str_type=null, $str1=null, $str2=null){
         if(!$this->m_socket){
            return false;
         }

         if($this->m_login){$this->logout();}

         if(!empty($this->m_mailbox)){$this->close();}

         if(empty($str_type)){$str_type = "LOGIN";}
         if(empty($str1)){$str1 = $this->m_usr;}
         if(empty($str2)){$str2 = $this->m_pw;}

         $this->send($this->m_uid." AUTHENTICATE ".$str_type);
         $ret = $this->receive();

         if(strpos($ret, "+") === false){
            $this->m_error = -1;
		      $this->m_errormsg = "auth. failed";
            return false;
         }

         $this->send(base64_encode($str1));
         $ret = $this->receive();

         if(strpos($ret, "+") === false){
            $this->m_error = -1;
		      $this->m_errormsg = "auth. failed";
            return false;
         }

         $this->send(base64_encode($str1));
         $ret = $this->receive();

         if(strpos($ret, "+") === false){
            $this->m_error = -1;
		      $this->m_errormsg = "auth. failed";
            return false;
         }

         $this->m_error = 0;
		   $this->m_errormsg = "auth. ok";

			return true;
		}
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * login
    *
    * @return bool
    */
	function login(){
      if(!$this->m_socket){
            return false;
      }

      if($this->m_login){$this->logout();}

      $this->send($this->m_uid." LOGIN ".$this->m_usr." ".$this->m_pw);
      $ret = $this->receive();

      if(strpos($ret, $this->m_uid) === false || strpos($ret, "OK") === false){
         $this->m_error = -1;
	      $this->m_errormsg = "login failed";
         return false;
      }

      $this->m_error = 0;
		$this->m_errormsg = "login ok";
      $this->m_login = true;
      return true;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * logout
    *
    * @return bool
    */
	function logout(){
      if(!$this->m_socket || !$this->m_login){
            return false;
      }

      $this->send($this->m_uid." LOGOUT");
      $ret = $this->receive();

      if(strpos($ret, $this->m_uid) === false || strpos($ret, "OK") === false){
         $this->m_error = -1;
	      $this->m_errormsg = "logout failed";
         return false;
      }

      $this->m_error = 0;
		$this->m_errormsg = "logout ok";

		$this->m_login = false;

      return true;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * list of mailsbox
    *
    * @param string $ref_mail_box
    * @param string $wild_card
    * @param bool $active_sub    "ture" to get mailbox user has declared as being "active" or "subscribed"
    * @return array
    */
   function list_mailbox($ref_mail_box="", $wild_card="*", $active_sub=false){
      
      if(!$this->m_login){return array();}

   	if(trim($ref_mail_box) == "")
   		$ref_mail_box = '""';

   	if(trim($wild_card) == "")
   		$wild_card = '*';

   	
   	$cmd = "LIST";
   	if($active_sub){
   	   $cmd = "LSUB";
   	}

   	$this->send($this->m_uid." ".$cmd." ".$ref_mail_box." ".$wild_card);
   	$ret = $this->receive();
   	
   	if(strpos($ret, $this->m_uid) === false || strpos($ret, "OK") === false){
         $this->m_error = -1;
	      $this->m_errormsg = "list failed";
         return false;
      }

   	$temp = explode("\r\n", $ret);

   	$mailbox = array();

   	for($i = 0; $i < acount($temp)-1; $i++){
   	   $line = $temp[$i];
   	   if(left($line, 1) == '*')
   		   $mailbox[] = substr($line, strrpos($line," "));
   	}
   	$this->m_error = 0;
		$this->m_errormsg = "list ok";
   	return $mailbox;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * open/select a mailbox
    *
    * @param string $mailbox
    * @param string $readonly
    * @return bool
    */
   function open($mailbox, $readonly=false){
      if(!$this->m_login){return false;}

      $cmd = "SELECT";
      if($readonly){
         $cmd = "EXAMINE";
      }

      $this->send($this->m_uid." ".$cmd." ".$mailbox);
      $ret = $this->receive();
      if(strpos($ret, $this->m_uid) === false || strpos($ret, "OK") === false){
         $this->m_error = -1;
         $this->m_errormsg = "open failed";
         return false;
      }
      $this->m_mailbox = $mailbox;
      $this->m_error = 0;
		$this->m_errormsg = "open ok";
      return true;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * select a mailbox
    *
    * @param string $mailbox
    * @return bool
    */
   function select($mailbox="INBOX"){
      return $this->open($mailbox);
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * get last open/selected mailbox
    *
    * @return string
    */
   function getSelected(){return $this->m_mailbox;}
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * get status of mailbox
    *
    * flags:
    *
    * MESSAGES
    *    The number of messages in the mailbox.
    *
    * RECENT
    *    The number of messages with the \Recent flag set.
    *
    * UIDNEXT
    *    The next unique identifier value of the mailbox.
    *
    * UIDVALIDITY
    *    The unique identifier validity value of the mailbox.
    *
    * UNSEEN
    *    The number of messages which do not have the \Seen flag set.
    *
    * @param string $mailbox
    * @param string $flag
    * @return string
    */
   function status($mailbox, $flag){
      if(!$this->m_login){return false;}

      $this->send($this->m_uid." STATUS ".$mailbox." (".$flag.")");
      $ret = $this->receive();
      if(strpos($ret, $this->m_uid) === false || strpos($ret, "OK") === false){
         $this->m_error = -1;
         $this->m_errormsg = "status failed";
         return false;
      }

      $temp = preg_split('/'.$flag.'/i', $ret);
      $this->m_error = 0;
		$this->m_errormsg = "status ok";
		return intval($temp[1]);
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * number of messages in the mailbox
    *
    * @return int
    */
   function count($mailbox="INBOX"){
      return $this->status($mailbox, "MESSAGES");
   }
//-------------------------------------------------------------------------------------------------------------------------------------
	/**
	 * noop function can be used as a periodic poll for new messages or message status updates during a period of inactivity
	 *
	 * @return bool
	 */
	function noop(){
		if(!$this->m_login){return false;}

		$this->send($this->m_uid." NOOP");
      $ret = $this->receive();
      if(strpos($ret, $this->m_uid) === false || strpos($ret, "OK") === false){
         $this->m_error = -1;
         $this->m_errormsg = "noop failed";
         return false;
      }
      $this->m_error = 0;
		$this->m_errormsg = "noop ok";
		return true;
	}
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * create a mailbox
    *
    * @param string $mailbox
    * @return bool
    */
   function create($mailbox){
      if(!$this->m_login){return false;}

		$this->send($this->m_uid." CREATE ".$mailbox);
      $ret = $this->receive();
      if(strpos($ret, $this->m_uid) === false || strpos($ret, "OK") === false){
         $this->m_error = -1;
         $this->m_errormsg = "create failed";
         return false;
      }
      $this->m_error = 0;
		$this->m_errormsg = "create ok";
		return true;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * delete a mailbox
    *
    * @param string $mailbox
    * @return bool
    */
   function delete($mailbox){
      if(!$this->m_login){return false;}

		$this->send($this->m_uid." DELETE ".$mailbox);
      $ret = $this->receive();
      if(strpos($ret, $this->m_uid) === false || strpos($ret, "OK") === false){
         $this->m_error = -1;
         $this->m_errormsg = "delete failed";
         return false;
      }
      $this->m_error = 0;
		$this->m_errormsg = "delete ok";
		return true;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * rename a mailbox
    *
    * @param string $mailbox_name_old
    * @param string $mailbox_name_new
    * @return bool
    */
   function rename($mailbox_name_old, $mailbox_name_new){
      if(!$this->m_login){return false;}

		$this->send($this->m_uid." RENAME ".$mailbox_name_old." ".$mailbox_name_new);
      $ret = $this->receive();
      if(strpos($ret, $this->m_uid) === false || strpos($ret, "OK") === false){
         $this->m_error = -1;
         $this->m_errormsg = "rename failed";
         return false;
      }
      $this->m_error = 0;
		$this->m_errormsg = "rename ok";
		return true;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * adds the specified mailbox name to the server's set of "active" or "subscribed" mailboxes
    *
    * @param string $mailbox
    * @return bool
    */
   function subscribe($mailbox){
      if(!$this->m_login){return false;}

		$this->send($this->m_uid." SUBSCRIBE ".$mailbox);
      $ret = $this->receive();
      if(strpos($ret, $this->m_uid) === false || strpos($ret, "OK") === false){
         $this->m_error = -1;
         $this->m_errormsg = "subscribe failed";
         return false;
      }
      $this->m_error = 0;
		$this->m_errormsg = "subscribe ok";
		return true;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * remove the specified mailbox name from the server's set of "active" or "subscribed" mailboxes
    *
    * @param string $mailbox
    * @return bool
    */
   function unsubscribe($mailbox){
      if(!$this->m_login){return false;}

		$this->send($this->m_uid." UNSUBSCRIBE ".$mailbox);
      $ret = $this->receive();
      if(strpos($ret, $this->m_uid) === false || strpos($ret, "OK") === false){
         $this->m_error = -1;
         $this->m_errormsg = "unsubscribe failed";
         return false;
      }
      $this->m_error = 0;
		$this->m_errormsg = "unsubscribe ok";
		return true;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * The CHECK command requests a checkpoint of the currently selected mailbox.  A checkpoint refers to any implementation-dependent housekeeping associated with the mailbox
    *
    * @return string
    */
   function check(){
      if(!$this->m_login){return false;}

		$this->send($this->m_uid." CHECK");
      $ret = $this->receive();
      if(strpos($ret, $this->m_uid) === false || strpos($ret, "OK") === false){
         $this->m_error = -1;
         $this->m_errormsg = "check failed";
         return false;
      }
      $this->m_error = 0;
		$this->m_errormsg = "check ok";
		return $ret;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * close the currently selected mailbox
    *
    * @return bool
    */
   function close(){
      if(!$this->m_login){return false;}
      if(empty($this->m_mailbox)){return false;}

		$this->send($this->m_uid." CLOSE");
      $ret = $this->receive();
      if(strpos($ret, $this->m_uid) === false || strpos($ret, "OK") === false){
         $this->m_error = -1;
         $this->m_errormsg = "close failed";
         return false;
      }

      $this->m_mailbox = "";
      $this->m_error = 0;
		$this->m_errormsg = "close ok";
		return true;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * searches the mailbox for messages that match the given searching query
    *
    * @param string $query    possible search keys SUBJECT <string>, BODY <string>, sample: SUBJECT "test mail", also see http://www.isi.edu/in-notes/rfc3501.txt
    * @param string $charset
    * @param bool $use_uid
    * @return array
    */
   function search($query, $charset="", $use_uid=false){
      if(!$this->m_login){return false;}
      if(empty($this->m_mailbox)){return false;}

      $query = trim($query);

      if(trim($charset) != "")
			$charset = 'CHARSET "'.trim(addslashes($charset)).'" ';

		if($use_uid){
		   $this->send($this->m_uid." UID SEARCH ".$charset.$query);
		}else{
		   $this->send($this->m_uid." SEARCH ".$charset.$query);
		}
      $ret = $this->receive();
      if(strpos($ret, $this->m_uid) === false || strpos($ret, "OK") === false){
         $this->m_error = -1;
         $this->m_errormsg = "search failed";
         return false;
      }

		$found = array();
		$temp = explode("\r\n", $ret);
		foreach($temp as $line){
		   if(substr($line, 0, 9) == "* SEARCH "){
			   $found += explode(" ", substr($line, 9));
		   }
		}
		$this->m_error = 0;
		$this->m_errormsg = "search ok";
		return $found;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * retrieves data associated with a message in the mailbox
    * sample: $imap->fetch("30:103", "BODY[HEADER]")     return the header for mail 30 and 103
    * sample: $imap->fetch("30:103", "BODY[TEXT]")       return the TEXT for mail 30 and 103
    * also see http://www.isi.edu/in-notes/rfc3501.txt
    *
    * @param string $msg_set
    * @param string $msg_data_name
    * @param bool $use_uid
    * @return string
    */
   function fetch($msg_set, $msg_data_name, $use_uid=false){
   	if(!$this->m_login){return false;}
      if(empty($this->m_mailbox)){return false;}

   	$msg_set = trim($msg_set);
   	$msg_data_name = trim($msg_data_name);

   	if($use_uid){
		   $this->send($this->m_uid." UID FETCH ".$msg_set." (".$msg_data_name.")");
		}else{
		   $this->send($this->m_uid." FETCH ".$msg_set." (".$msg_data_name.")");
		}

   	$ret = $this->receive();
   	
      if(strpos(right($ret,strlen($this->m_uid)+200), $this->m_uid." OK") === false){
         $this->m_error = -1;
         $this->m_errormsg = "fetch failed (missing uid:".$this->m_uid." OK".")";
         return false;
      }
            
      $this->m_error = 0;
		$this->m_errormsg = "fetch ok";
				
		$pos = strpos($ret, "\r\n");
		if($pos !== false){
		   $ret = substr($ret, $pos+2);
		}
		
		$pos = strpos($ret, ")\r\ncrVCL_IMAP");
		if($pos !== false){
		   $ret = substr($ret, 0, $pos);
		}
		
   	return $ret;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * fetch a mail
    *
    * @param int $id
    * @param bool $use_uid
    * @return imap_msg
    */
   function fetch_msg($id, $use_uid=false, $limit=0){
      
      $header = $this->fetch($id, "BODY[HEADER]", $use_uid);
      if($header === false || stripos($header, "from:") === false || stripos($header, "date:") === false){
         $header = $this->fetch($id, "BODY[HEADER.FIELDS]", $use_uid);
      }
      
      // for test only
      //file_put_contents($GLOBALS["DOCROOT"]."/logs/header.data", $header, false);
      
      // for test only
      //$header = file_get_contents("W:/richie.panthermedia.net/test/imap.header.data");                      		
		
      ///////////////
				
      if($header === false){return null;}
      $body = $this->fetch($id, "BODY[TEXT]", $use_uid);
      
      // for test only
      //file_put_contents($GLOBALS["DOCROOT"]."/logs/body.data", $body); 
     
      // for test only
      //$body = file_get_contents("W:/richie.panthermedia.net/test/imap.body.data");
            
      ///////////////
            
      if($body === false){return null;}
      
      // trim IMAP flags
      $pos = strpos($header, "\x20UID"); // trim IMAP flags
		if($pos !== false){
		   $header = substr($header, 0, $pos);
		}
		
		$pos = strpos($body, "\x20UID"); // trim IMAP flags
		if($pos !== false){
		   $body = substr($body, 0, $pos);
		}
		///////////////
      

      if(is_string($limit)){
         $limit = str2byteInt($limit);
      }
      if($limit != 0 && strlen($header.$body) > $limit){
         $this->m_error = -1;
		   $this->m_errormsg = "fetch limit reached";
         return null;
      }

      $header = new imap_header($header, $this->m_charset_decode);
      if(strtolower($header->m_encoding) == "base64"){
         if(is_base64_encoded($header->m_subject, true)){
            $header->m_subject = base64_decode($header->m_subject);
            if(strtoupper($this->m_charset_decode)!="UTF-8"){
               $header->m_subject = ascii_non_visible_decode($header->m_subject);
            }   
         }   
         $body = trim($body);
         
         if($header->m_encoding == "base64" || is_base64_encoded($body, true)){
            $tmp = $body;
            
            $pos = strpos($tmp, "==");
      		if($pos !== false){
      		   $tmp = substr($tmp, 0, $pos+2);
      		}   
               
            $tmp = base64_decode($tmp);
            if($tmp !== false){
               $body = $tmp;
            }  
            $tmp = null; 
            
            if(strtoupper($this->m_charset_decode)!="UTF-8"){
               $body = ascii_non_visible_decode($body);
            } 
           
         }   
      }else if(strtolower($header->m_charset) == "utf-8"){      
                         
         if(strtoupper($this->m_charset_decode)!="UTF-8"){
            $header->m_subject = utf8_decode($header->m_subject);
            $header->m_subject = ascii_non_visible_decode($header->m_subject);                  
         }else{
            $header->m_subject = utf8_fix($header->m_subject);
         }
          
         
         if(strtoupper($this->m_charset_decode)!="UTF-8"){
            $body = utf8_decode($body);
            $body = ascii_non_visible_decode($body);
         }else{
            $body = utf8_fix($body);
         }
                
      }
      // for test only
      //file_put_contents($GLOBALS["DOCROOT"]."/logs/body.data", $body); 
     
      $body = new imap_body($body, $header->m_boundary, $this->m_uid, $this->m_charset_decode, $header->m_charset);
      
      $msg = new imap_msg($header, $body);

      $this->m_error = 0;
		$this->m_errormsg = "fetch ok";
      return $msg;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * The STORE command alters data associated with a message in the mailbox.
    *
    * @param string $msg_set
    * @param string $msg_data_name
    * @param bool $use_uid
    * @return string
    */
   function store($msg_set, $msg_data_name, $value, $use_uid=false){
   	if(!$this->m_login){return false;}
      if(empty($this->m_mailbox)){return false;}

   	$msg_set = trim($msg_set);
   	$msg_data_name = trim($msg_data_name);

   	if($use_uid){
		   $this->send($this->m_uid." UID STORE ".$msg_set." ".$msg_data_name." (".$value.")");
		}else{
		   $this->send($this->m_uid." STORE ".$msg_set." ".$msg_data_name." (".$value.")");
		}

   	$ret = $this->receive();
      if(strpos($ret, $this->m_uid) === false || strpos($ret, "OK") === false){
         $this->m_error = -1;
         $this->m_errormsg = "store failed";
         return false;
      }
      $this->m_error = 0;
		$this->m_errormsg = "store ok";
   	return $ret;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * mark message as seen
    *
    * @param int $id
    * @param bool $use_uid
    * @return bool
    */
   function seen($id, $use_uid=false){
      if($this->store($id, "+Flags", "\\Seen", $use_uid) !== false){
         return true;
      }
      return false;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * mark message as recent / unseen
    *
    * @param int $id
    * @param bool $use_uid
    * @return bool
    */
   function recent($id, $use_uid=false){
      if($this->store($id, "-Flags", "\\Seen", $use_uid) !== false){
         return true;
      }
      return false;
   }   
//------------------
   /**
    * mark message as unseen / recent
    *
    * @param int $id
    * @param bool $use_uid
    * @return bool
    */
   function unseen($id, $use_uid=false){
      return $this->recent($id, $use_uid);      
   }      
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * delete a mail
    *
    * @param int $id
    * @param bool $use_uid
    * @return bool
    */
   function delete_msg($id, $use_uid=false){
      if($this->store($id, "+Flags", "\\Deleted", $use_uid) !== false){
         return true;
      }
      return false;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
/**
    * undelete a mail
    *
    * @param int $id
    * @param bool $use_uid
    * @return bool
    */
   function undelete_msg($id, $use_uid=false){
      if($this->store($id, "-Flags", "\\Deleted", $use_uid) !== false){
         return true;
      }
      return false;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * array with unseen mails
    *
    * @return array
    */
   function list_msg_unseen($use_uid=false){
      return $this->search('UNSEEN', "", $use_uid);
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * array with undeleted mails
    *
    * @return array
    */
   function list_msg_undeleted($use_uid=false){
      return $this->search('UNDELETED', "", $use_uid);
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * array with seen mails
    *
    * @return array
    */
   function list_msg_seen($use_uid=false){
      return $this->search('SEEN', "", $use_uid);
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * array with deleted mails
    *
    * @return array
    */
   function list_msg_deleted($use_uid=false){
      return $this->search('DELETED', "", $use_uid);
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    *  The EXPUNGE command permanently removes from the currently selected mailbox all messages that have the \Deleted flag set.
    *
    * @return string
    */
   function expung_deleted_msg(){
      if(!$this->m_login){return false;}
      if(empty($this->m_mailbox)){return false;}

		$this->send($this->m_uid." EXPUNGE");

   	$ret = $this->receive();
      if(strpos($ret, $this->m_uid) === false || strpos($ret, "OK") === false){
         $this->m_error = -1;
         $this->m_errormsg = "expunge failed";
         return false;
      }
      $this->m_error = 0;
		$this->m_errormsg = "expunge ok";
   	return $ret;
   }
}
//-------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------
class imap_msg{
// public
   /**
    * imap header object
    *
    * @var imap_header
    */
   var $m_header = null;
   /**
    * imap body object
    *
    * @var imap_body
    */
   var $m_body = null;
//-------------------------------------------------------------------------------------------------------------------------------------
// constructor
    function imap_msg($header, $body){
       $this->m_header = $header;
       $this->m_body = $body;
    }
//-------------------------------------------------------------------------------------------------------------------------------------
}
//-------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------
class imap_header{
// private
   var $m_charset_decode = "UTF-8";
   var $m_data = "";
// public
   var $m_to = "";
   var $m_cc = "";
   var $m_from = "";
   var $m_subject = "";
   var $m_date = "";
   var $m_content_type = "";
   var $m_charset = "";
   var $m_boundary = "";
   var $m_encoding = "";
//-------------------------------------------------------------------------------------------------------------------------------------
   function parse_charset($str){             		   
      $str = strtoupper($str);
	   $pos = strpos($str, '?Q?');
	   if($pos === false){
	      $pos = strpos($str, '?B?');
	   }
	   
	   if($pos !== false){
	      $str = left($str, $pos);
	      
	      $pos = strpos($str, '=?');
	      if($pos !== false){
	         $str = substr($str, $pos+2);
	         return $str;
	      }    		      
	   }   
	   return false;
   }   
//-------------------------------------------------------------------------------------------------------------------------------------
// constructor
    function imap_header($header_data, $charset){
         $this->m_charset_decode = $charset;

    		$this->m_data = $header_data;

    		$header_data = str_replace("\r\n ", " ", $header_data);
    		$header_data = str_replace("\r\n\t", " ", $header_data);
    		$data_list = explode("\r\n", $header_data);

    		$subject_index = -1;
    		for($i = 0; $i < acount($data_list); $i++){
    		   if(strtolower(substr($data_list[$i], 0, 5)) == "from:"){
    		      $from = $data_list[$i];
    		      $from = trim(strricut($from, "from:",true));
    		      $from = iso_decode($from);
    		      if(strtoupper($this->m_charset_decode)=="UTF-8"){          
    		         $charset = $this->parse_charset($data_list[$i]);    		       		       		            
    		         $from = utf8_fix($from, $charset);
    		      }   
    		      $this->m_from = $from;
    		   }
    		   if(strtolower(substr($data_list[$i], 0, 3)) == "to:"){
    		      $to = $data_list[$i];
    		      $to = trim(strricut($to, "to:",true));
    		      $to = iso_decode($to);
    		      if(strtoupper($this->m_charset_decode)=="UTF-8"){          
    		         $charset = $this->parse_charset($data_list[$i]);    		       		       		            
    		         $to = utf8_fix($to, $charset);
    		      }   
    		      $this->m_to = $to;
    		   }
    		   if(strtolower(substr($data_list[$i], 0, 3)) == "cc:"){
    		      $cc = $data_list[$i];
    		      $cc = trim(strricut($cc, "cc:",true));
    		      $cc = iso_decode($cc);
    		      if(strtoupper($this->m_charset_decode)=="UTF-8"){          
    		         $charset = $this->parse_charset($data_list[$i]);    		       		       		            
    		         $cc = utf8_fix($cc, $charset);
    		      }   
    		      $this->m_cc = $cc;
    		   }
    		   if(strtolower(substr($data_list[$i], 0, 8)) == "subject:"){
    		      $subject_index = $i;
    		      $subject = $data_list[$i];
    		      $subject = trim(strricut($subject, "subject:",true));    		      
    		      $subject = iso_decode($subject);
    		      
    		      if(strtoupper($this->m_charset_decode)=="UTF-8"){          
    		         $charset = $this->parse_charset($data_list[$i]);    		       		       		            
    		         $subject = utf8_fix($subject, $charset);
    		      } 
    		          		        
    		      $this->m_subject = $subject;
    		   }
    		   if(strtolower(substr($data_list[$i], 0, 26)) == "content-transfer-encoding:"){
    		      $encoding = $data_list[$i];
    		      $encoding = trim(strricut($encoding, "content-transfer-encoding:",true));
    		      $this->m_encoding = $encoding;
    		   }
    		   if(strtolower(substr($data_list[$i], 0, 5)) == "date:"){
    		      $date = $data_list[$i];
    		      $date = trim(strricut($date, "date:",true));

    		      $mounth_short = array("Jan", "Feb", "Mar", "Apr", "May", "Jun",
                                    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");

               if(substr($date,3,1) == ","){$date = trim(substr($date, 4));}
               $date = explode(" ", $date);
               $mounth = array_search($date[1], $mounth_short);
               $mounth += 1;
               $date[1] = $mounth;

    		      $this->m_date = strzero($date[2],2)."-".strzero($date[1],2)."-".strzero($date[0],2)." ".$date[3];
    		   }
    		   if(strtolower(substr($data_list[$i], 0, 13)) == "content-type:"){
               $temp = explode(";", $data_list[$i]);

               $this->m_content_type = trim(strricut($temp[0], "content-type:",true));
               if(acount($temp) > 1){
                  if(stripos($temp[1], "charset=") !== false){
                     $this->m_charset = trim(strricut($temp[1], "charset=",true));
                     $this->m_charset = str_replace("\"","",$this->m_charset);
                  }   
               }   
               for($v = 1; $v < acount($temp); $v++){
                  if(stripos($temp[$v], "boundary=") !== false){
                     $this->m_boundary = trim(strricut($temp[$v], "boundary=",true));
                     $this->m_boundary = str_replace('"',"",$this->m_boundary);
                  }
               }
    		   }

    		}
    		if($subject_index > -1 && empty($this->m_charset)){
    		   $this->m_charset = $this->parse_charset($data_list[$subject_index]);    		       		   
    		   if(empty($this->m_charset)){ $this->m_charset = 'ISO-8859-1';}   		   
    		}
    		//print_d($header_data);
    		//echo HR.'detected charset: '.$this->m_charset.HR;
    }
//-------------------------------------------------------------------------------------------------------------------------------------
}
//-------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------
class imap_body{
// private
   var $m_data = "";
   var $m_charset_decode = "UTF-8";
   var $m_charset = "";
// public
   var $m_boundarys;
   var $m_text = "";
   var $m_html = "";
   /**
    * list contain imap_attachment objects
    *
    * @var array
    */
   var $m_attachments = array();

//-------------------------------------------------------------------------------------------------------------------------------------
// constructor
    function imap_body($msg_data, $boundary, $uid, $charset_decode, $charset){             
         $this->m_charset_decode = $charset_decode;
         $this->m_charset = $charset;
         
                  
    		$this->m_data = $msg_data;
         $this->m_boundarys = array("--".$boundary, "--".$boundary."--");

         if(empty($boundary)){
            if(stripos($msg_data, "</html>")===false){
               $this->m_text = strrcut($msg_data, "}", true);
               $pos = strpos($this->m_text, ")\r\n".$uid);
               if($pos !== false){
                  $this->m_text = substr($this->m_text, 0, $pos);
               }
               $this->m_text = quoted_printable_decode($this->m_text);
               
               if(($deq_pos = strpos($msg_data, "==")) !== false){ // fix exchange server
                  $tmp = trim(substr($msg_data, 0, $deq_pos+2));
                  
                  if(is_base64_encoded($tmp,true)){
                     $this->m_text = base64_decode($tmp);
                  }
               }             
               
               if(strtoupper($charset_decode)=="UTF-8"){          
                  if(!is_utf8($this->m_text)){
                     $this->m_text = utf8_encodeEx($this->m_text);                                  
                  }                     
               }else{
                  if(is_utf8($this->m_text)){
                     $this->m_text = utf8_decode($this->m_text);                                 
                  }
               }                                          
                                                                           
               return;
               
               
            }else{
               $this->m_html = strrcut($msg_data, "<html", false);
               $pos = stripos($this->m_html, "</html>");
               if($pos !== false){
                  $this->m_html = substr($this->m_html, 0, $pos+7);
               }
               $this->m_html = strrcut($this->m_html, "<body", false);
               $pos = stripos($this->m_html, "</body>");
               if($pos !== false){
                  $this->m_html = substr($this->m_html, 0, $pos+7);
               }
               $this->m_text = html2text($this->m_html);
               
               if(strtoupper($charset_decode)=="UTF-8"){          
                  if(!is_utf8($this->m_text)){
                     $this->m_text = utf8_encodeEx($this->m_text);                                  
                  }                     
               }else{
                  if(is_utf8($this->m_text)){
                     $this->m_text = utf8_decode($this->m_text);                                 
                  }
               }       
               
               return;
            }
         }

         $this->getAdditionalBoundrys($msg_data);
         $parts = $this->splittParts($msg_data);
         
         /* // old slow way to get additional boundrys and parts
         $lines = explode("\r\n", $msg_data);
         $clines = acount($lines);
         $parts = array();
         $part = "";
         $l = 0;
         while($l < $clines){
            $line = null;
            $line = $lines[$l];
            $isBoundLine = false;
            $isBoundLineEnd = false;
            if(substr($line,0,2) == "--"){
               $isBoundLine = array_search($line, $this->m_boundarys);
               $isBoundLineEnd = array_search($line, $this->m_boundarys);
            }
            if($isBoundLine === false && $isBoundLineEnd === false){
               $part .= $line."\r\n";

               if(stripos($part, "boundary=") !== false){
                  $boundaryX = trim(strricut($part, "boundary=",true));
                  $boundaryX = str_replace('"',"",$boundaryX);
                  $found = array_search("--".$boundaryX, $this->m_boundarys);
                  if($found === false){
                     $this->m_boundarys[] = "--".$boundaryX;
                     $this->m_boundarys[] = "--".$boundaryX."--";
                  }
               }
            }else{
               $parts[] = $part;
               $part = "";
            }
            $l++;
         }
         $lines = array();
         $parts[] = $part;
         */

         $cparts = acount($parts);
         for($p = 0; $p < $cparts; $p++){
            //echo $parts[$p]."<hr>";
            
            
            $bound_head = strcut($parts[$p], "\r\n\r\n");
            if(stripos($bound_head, "Content-Type:") !== false){
            
               if(stripos($bound_head, "text/plain;") !== false){
                  $this->parse_text($parts[$p]);
               }else if(stripos($bound_head, "text/html;") !== false){
                  $this->parse_html($parts[$p]);
               }else if(stripos($bound_head, "name=") !== false){
                  $this->parse_file($parts[$p]);
               }
            }   
         }
         //print_d($data);
    }
//-------------------------------------------------------------------------------------------------------------------------------------
// private
   function getAdditionalBoundrys($msg_data){
      while($msg_data != ""){
         $pos = stripos($msg_data, "boundary=");
         if($pos !== false){
            $msg_data = substr($msg_data, $pos);
            $pos = strpos($msg_data, "\r\n");
            $boundaryX = "";
            if($pos !== false){
               $boundaryX = substr($msg_data, 0, $pos);
               $msg_data = substr($msg_data, $pos+2);
            }else{
               $boundaryX = substr($msg_data, 0);
               $msg_data = "";
            }
            $boundaryX = trim(strricut($boundaryX, "boundary=",true));
            $boundaryX = str_replace('"',"",$boundaryX);
            $found = array_search("--".$boundaryX, $this->m_boundarys);
            if($found === false){
               $this->m_boundarys[] = "--".$boundaryX;
               $this->m_boundarys[] = "--".$boundaryX."--";
            }
         }else{
            $msg_data = "";
         }
      }
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   function splittParts($msg_data){
      $parts = array($msg_data);
      $cbundarys = count($this->m_boundarys);
      for($b = 0; $b < $cbundarys; $b++){
          $cparts =  count($parts);
          $xparts = array();
          for($p = 0; $p < $cparts; $p++){
              $part = $parts[$p];
              $xparts = array_merge($xparts, explode($this->m_boundarys[$b]."\r\n", $part));
          }
          $parts = $xparts;
      }
      return $parts;
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   function parse_text($data){
         $pos = strpos($data, "\r\n\r\n");
         if($pos !== false){
            $head = substr($data, 0, $pos);
            $text = substr($data, $pos+2);
            if(trim($text) != ""){
               if(stripos($head, "base64") !== false){
                  $text = base64_decode($text);
               }   
               if(stripos($head, "quoted-printable") !== false || is_utf8($text)){
                  $text = quoted_printable_decode($text);               
               }   
               if(stripos($head, "utf-8") !== false){
                  if(strtoupper($this->m_charset_decode)!="UTF-8"){          
                     $text = utf8_decode($text);                                 
                  }   
               }else if(stripos($head, "utf-8") === false){
                  if(strtoupper($this->m_charset_decode)=="UTF-8"){          
                     if(!is_utf8($text)){
                        $text = utf8_encodeEx($text, $this->m_charset);                                  
                     }                     
                  }
               }
               $this->m_text = $text;
            }

            $str = $this->m_text;

            $tmp = "";
            while($str != ""){
             $pos = stripos($str, "<http://");

             if($pos !== false){
                $tmp .= substr($str, 0, $pos);
                $str = substr($str, $pos);

                $pos = strpos_next_word($str);

                $str = substr($str, $pos);
                $tmp .= " ";
             }else{
                $tmp .= " ".$str;
                $str = "";
             }
            }
            $str = $tmp;

            $tmp = "";
            while($str != ""){
             $pos = stripos($str, "<mailto:");

             if($pos !== false){
                $tmp .= substr($str, 0, $pos);
                $str = substr($str, $pos);

                $pos = strpos_next_word($str);

                $str = substr($str, $pos);
                $tmp .= " ";
             }else{
                $tmp .= " ".$str;
                $str = "";
             }
            }
            $str = $tmp;

            if(strtoupper($this->m_charset_decode)!="UTF-8"){
               $str = ascii_non_visible_decode($str);
            }
            $this->m_text = $str;

         }
   }
//-------------------------------------------------------------------------------------------------------------------------------------
function parse_html($data){
         $pos = strpos($data, "\r\n\r\n");
         if($pos !== false){
            $head = substr($data, 0, $pos);
            $html = substr($data, $pos+2);

            if(trim($html) != ""){
               if(stripos($head, "base64") !== false){
                  $html = base64_decode($html);
               }   
               if(stripos($head, "quoted-printable") !== false || is_utf8($html)){
                  $html = quoted_printable_decode($html);               
               }                                           
               if(stripos($head, "utf-8") !== false){
                  if(strtoupper($this->m_charset_decode)!="UTF-8"){          
                     $html = utf8_decode($html);                                 
                  }   
               }else if(stripos($head, "utf-8") === false){
                  if(strtoupper($this->m_charset_decode)=="UTF-8"){                                                             
                     if(!is_utf8($html)){
                        $html = utf8_encodeEx($html, $this->m_charset);                                  
                     }
                  }
               }                                             
               
               $this->m_html = $html;               
            }
            if(strtoupper($this->m_charset_decode)!="UTF-8"){
               $this->m_html = ascii_non_visible_decode($this->m_html);
            }            
         }
   }
//-------------------------------------------------------------------------------------------------------------------------------------
   function parse_file($data){
         $pos = strpos($data, "\r\n\r\n");
         if($pos !== false){
            $head = substr($data, 0, $pos);
            $file = substr($data, $pos+2);
            
            if(trim($file) != ""){
               $description = substr($data, 0, $pos);
               $description = explode("\r\n",$description);

               $filename = "";
               $cdescription = acount($description);
               for($i = 0; $i < $cdescription; $i++){
                  if(stripos($description[$i], "name=") !== false){
                     $filename = strricut($description[$i], "name=", true);
                     $pos = strpos($filename, ";");
                     if($pos !== false){
                        $filename = substr($filename, 0, $pos);
                     }
                     $filename = trim($filename);                     
                     $filename = str_replace("\"", "", $filename);                     
                  }
               }

               $att = new imap_attachment($this->m_charset_decode);
               
               if(strtoupper($this->m_charset_decode)!="UTF-8"){          
                  $filename = ascii_non_visible_decode(iso_decode($filename));
               }
               $fileext = extractFileExt($filename);                                           
               $filename = extractFileName($filename);                                           
               $fileext = trim(preg_replace("/[^A-Z]/i","",$fileext));      
               $att->m_filename = $filename.".".$fileext;

               // for test only
               //file_put_contents($GLOBALS["DOCROOT"]."/logs/base64.data", $file); 
               
               if(stripos($head, "base64") !== false){
                  $file = base64_decode($file);
               }else if(stripos($head, "quoted-printable") !== false){
                  $file = quoted_printable_decode($file);               
               }else if(stripos($head, "utf-8") !== false){
                  if(strtoupper($this->m_charset_decode)!="UTF-8"){          
                     $file = utf8_decode($file);                                 
                  }   
               }else if(stripos($head, "utf-8") === false){
                  if(strtoupper($this->m_charset_decode)=="UTF-8"){          
                     if(!is_utf8($file)){
                        $file = utf8_encodeEx($file, $this->m_charset);                                  
                     }
                  }
               }   
               
               
               $att->m_data = $file;  
               
               
               $this->m_attachments[] = $att;
            }
         }
   }
//-------------------------------------------------------------------------------------------------------------------------------------
}
//-------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------
class imap_attachment{
// private
   var $m_charset_decode = "UTF-8";
// public
   var $m_filename = "";
   var $m_data = "";
//-------------------------------------------------------------------------------------------------------------------------------------
// constructor
    function imap_attachment($charset_decode){
      $this->m_charset_decode = $charset_decode;      
    }
//-------------------------------------------------------------------------------------------------------------------------------------
}

// for debug
//$imap = new imap_header(file_get_contents("W:/carolina.panthermedia.net/test/imap.data_gmail"), "UTF-8");
//$imap = new imap_body(file_get_contents("C:/Programme/Apache Software Foundation/Apache2.2/htdocs/test.net/imap.data"), "----=_NextPart_000_000D_01C84EC4.C76A5410", "01");
//$imap = new imap_header(file_get_contents("W:/richie.panthermedia.net/test/imap.header.data"), "UTF-8");
//$imap = new imap_body(file_get_contents("W:/richie.panthermedia.net/test/imap.body.data"), "crVCL-Mail-1.7-beta-Mixed--e95e512bbed92bdeb359bd60df6dae36", "27", "UTF-8", "UTF-8");
//if(empty($imap->m_text)){
//   $mailtxt = html2text($imap->m_html);
//} 
//$x = 1;   
/*$imap = new imap();
$imap->fetch_msg(27, true);*/

//file_put_contents("W:/richie.panthermedia.net/test/base64.jpg", base64_decode(file_get_contents("W:/richie.panthermedia.net/test/base64.data")));


   
############################################################
}
############################################################
?>
Return current item: crVCL PHP Framework