I'm writing a php IMAP API. The constructor connects to them Gmail server and stores the socket in a variable. When I use the same socket connection in another method, the connection is null. Why does this happen and how can I fix it?
class Imap{
const RESPONSE_SIZE = 4096;
const LOCAL_HOST = '127.0.0.1';
const CRLF = "\r\n";
//------------RESPONSE CODES---------//
const OK = "OK";
const BAD = "BAD";
const NO = "NO";
//----------------FLAGS--------------//
const FLAG_ANSWERED = "\\Answered";
const FLAG_FLAGGED = "\\Flagged";
const FLAG_DRAFT = "\\Draft";
const FLAG_DELETED = "\\Deleted";
const FLAG_SEEN = "\\Seen";
//------------- PRIVATE VARS ------------//
private $_connection = NULL;
private $_number = 0;
private $_instruction_num;
private $_connected = false;
private $_authenticated = false;
//------------- PUBLIC VARS ------------//
public $error = array();
function __construct($imap_server, $imap_port)
{
$this->connect($imap_server,$imap_port);
}
function __destruct()
{
if($this->_connected)
$this->logout();
}
private function connect($imap_server, $imap_port)
{
if($this->_connected == false)
{
if($imap_server == NULL) $imap_server = self::LOCAL_HOST;
if($imap_port == NULL) $imap_port = 993;
$this->_connection = fsockopen($imap_server,$imap_port);
if(empty($this->_connection))
{
throw new Exception('Connection to server could not be established');
}
else $this->_connected = true;
}
return $this->_connected;
}
function login($username, $password)
{
echo 'connection: '.$this->_connected;
if(!$this->_authenticated)
{
$instruction = $this->get_instruction_num();
fputs($this->_connection,"$instruction LOGIN $username $password".self::CRLF);
$response = $this->get_response($instruction);
switch ($response['code']) {
case self::OK:
$this->_authenticated = true;
break;
case self::NO:
$this->_authenticated = false;
$this->error = array('error'=>'Invalid username or password.');
break;
case self::BAD:
default:
$this->_authenticated = false;
$this->error = array('error'=>$response['response']);
break;
}
}
return $this->_authenticated;
}
private function get_response($aInstructionNumber)
{
$end_of_response = false;
if(empty($this->_connection))
die('DEAD');//connection is null here.
while (!$end_of_response)
{
$line = fgets($this->_connection,self::RESPONSE_SIZE);
$response .= $line.'<br/>';
if(preg_match("/$aInstructionNumber (OK|NO|BAD)/", $response,$responseCode))
$end_of_response = true;
}
return array('code' => $responseCode[1],
'response'=>$response);
}
Used in Mailer.php
class Mailer
{
const imap_server = "ssl://imap.gmail.com";
const imap_port = 993;
const smtp_server = "ssl://smtp.gmail.com";
const smtp_port = 465;
private $imap = NULL;
private $smtp = NULL;
private $username = "";
private $password = "";
private $logged_in = false;
function __construct()
{
try{
$this->imap = new Imap(self::imap_server,self::imap_port);
$this->smtp = new Smtp(self::smtp_server,self::smtp_port);
}catch(Exception $e)
{
throw new Exception($e->getMessage());
}
}
function login($username,$password)
{
if($username != NULL) $this->username = $username;
if($password != NULL) $this->password = $password;
//$this->imap = new Imap(self::imap_server,self::imap_port);
if(!$this->imap->login($this->username,$this->password))
{
$result = array('success'=>0,'message'=>$this->imap->error());
}
else
{
$this->logged_in = true;
$result = array('success'=>1,'message'=>'Login successful');
}
return $result;
}
The code in the logging in page:
if(!isset($_SESSION['mailer']))
{
try{
$mailer = new Mailer();
}catch(Exception $e){
die($e->getMessage());
}
$_SESSION['mailer'] = serialize($mailer);
}
if(isset($_POST['username']) && isset($_POST['password']))
{
//ENCRYPT
$username = htmlentities($_POST['username']);
$password = htmlentities($_POST['password']);
$s_mailer = $_SESSION['mailer'];
$mailer = unserialize($s_mailer);
$_login = $mailer->login($username,$password);
if($_login['success']!=1)
{
$feedback = $_login['message'];
}else
header('Location: inbox.php');
}
You are storing the Mailer class in SESSION and expecting that the connection keeps alive across several requests. Note that this will not work.
Instead you could store the serialized Mailer object in the SESSION and implement __sleep and __wakeup to establish the connection again on unserialize.