<?php
/*======================================================================*\
|| #################################################################### ||
|| # ---------------------------------------------------------------- # ||
|| # Copyright ©2013 Fillip Hannisdal AKA Revan/NeoRevan/Belazor 	  # ||
|| # All Rights Reserved. 											  # ||
|| # This file may not be redistributed in whole or significant part. # ||
|| # ---------------------------------------------------------------- # ||
|| # You are not allowed to use this on your server unless the files  # ||
|| # you downloaded were done so with permission.					  # ||
|| # ---------------------------------------------------------------- # ||
|| #################################################################### ||
\*======================================================================*/

// #############################################################################
// vBMail POP3 functionality class

/**
* Handles everything to do with vBMail's connectivity to IMAP.
*/
class VBMAIL_IMAP
{
	/**
	* The vBulletin registry object
	*
	* @protected	vB_Registry
	*/	
	protected static $vbulletin 	= NULL;
	
	/**
	* The connection to the server
	*
	* @private		resource
	*/	
	private static $connection 		= NULL;
	
	
	
	/**
	* Does important checking before anything else should be going on
	*
	* @param	vB_Registry	Registry object
	*/
	public static function init($vbulletin)
	{
		// Check if the vBulletin Registry is an object
		if (!is_object($vbulletin))
		{
			// Something went wrong here I think
			trigger_error("Registry object is not an object", E_USER_ERROR);
		}
		
		// Set registry
		self::$vbulletin =& $vbulletin;
	}
	
	/**
	* (Re-)Opens a connection to the mail server
	*/
	public static function open()
	{
		global $vbphrase;
		
		if (self::$connection)
		{
			// Reopens the mailbox
			if (!imap_reopen(self::$connection, self::$vbulletin->options['dbtech_vbmail_imap_mailbox']))
			{
				// We couldn't reopen the mailbox
				trigger_error($vbphrase['dbtech_vbmail_cannot_reopen_mailbox'] . '<br />' . imap_last_error(), E_USER_ERROR);
			}
		}
		else
		{
			if (!self::$vbulletin->options['dbtech_vbmail_imap_host'] OR
				!self::$vbulletin->options['dbtech_vbmail_imap_port'] OR
				!self::$vbulletin->options['dbtech_vbmail_imap_mailbox'] OR
				!self::$vbulletin->options['dbtech_vbmail_imap_username'] OR
				!self::$vbulletin->options['dbtech_vbmail_imap_password']
			)
			{
				// We couldn't open the mailbox
				trigger_error($vbphrase['dbtech_vbmail_cannot_open_mailbox'] . '<br />' . imap_last_error(), E_USER_ERROR);
			}
			
			// Open the connection to the mailbox
			self::$connection = imap_open(
				'{' . self::$vbulletin->options['dbtech_vbmail_imap_host'] . ':' . self::$vbulletin->options['dbtech_vbmail_imap_port'] . '/novalidate-cert/imap' . 
					(self::$vbulletin->options['dbtech_vbmail_imap_ssl'] ? '/ssl/novalidate-cert' : '') . 
					(self::$vbulletin->options['dbtech_vbmail_imap_tls'] ? '/tls/novalidate-cert' : '') . 
				'}' . self::$vbulletin->options['dbtech_vbmail_imap_mailbox'],
				self::$vbulletin->options['dbtech_vbmail_imap_username'],
				self::$vbulletin->options['dbtech_vbmail_imap_password']
			);
			
			if (!self::$connection)
			{
				// We couldn't open the mailbox
				trigger_error($vbphrase['dbtech_vbmail_cannot_open_mailbox'] . '<br />' . imap_last_error(), E_USER_ERROR);
			}
		}
	}
	
	/**
	* Deletes a specific message from the opened mail server
	*
	* @param	integer	(Optional) Start index
	* @param	integer	(Optional) End index
	*/
	public static function listMessages($start = 1, $end = false)
	{
		// Check mailbox
		$MC = imap_check(self::$connection);
		
		if (!$end OR $end > $MC->Nmsgs)
		{
			// Set the new end range
			$end = $MC->Nmsgs;
		}
		
		// Grab the response
		$response = imap_fetch_overview(self::$connection, ($start ? $start : 1) . ':' . $end);
		
		$results = array();
		foreach ($response as $msg)
		{
			$bounce = '0';
			$matches = array();
			
			// Ensure we get the proper headers
			$headers 	= (array)imap_rfc822_parse_headers(imap_fetchheader(self::$connection, $msg->msgno));
			$from 		= (array)$headers['from'][0];
			
			// Fetch the body		
			$body = imap_body(self::$connection, $msg->msgno);	
			
			if (!preg_match("/X-vBMail-BouncedFrom\: (.*)\n/", $body, $matches))
			{
				if (preg_match("/Warning: message (.*) delayed/", $headers['subject']))
				{
					imap_delete(self::$connection, $msg->msgno);
					continue;
				}

				// Try an alternate match
				if (!preg_match('/^.*@.*$/m', $body, $matches) OR $from['mailbox'] != 'Mailer-Daemon')
				{
					$from = $from['mailbox'] . '@' . $from['host'];
					if (self::$vbulletin->options['dbtech_vbmail_bouncehandling'])
					{
						// Just delete the mail and continue
						imap_delete(self::$connection, $msg->msgno);
						continue;
					}
				}
				else
				{
					// Valid bounced email, go!
					$from = trim($matches[1]);
					
					// Flag as a valid bounce
					$bounce = '1';
				}
			}
			else
			{
				// Valid bounced email, go!
				$from = trim($matches[1]);
				
				// Reset matches
				$matches = array();
				
				// Grab the bouncekey header if it exists
				$result = preg_match("/X-vBMail-BounceKey\: (.*)\n/", $body, $matches);
				if (self::$vbulletin->options['dbtech_vbmail_bouncehandling'] AND (!$result OR trim($matches[1]) != md5(md5($from) . md5($from))))
				{
					// Just delete the mail and continue
					imap_delete(self::$connection, $msg->msgno);
					continue;
				}
				
				// Flag as a valid bounce
				$bounce = '1';
			}
			
			// Index message info by message number
			$results[$msg->uid] = array(
				'messageid' 	=> $msg->uid,
				'fromaddress' 	=> $from,
				'subject'		=> $msg->subject,
				'headers'		=> $headers,
				'body' 			=> trim($body),
				'dateline' 		=> strtotime($msg->date),
				'bounce' 		=> $bounce,
			);
		}
		
		return $results;
	}
	
	/**
	* Deletes a specific message from the opened mail server
	*
	* @param	integer	Message ID
	*/
	public static function delete($messageNumber)
	{
		return imap_delete(self::$connection, $messageNumber, FT_UID);
	}
	
	/**
	* Closes the connection, and cleans up any deleted messages
	*/
	public static function close()
	{
		// Close the mailbox and expunge the mailbox
		return imap_close(self::$connection, CL_EXPUNGE);
	}
}