Location: PHPKode > scripts > AfterLogic WebMail Lite PHP > afterlogic-webmail-lite-php/webmail/adminpanel/plugins/webmail/common/libs/class_imap.php
<?php

/*
 * AfterLogic Admin Panel by AfterLogic Corp. <hide@address.com>
 *
 * Copyright (C) 2002-2010  AfterLogic Corp. (www.afterlogic.com)
 * Distributed under the terms of the license described in LICENSE.txt
 * 
 */

	define('USE_LSUB', false);

/**
 * @author Harish Chauhan
 */
class IMAPMAIL
{
	var $host;			/* host like 127.0.0.1 or mail.yoursite.com */
	var $port;			/* port default is 110 or 143 */
	var $user;			/* user for logon */
	var $password;		/* user paswword */
	var $state;			/* variable define diffrent state of connection */
	var $connection;	/* handle to a open connection */
	var $error;			/* error string */
	var $must_update;
	var $tag;
	var $mail_box;
	var $response_text;
	
	var $_oLog = null;
	var $_bLogEnable = false;

	var $_capas = null;
	
	function IMAPMAIL()
	{
		$this->host = null;
		$this->port = 143;
		$this->user = '';
		$this->password = '';
		$this->state = 'DISCONNECTED';
		$this->connection = null;
		$this->error = '';
		$this->must_update = false;
		$this->UpdateTag();
		
		$this->_oLog = true;
		$this->_bLogEnable = true;
	}
	
	/**
	 * @param	string	$_string
	 */
	function _log($_string)
	{
		if (null !== $this->_oLog && $this->_bLogEnable)
		{
			CAdminPanel::Log($_string);
		}
	}
	
	/**
	 * This functiuon set the host
	 * @example popmail::set_host("mail.yoursite.com")
	 * 
	 * @param string $host
	 */
	function set_host($host)
	{
		$this->host = $host;
	}
	
	/**
	 * This functiuon set the port
	 * @example popmail::set_port(110)
	 * 
	 * @param int $port
	 */
	function set_port($port)
	{
		$this->port = $port;
	}
	
	/**
	 * This functiuon is to retrive the error of last operation
	 * @example popmail::get_error()
	 * 
	 * @return string
	 */
	function get_error()
	{
		return $this->error;
	}
	
	/**
	 * This functiuon is to retrive the state of connaction
	 *
	 * @return string
	 */
	function get_state()
	{
		return $this->state;
	}

	/**
	 * Function is used to open connection
	 *
	 * @param	string	$host
	 * @param	int		$port
	 * @return	bool
	 */
	function open($host = '', $port = '')
	{
		if (!empty($host))
		{
			$this->host = $host;
		}
		if (!empty($port))
		{
			$this->port = $port;
		}
		
		return $this->open_connection();
	}

	/**
	 * close the active connection
	 *
	 * @return bool
	 */
	function close()
	{
		$this->logout();
		@fclose($this->connection);
		$this->connection = null;
		$this->state = 'DISCONNECTED';
		return true;
	}

	/*
	 * The Functions is written bellow is the subordinate functions used in
	 * communication with SERVER.
	 */

	/* This function is used to get response line from server */
	function get_line()
	{
		$return = false;
		if ($this->connection)
		{
			$return = @fgets($this->connection, 512);
			if ($this->_bLogEnable)
			{
				$this->_log('IMAP4 < '.ap_Utils::ShowCRLF($return));
			}

			if (!$return)
			{
				$_socket_status = @socket_get_status($this->connection);
				if (isset($_socket_status['timed_out']) && $_socket_status['timed_out'])
				{
					$this->error = 'Error : Socket timeout reached during IMAP4 connection.';
				}
			}
		}
		
		return $return;
	}
	
	/* This functiuon is to retrive the full response message from server */
	function get_server_responce()
	{	
		$response = array();
		$l = strlen($this->tag);
		while(1)
		{
			$new = $this->get_line();
			if ($new == false)
			{
				break;
			}

			if (substr($new, 0, $l) == $this->tag)
			{
				$response[] = $new;
				break;
			}

			$response[] = $new;
		}
		return trim(implode("\r\n", $response));
	}

	/**
	 * this functiuon is to send the command to server
	 *
	 * @param string $msg
	 * @return bool
	 */
	function put_line($msg = '')
	{
		if ($this->_bLogEnable)
		{
			$this->_log('IMAP > '.$msg);
		}
		
		if (!@fputs($this->connection, $msg."\r\n"))
		{
			$this->error = 'Error : Could not send user request.';
			return false;
		}
		return true;
	}

	/*
	 * The Functions is written bellow is the main commands defined in IMAP
	 * protocol.
	 */
	
	/**
	 * This functiuon is to open the connection to the server
	 *
	 * @return bool
	 */
	function open_connection()
	{
		if (!$this->_checkState_0('DISCONNECTED')) return false;
		
		if (empty($this->host) || empty($this->port))
		{
			$this->error = 'Error : Either HOST or PORT is undifined!';
			return false;
		}
		
		$host = $this->host;
		$isSsl = ((strlen($host) > 6) && strtolower(substr($host, 0, 6)) == 'ssl://');
		if (function_exists('openssl_open') && ($isSsl || $this->port == 993))
		{
			if (!$isSsl)
			{
				$host = 'ssl://'.$host;
			}
		}
		else 
		{
			if ($isSsl)
			{
				$host = substr($host, 6);
			}
		}
		
		$errno = $errstr = null;
		CAdminPanel::Log('IMAP4 > Start connect to '.$host.':'.$this->port);
		$this->connection = @fsockopen($host, $this->port, $errno, $errstr, 10);
		if (!$this->connection)
		{
			$this->error = 'Could not make a connection to server , Error : '.$errstr.' ('.$errno.')';
			return false;
		}

		/* set socket timeout
         * it is valid for all other functions! */
		@socket_set_timeout($this->connection, 20);
        /* socket_set_blocking($this->connection, true); */
        
		$this->get_line();
		$this->state = 'AUTHORIZATION';
		$this->InitCapa();
		return true;
	}

	/**
	 * The get_capability function returns a listing of capabilities that the
	 * server supports.
	 * 
	 * @return string|false
	 */
	function get_capability()
	{
		if (!$this->_checkState_0('AUTHORIZATION')) return false;

		$this->UpdateTag();
		if ($this->put_line($this->tag.' CAPABILITY'))
		{
			$response = $this->get_server_responce();
			if ($this->_checkResponse($response))
			{
				return $response;
			}
		}

		return false;
	}

	/**
	 * 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->_checkState_0('AUTHORIZATION')) return false;

		$this->UpdateTag();
		if ($this->put_line($this->tag.' NOOP'))
		{
			if ($this->_checkResponse($this->get_server_responce()))
			{
				return true;
			}
		}

		return false;
	}

	/**
	 * The logout function informs the server that the client is done with the connection.
	 *
	 * @return bool
	 */
	function logout()
	{
		if (!$this->_checkState_0('AUTHORIZATION')) return false;

		$this->UpdateTag();
		if ($this->put_line($this->tag.' LOGOUT'))
		{
			if ($this->_checkResponse($this->get_server_responce()))
			{
				return true;
			}
		}

		return false;
	}

	/**
	 * This function is used to authenticate the user
	 * arguments $auth_str is a authorization String example LOGIN
	 * $ans_str1 and $ans_str2 is a base 64 encoded answer string to server
	 * Example if it authentication type is login then user your userid and password
	 * as ans_str1 and ans_str2
	 * 
	 * @param unknown_type $auth_str
	 * @param unknown_type $ans_str1
	 * @param unknown_type $ans_str2
	 * @return unknown
	 */
	function authenticate($auth_str, $ans_str1 = '', $ans_str2 = '')
	{
		if (!$this->_checkState_1('DISCONNECTED')) return false;
		if (!$this->_checkState_1('AUTHENTICATED')) return false;

		$this->UpdateTag();
		if ($this->put_line($this->tag.' AUTHENTICATE '.$auth_str))
		{
			$response = $this->get_line();
			if (strtok($response, ' ') == '+')
			{
				$ans_str1 = base64_encode($ans_str1);
				$this->put_line($ans_str1);
			}
			else
			{
				$this->error = 'Error : '.$response;
				return false;
			}
			$response = $this->get_line();
			if (strtok($response, ' ') == '+')
			{
				$ans_str2 = base64_encode($ans_str2);
				$this->put_line($ans_str2);
			}
			else
			{
				$this->error = 'Error : '.$response;
				return false;
			}
			$response = $this->get_line();
			if ($this->_checkResponse($response))
			{
				$this->state = 'AUTHENTICATED';
				return $response;
			}
		}

		return false;
	}
	
	/**
	 * This function is used to login into server
	 * $user is a valid username and $pwd is a valid password.
	 *
	 * @param string $user
	 * @param string $pwd
	 * @return bool
	 */
	function login($user, $pwd)
	{
		if (!$this->_checkState_1('DISCONNECTED')) return false;
		if (!$this->_checkState_1('AUTHENTICATED')) return false;

		$this->UpdateTag();
		if ($this->put_line($this->tag.' LOGIN "'.$this->quote($user).'" "'.$this->quote($pwd).'"'))
		{
			if ($this->_checkResponse($this->get_server_responce()))
			{
				$this->state = 'AUTHENTICATED';
				return true;
			}
		}

		return false;
	}
	
	/**
	 * @param string $text
	 * @return int
	 */
	function get_mailbox_count($text)
	{
		$arr = array();
		preg_match_all('/\* (\d+) EXISTS/i', $text, $arr);	
		
		return isset($arr[1][0]) ? (int) $arr[1][0] : 0;
	}
	
	/**
	 * @param string $str
	 * @return string
	 */
	function quote($str)
	{
		return strtr($str, array('"' => '\\"', '\\' => '\\\\'));
	}
	
	/**
	 * This function create a mail box
	 *
	 * @param string $mailbox_name
	 * @return bool
	 */
	function create_mailbox($mailbox_name)
	{
		if (!$this->_checkState_1('AUTHORIZATION')) return false;

		$this->UpdateTag();
		if ($this->put_line($this->tag.' CREATE "'.$mailbox_name.'"'))
		{
			if ($this->_checkResponse($this->get_server_responce()))
			{
				return true;
			}
		}
		
		setGlobalError($this->error);
		return false;
	}

	/**
	 * This function delete exists mail box
	 *
	 * @param string $mailbox_name
	 * @return bool
	 */
	function delete_mailbox($mailbox_name)
	{
		if (!$this->_checkState_1('AUTHORIZATION')) return false;

		$this->UpdateTag();
		if ($this->put_line($this->tag.' DELETE "'.$mailbox_name.'"'))
		{
			if ($this->_checkResponse($this->get_server_responce()))
			{
				return true;
			}
		}

		return false;
	}

	/**
	 * The subscribe_mailbox command adds the specified mailbox name to the
	 * server's set of "active" or "subscribed" mailboxes
	 * 
	 * @param string $mailbox_name
	 * @return bool
	 */
	function subscribe_mailbox($mailbox_name)
	{
		if (!$this->_checkState_1('AUTHORIZATION')) return false;

		$this->UpdateTag();
		if ($this->put_line($this->tag.' SUBSCRIBE "'.$mailbox_name.'"'))
		{
			if ($this->_checkResponse($this->get_server_responce()))
			{
				return true;
			}
		}

		return false;
	}
	
	/* 
	 * The subscribe_mailbox command removes the specified mailbox name to the
	 * server's set of "active" or "subscribed" mailboxes 
	 * 
	 * @param string $mailbox_name
	 * @return bool
	 */
	function unsubscribe_mailbox($mailbox_name)
	{
		if (!$this->_checkState_1('AUTHORIZATION')) return false;

		$this->UpdateTag();
		if ($this->put_line($this->tag.' UNSUBSCRIBE "'.$mailbox_name.'"'))
		{
			if ($this->_checkResponse($this->get_server_responce()))
			{
				return true;
			}
		}

		return false;
	}

	/**
	 * @param string $delimiter
	 * @param string $ref_mail_box = ''
	 * @param string $wild_card = '*'
	 * @param string $_isSub = false
	 * @return array
	 */
	function &_in_list_mailbox(&$delimiter, $ref_mail_box = '', $wild_card = '*', $_isSub = USE_LSUB)
	{
		$false = false;
		if (!$this->_checkState_1('AUTHORIZATION')) return $false;
		
		$return_arr = null;
		$firstDelimiter = $delimiter;
		
		if (trim($ref_mail_box) == '')
		{
			$ref_mail_box = '""';
		}
		
		$_line = ($_isSub) ? 'LSUB' : 'LIST';

		$this->UpdateTag();
		if ($this->put_line($this->tag.' '.$_line.' '.$ref_mail_box.' '.$wild_card))
		{
			$response = $this->get_server_responce();
			if (!$this->_checkResponse($response))
			{
				return $return_arr;
			}
		}
		else
		{
			$this->error = 'Error : Could not send User request.';
			return $return_arr;
		}
		
		$temp_arr = explode("\r\n", $response);
		 
		$lit = null;
		$litString = null;
		$return_arr = array();
		for ($i = 0, $c = count($temp_arr) - 1; $i < $c; $i++)
		{
			$line = $temp_arr[$i];
			if (substr($line, 0, 6) == '* '.$_line)
			{
				$foldersParts = explode(')', $line, 2);
				if (strpos(strtolower($foldersParts[0]), '\noselect') !== false)
				{
					continue;
				}
				
				$parts = explode(' ', $foldersParts[1], 3);
				if (trim($parts[1]) != 'NIL')
				{
					$delimiter = trim($parts[1], '"');
				}
				
				$delimiter = (strlen($delimiter) > 0) ? $delimiter{strlen($delimiter) - 1} : $firstDelimiter;
				
				$name = $parts[2];
				
				if ($name{strlen($name) - 1} == '}' && strpos($name, '{') !== false)
				{
					$start = strpos($name, '"');;
					$startIndex =  strpos($name, '{');
					$endIndex =  strpos($name, '}');
				
					if (($start === false || $start > $startIndex) && $startIndex < $endIndex)
					{
						$lit = substr($name, $startIndex + 1, $endIndex - $startIndex - 1);
						if (is_numeric($lit))
						{
							$lit = (int) $lit;
						}
						else
						{
							$lit = null;
						}
					}
				}
				
				if ($lit === null)
				{
					$name = trim($name, '"'.$delimiter);
					array_push($return_arr, $name);
				}
				else
				{
					$litString = $name;
				}
			}
			else if ($lit > 0)
			{
				$litline = substr($line, 0, $lit);
				$litString = str_replace('{'.$lit.'}', $litline, $litString);
				
				$litString = trim($litString, '"'.$delimiter);
				array_push($return_arr, $litString);
				
				$litString = null;
				$lit = null;
			}
		}
		
		return $return_arr;
	}
	
	/**
	 * 
	 * 	The list_mailbox command gets the specified list of mailbox
	 *
	 *	$ref_mail_box	$wild_card   	Interpretation
	 *	Reference    	Mailbox Name  	Interpretation
	 *	------------  	------------  	--------------
	 *	~smith/Mail/  	foo.*         	~smith/Mail/foo.*
	 *	archive/      	%             	archive/%
	 *	#news.        	comp.mail.*   	#news.comp.mail.*
	 *	~smith/Mail/  	/usr/doc/foo  	/usr/doc/foo
	 *	archive/      	~fred/Mail/*  	~fred/Mail/*
	 * 
	 * @param string $delimiter
	 * @param string $ref_mail_box = ''
	 * @param string $wild_card = '*'
	 * @return array
	 */
	function &list_mailbox(&$delimiter, $ref_mail_box = '', $wild_card = '*')
	{
		$_sub =& $this->_in_list_mailbox($delimiter, $ref_mail_box, $wild_card); 
		return $_sub; 
	}
	
	/**
	 * function is same as list_mailbox rather than it returns active mail box list
	 *
	 * @param string $delimiter
	 * @param string $ref_mail_box = ''
	 * @param string $wild_card = '*'
	 * @return array
	 */
	function &list_subscribed_mailbox(&$delimiter, $ref_mail_box = '', $wild_card = '*')
	{
		$_sub =& $this->_in_list_mailbox($delimiter, $ref_mail_box, $wild_card, true); 
		return $_sub; 
	}

	function InitCapa()
	{
		if (null === $this->_capas)
		{
			$resp = $this->get_capability();
			if ($resp)
			{
				$this->_parseCapability($resp);
			}
		}
	}

	/**
	 * @param string $_str
	 * @return bool
	 */
	function _isSupport($_str)
	{
		return is_array($this->_capas) ? in_array($_str, $this->_capas) : false;
	}

	/**
	 * @return bool
	 */
	function IsUidPlusSupport()
	{
		if (null === $this->_capas)
		{
			$this->InitCapa();
		}

		return $this->_isSupport('UIDPLUS');
	}

	/**
	 * @return bool
	 */
	function IsQuotaSupport()
	{
		if (null === $this->_capas)
		{
			$this->InitCapa();
		}

		return $this->_isSupport('QUOTA');
	}

	/**
	 * @param string $str
	 */
	function _parseCapability($str)
	{
		$this->_capas = array();
		$capasLineArray = explode("\n", $str);
		foreach ($capasLineArray as $capasLine)
		{
			$capa = strtoupper(trim($capasLine));
			if (substr($capa, 0, 12) == '* CAPABILITY')
			{
				$capa = substr($capa, 12);
				$cArray = explode(' ', $capa);

				foreach ($cArray as $c)
				{
					if (strlen($c) > 0)
					{
						$this->_capas[] = $c;
					}
				}
			}
		}
	}

	/**
	 * @return int | false
	 */
	function get_quota()
	{
		if ($this->IsQuotaSupport())
		{
			$this->UpdateTag();
			if ($this->put_line($this->tag.' GETQUOTAROOT "INBOX"'))
			{
				$response = $this->get_server_responce();
				if (!$this->_checkResponse($response))
				{
					return false;
				}

				if (preg_match('/STORAGE (\d+) (\d+)/i', $response, $match) && count($match) > 2)
				{
					return $match[2] * 1024;
				}
			}
		}

		return false;
	}
	
	/**
	 * @param string $response
	 * @return string
	 */
	function _checkResponse($response)
	{
		if (substr($response, strpos($response, $this->tag.' ') + strlen($this->tag) + 1, 2) != 'OK')
		{
			if (trim($response) == '')
			{ 
				$this->error = 'Error : Null response';
			}
			else 
			{
				$this->error = 'Error response: '.$response;
			}
			
			return false;
		}
		return true;
	}
	
	/**
	 * @param string $_state
	 * @return bool
	 */
	function _checkState_0($_state)
	{
		if ($this->state != $_state)
		{
			$this->error = $this->_getState_0_Error($_state);
			return false;
		}
		
		return true;
	}
	
	/**
	 * @param string $_state
	 * @return bool
	 */
	function _checkState_1($_state)
	{
		if ($this->state == $_state)
		{
			$this->error = $this->_getState_1_Error($_state);
			return false;
		}
		
		return true;
	}
	
	/**
	 * @param string $_state
	 * @return string
	 */
	function _getState_0_Error($_state)
	{
		switch ($_state)
		{
			default:				return 'Error : Unknown state.';
			case 'SELECTED':		return 'Error : No mail box is selected.';
			case 'DISCONNECTED':	return 'Error : Already Connected!';
			case 'AUTHORIZATION':	return 'Error : No Connection Found!';
		}
	}
	
	/**
	 * @param string $_state
	 * @return string
	 */
	function _getState_1_Error($_state)
	{
		switch ($_state)
		{
			default:				return 'Error : Unknown state.';
			case 'DISCONNECTED':	return 'Error : No Connection Found!';
			case 'AUTHENTICATED':	return 'Error : Already Authenticated!';
			case 'AUTHORIZATION':	return 'Error : User is not authorised or logged in!';
		}
	}

	/**
	 * @param string $_prefix = null
	 * @return string
	 */
	function GetTag($_prefix = null)
	{
		if (null === $_prefix)
		{
			$_prefix = 'ADM';
		}

		return $_prefix.rand(1000, 9999);
	}

	/**
	 * @param string $_prefix = null
	 */
	function UpdateTag($_prefix = null)
	{
		$this->tag = $this->GetTag($_prefix);
	}
}
Return current item: AfterLogic WebMail Lite PHP