Location: PHPKode > scripts > AfterLogic WebMail Lite PHP > afterlogic-webmail-lite-php/webmail/common/class_imapstorage.php
<?php

/*
 * AfterLogic WebMail Pro PHP by AfterLogic Corp. <hide@address.com>
 *
 * Copyright (C) 2002-2010  AfterLogic Corp. (www.afterlogic.com)
 * Distributed under the terms of the license described in COPYING
 * 
 */

defined('WM_ROOTPATH') || define('WM_ROOTPATH', (dirname(__FILE__) . '/'));

require_once (WM_ROOTPATH . 'libs/class_imap.php');
require_once (WM_ROOTPATH . 'common/class_webmailmessages.php');
require_once (WM_ROOTPATH . 'common/class_folders.php');
require_once (WM_ROOTPATH . 'common/class_mailstorage.php');
require_once (WM_ROOTPATH . 'common/class_bodystructure.php');

class ImapStorage extends MailServerStorage
{
	/**
	 * @access private
	 * @var IMAPMAIL
	 */
	var $_imapMail;

	/**
	 * @param Account $account
	 * @return ImapStorage
	 */
	function ImapStorage(&$account, &$mp)
	{
		$this->mailproc =& $mp;
		MailServerStorage::MailServerStorage($account);
		$this->_imapMail = new IMAPMAIL();
		$this->_imapMail->host = $account->MailIncHost;
		$this->_imapMail->port = $account->MailIncPort;
		$this->_imapMail->user = $account->MailIncLogin;
		$this->_imapMail->password = $account->MailIncPassword;
	}

	/**
	 * @param $arg[optional] = false
	 * @return bool
	 */
	function Connect()
	{
		if($this->_imapMail->connection != false)
		{
			return true;
		}
		
		@register_shutdown_function(array(&$this, 'Disconnect'));
		if (!$this->_imapMail->open())
		{
			setGlobalError(ErrorIMAP4Connect);
			return false;
		}
		
		if (!$this->_imapMail->login($this->Account->MailIncLogin, $this->Account->MailIncPassword))
		{
			setGlobalError(ErrorPOP3IMAP4Auth);
			return false;				
		}

		return true;
	}

	/**
	 * @return bool
	 */
	function Disconnect()
	{
		if ($this->_imapMail->connection == false)
		{
			return true;
		}
		return $this->_imapMail->close();
	}

	/**
	 * @param Array $messageIndexSet
	 * @param bool $indexAsUid
	 * @param Folder $folder
	 * @return WebMailMessageCollection
	 */
	function LoadMessages(&$messageIndexSet, $indexAsUid, &$folder, $imapUids = null, $imapUidFlags = null, $imapUidSizes = null)
	{
		$messageCollection = null;
		if ($this->_imapMail->open_mailbox($folder->FullName, false))
		{
			$_imapUids = array();
			$_imapUidFlags = array();
			$_imapUidSizes = array();
				
			if ($imapUids == null)
			{
				//Get uid, flags and size from imap Server
				$paramsMessages = $this->_imapMail->getParamsMessages();
				if (!is_array($paramsMessages))
				{
					return $messageCollection;
				}
				
				foreach($paramsMessages as $key => $value)
				{
					$_imapUids[$key] = $value["uid"];
					$_imapUidFlags[$value["uid"]] = $value["flag"];
					$_imapUidSizes[$value["uid"]] = $value["size"];
				}
			}
			
			$messageCollection = new WebMailMessageCollection();
			foreach($messageIndexSet as $idx)
			{
				$response = $this->_imapMail->get_message($idx, $indexAsUid);
				if ($response)
				{
					$msg = new WebMailMessage();
					$msg->LoadMessageFromRawBody($response, true);
					if($indexAsUid)
					{
						$msg->Uid = $idx;
					} 
					else
					{
						if ($imapUids == null) 
						{
							$imapUids = $_imapUids;
						}
						$msg->Uid = $imapUids[$idx];
					}
					
					if ($imapUidSizes == null)
					{
						$imapUidSizes = $_imapUidSizes;
					}
									
					$msg->Size = $imapUidSizes[$msg->Uid];
					
					if ($imapUidFlags == null)
					{
						$imapUidFlags = $_imapUidSizes;
					}
					
					$this->_setMessageFlags($msg, $imapUidFlags[$idx]);
					$messageCollection->Add($msg);
					unset($msg);
				}
			}
			if ($messageCollection->Count() > 0)
			{
				return $messageCollection;
			}
		}
		return $messageCollection;
	}

	function GetBodyPartByIndex($bsIndex, $messageUid, $folder)
	{
		$out = '';
		if ($this->_imapMail->open_mailbox($folder->FullName, false))
		{
			$out = $this->_imapMail->getBodyPartByIndex($bsIndex, $messageUid);
		}
		return $out;
	}
	
	/**
	 * @param string $messageUid
	 * @param bool $indexAsUid
	 * @param Folder $folder
	 * @return WebMailMessage
	 */
	function LoadMessage($messageUid, $indexAsUid, &$folder, $mode = null)
	{
		$msg = null;
		if ($indexAsUid && $this->_imapMail->open_mailbox($folder->FullName, false))
		{
			if (null !== $mode)
			{
				$bodyStructureObject = $this->_imapMail->getMessageBodyStructure($messageUid);
				if ($bodyStructureObject && $bodyStructureObject->GetSize() > BODYSTRUCTURE_MGSSIZE_LIMIT)
				{
					$this->_imapMail->FillBodyStructureByMode($messageUid, $mode, $bodyStructureObject);

					$msg = new WebMailMessage();
					$msg->FillByBodyStructure($bodyStructureObject, $this->Account->GetDefaultIncCharset());
					$msg->Uid = $messageUid;
					$msg->Size = $bodyStructureObject->GetSize();
					$this->_setMessageFlags($msg, $bodyStructureObject->GetFlags());
				}
			}

			if (null === $msg)
			{
				$responseArray = $this->_imapMail->getMessageWithFlag($messageUid);
				if ($responseArray && count($responseArray) == 2)
				{
					$msg = new WebMailMessage();
					$msg->LoadMessageFromRawBody($responseArray[0], true);
					$msg->Uid = $messageUid;
					$msg->Size = strlen($responseArray[0]);
					$this->_setMessageFlags($msg, $responseArray[1]);
				}
				else
				{
					setGlobalError(PROC_MSG_HAS_DELETED);
				}
			}
		}
		return $msg;
	}

	/**
	 * @param int $pageNumber
	 * @param Folder $folder
	 * @param string $condition
	 * @param bool $inHeadersOnly
	 * @return WebMailMessageCollection
	 */
	function &DmImapSearchMessages($pageNumber, &$folder, $condition, $inHeadersOnly, &$refMsgCount)
	{
		$webMailMessageCollection = $paramsMessages = null;
		if ($this->_imapMail->open_mailbox($folder->FullName, false))
		{
			$searchRequest = 'OR (OR FROM "'.$condition.'" TO "'.$condition.'") SUBJECT "'.$condition.'"';
			if (!$inHeadersOnly)
			{
				$searchRequest = 'OR ('.$searchRequest.') BODY "'.$condition.'"';
			}
			
                        $isSortSupport = $this->_imapMail->IsSortSupport();

                        if ($isSortSupport)
                        {
                                $order_by = $this->GetOrderByForImapSort();
                        }
                        else
                        {
                                $order_by = null;
                        }

                        $searchMessagesIndexsValues = $this->_imapMail->search_mailbox($searchRequest, 'UTF-8', $order_by);

			$msgCount = count($searchMessagesIndexsValues);
			if ($searchMessagesIndexsValues == false || $msgCount == 0)
			{
				$newcoll = new WebMailMessageCollection();
				return $newcoll;
			}

			$pages = ceil($msgCount / $this->Account->MailsPerPage);

			if ($pageNumber > $pages)
			{
				$pageNumber = 1;
			}
			
			$refMsgCount = $msgCount;

			$messageIndexSet = array();
			$start = ($pageNumber - 1) * $this->Account->MailsPerPage;
			$messageIndexSet = array_slice($searchMessagesIndexsValues, $start, $this->Account->MailsPerPage);
			$webMailMessageCollection =& $this->LoadMessageHeadersInOneRequest($folder, $messageIndexSet);
		}
		
		return $webMailMessageCollection;
	}

	/**
	 * @param Folder $folder
	 * @param string $condition
	 * @return array|false
	 */
	function HeadersBodyImapSearchMessagesUids($folder, $condition)
	{
		$uids = false;
		if ($this->_imapMail->open_mailbox($folder->FullName, false))
		{
			$searchRequest = 'OR (OR FROM "'.$condition.'" TO "'.$condition.'") SUBJECT "'.$condition.'"';
			$searchRequest = 'OR ('.$searchRequest.') BODY "'.$condition.'"';

                        $isSortSupport = $this->_imapMail->IsSortSupport();

                        if ($isSortSupport)
                        {
                                $order_by = $this->GetOrderByForImapSort();
                        }
                        else
                        {
                                $order_by = null;
                        }

                        $uids = $this->_imapMail->uid_search_mailbox($searchRequest, 'UTF-8', $order_by);
		}
		return $uids;
	}

	/**
	 * @param int $pageNumber
	 * @param Folder $folder
	 * @return WebMailMessageCollection
	 */
	function &LoadMessageHeaders($pageNumber, &$folder)
	{
		$webMailMessageCollection = null;
		if ($this->_imapMail->open_mailbox($folder->FullName, false))
		{
			if ($folder->SyncType == FOLDERSYNC_DirectMode)
			{
				if ($folder->MessageCount < 1)
				{
					$newcoll = new WebMailMessageCollection();
					return $newcoll;
				}

				$msgCount = $folder->MessageCount;
				$messageIndexSet = array();

				$isSortSupport = $this->_imapMail->IsSortSupport();

				if ($isSortSupport)
				{
					$order_by = $this->GetOrderByForImapSort();
					$messageSortedIndexSet = array();
					$messageSortedIndexSet = $this->_imapMail->search_mailbox('', 'UTF-8', $order_by);
					$msgCount = count($messageSortedIndexSet);
				}
                                
				for ($i = $msgCount - ($pageNumber - 1) * $this->Account->MailsPerPage,
						$t = $msgCount - $pageNumber * $this->Account->MailsPerPage; $i > $t; $i--)
				{
					if ($isSortSupport)
					{
						if ($i < 1) break;
						$messageIndexSet[] = $messageSortedIndexSet[$i - 1];
					}
					else
					{
						if ($i == 0) break;
						$messageIndexSet[] = $i;
					}
				}

				$webMailMessageCollection =& $this->LoadMessageHeadersInOneRequest($folder, $messageIndexSet);
			}
			else
			{
				$paramsMessages = $this->_imapMail->getParamsMessages();
				$imapFlags = array();
				$imapUids = array();
				$imapSizes = array();
				if (!is_array($paramsMessages))
				{
					return $webMailMessageCollection;
				}

				foreach($paramsMessages as $key => $value)
				{
					$imapFlags[$key] = $value["flag"];
					$imapUids[$key] = $value["uid"];
					$imapSizes[$key] = $value["size"];
				}

				if(count($paramsMessages) < 1)
				{
					$newcoll = new WebMailMessageCollection();
					return $newcoll;
				}

				$msgCount = count($imapUids);
				$messageIndexSet = array();
				//$imapNFlags = $imapNSizes = array();
				for($i = $msgCount - ($pageNumber - 1) * $this->Account->MailsPerPage; 
					$i > $msgCount - $pageNumber * $this->Account->MailsPerPage; $i--)
				{
					if ($i == 0) break;
					$messageIndexSet[] = $imapUids[$i];
					//$imapNFlags[$imapUids[$i]] = $imapFlags[$i];
					//$imapNSizes[$imapUids[$i]] = $imapSizes[$i];
				}
				$webMailMessageCollection =& $this->LoadMessageHeadersInOneRequest($folder, $messageIndexSet, true);
			}
		}
		return $webMailMessageCollection;
	}

	/**
	 * @param FolderCollection $folders
	 * @return bool
	 */
	function SynchronizeFolder(&$folder)
	{
		$dbStorage = &DbStorageCreator::CreateDatabaseStorage($this->Account);
		if ($dbStorage->Connect())
		{
			return $this->_synchronizeFolderWithOpenDbConnection($folder, $dbStorage);
		}
		return false;
	}

	/**
	 * @param FolderCollection $folders
	 * @return bool
	 */
	function Synchronize(&$folders)
	{
		$result = true;
		$dbStorage =& DbStorageCreator::CreateDatabaseStorage($this->Account);
		if ($dbStorage->Connect())
		{
			$folderList = $folders->CreateFolderListFromTree(); //copy tree object here
			for ($i = 0, $icount = $folderList->Count(); $i < $icount; $i++)
			{
				$folder =& $folderList->Get($i);
				$result &= $this->_synchronizeFolderWithOpenDbConnection($folder, $dbStorage);
				unset($folder);
				
				if (!$result)
				{
					break;
				}
			}
			return $result;
		}
		return false;
	}

	/**
	 * @return bool
	 */
	function SynchronizeFolders()
	{
		$result = true;
		if (!USE_DB)
		{
			return $result;
		}
			
		$dbStorage =& DbStorageCreator::CreateDatabaseStorage($this->Account);
		$serverFoldersTree =& $this->GetFolders();
		if ($serverFoldersTree && $dbStorage->Connect())
		{
			$dbFoldersTree =& $dbStorage->GetFolders();
			$serverFoldersList =& $serverFoldersTree->CreateFolderListFromTree();
			$dbFoldersList =& $dbFoldersTree->CreateFolderListFromTree();
			$delimiter = $this->Account->Delimiter;
			$serverFoldersListKeys = array_keys($serverFoldersList->Instance());
			foreach ($serverFoldersListKeys as $mkey)
			{
				$mailFolder =& $serverFoldersList->Get($mkey);
				$folderExist = false;
				$dbFoldersListKeys = array_keys($dbFoldersList->Instance());
				foreach ($dbFoldersListKeys as $skey)
				{
					$dbFolder =& $dbFoldersList->Get($skey);
					if (trim($mailFolder->FullName, $delimiter) == trim($dbFolder->FullName, $delimiter))
					{
						$folderExist = true;
						if ($mailFolder->SubFolders)
						{
							foreach(array_keys($mailFolder->SubFolders->Instance()) as $subkey)
							{
								$subFld =& $mailFolder->SubFolders->Get($subkey);
								$subFld->IdParent = $dbFolder->IdDb;
							}
						}
						
						if ($dbFolder->Hide != $mailFolder->Hide && $dbFolder->SyncType != FOLDERSYNC_DontSync)
						{
							$dbFolder->Hide = $mailFolder->Hide;
							$dbStorage->UpdateFolder($dbFolder);
						}
						
						break;
					}
					unset($dbFolder);
				}

				if (!$folderExist && $mailFolder)
				{
					$mailFolder->SyncType = $this->Account->GetDefaultFolderSync($this->_settings);
					$result &= $dbStorage->CreateFolder($mailFolder);
				}
			}

			$dbFoldersListKeys = array_keys($dbFoldersList->Instance());
			foreach ($dbFoldersListKeys as $skey)
			{
				$dbFolder =& $dbFoldersList->Get($skey);
				$folderExist = false;
				$serverFoldersListKeys = array_keys($serverFoldersList->Instance());
				foreach ($serverFoldersListKeys as $mkey)
				{
					$mailFolder =& $serverFoldersList->Get($mkey);
					if (trim($mailFolder->FullName, $delimiter) == trim($dbFolder->FullName, $delimiter))
					{
						$folderExist = true;
						break;
					}
					unset($mailFolder);
				}
				
				if (!$folderExist && $dbFolder->SyncType != FOLDERSYNC_DontSync)
				{
					if ($dbFolder->SyncType == FOLDERSYNC_DirectMode && $dbFolder->MessageCount == 0)
					{
						$dbStorage->DeleteFolder($dbFolder);
					}
					else
					{
						$dbFolder->SyncType = FOLDERSYNC_DontSync;
						$dbStorage->UpdateFolder($dbFolder);
					}
				}
			}
		}
		return $result;
	}
	
	/**
	 * @param array $paramsMessages
	 * @param array $imapUids
	 * @param array $imapSizes
	 * @param array $imapUidFlags
	 * @param array $imapUidSizes
	 */
	function _imapArrayForeach(&$paramsMessages, &$imapUids, &$imapSizes, &$imapUidFlags, &$imapUidSizes)
	{
		foreach ($paramsMessages as $key => $value)
		{
			$imapUids[$key] = $value["uid"];
			$imapSizes[$key] = $value["size"];
			$imapUidFlags[$value["uid"]] = $value["flag"];
			$imapUidSizes[$value["uid"]] = $value["size"];
		}
	}

	/**
	 * @param Folder $folders
	 * @param DbStorage $dbStorage
	 * @param int $lastIdMsg
	 * @return bool
	 */
	function _synchronizeFolderWithOpenDbConnection(&$folder, &$dbStorage)
	{
		$log =& CLog::CreateInstance();
		$result = true;
		if ($folder->SyncType == FOLDERSYNC_DontSync || $folder->SyncType == FOLDERSYNC_DirectMode || $folder->Hide)
		{
			if ($this->UpdateFolderHandler != null && $folder->SyncType == FOLDERSYNC_DirectMode)
			{
				call_user_func_array($this->UpdateFolderHandler, array($folder->IdDb, $folder->FullName));
			}
			return true;
		}

		$foldername = '';
		if ($this->DownloadedMessagesHandler != null)
		{
			$foldername = $folder->GetFolderName($this->Account);
			call_user_func_array($this->DownloadedMessagesHandler, array($foldername, 0));
		}
		
		if (!$this->_imapMail->open_mailbox($folder->FullName, false, true))
		{
			return true;
		}
		
		$_isAllUpdate = ($folder->SyncType == FOLDERSYNC_AllHeadersOnly || $folder->SyncType == FOLDERSYNC_AllEntireMessages);
		$_isUidsOnly = ($folder->SyncType == FOLDERSYNC_NewHeadersOnly); 
		
		/* get uid, flags and size from IMAP4 Server */
		if ($log->Enabled)
		{
			$start = getmicrotime();
		}
		
		// if (!$_isUidsOnly)
		if (true)
		{
			$paramsMessages = $this->_imapMail->getParamsMessages();
			if ($log->Enabled)
			{
				$log->WriteLine('IMAP4: getParamsMessages()='.(getmicrotime() - $start));
			}
			
			if (!is_array($paramsMessages))
			{
				return false;
			}
			
			$imapUids = $imapSizes = $imapUidFlags = $imapUidSizes = array();
			$this->_imapArrayForeach($paramsMessages, $imapUids, $imapSizes, $imapUidFlags, $imapUidSizes);
			unset($paramsMessages);
		}
		else
		{
			$imapUids = $this->_imapMail->getFastUids();
			if ($log->Enabled)
			{
				$log->WriteLine('IMAP4: getFastUids()='.(getmicrotime() - $start));
			}
			
			if (!is_array($imapUids))
			{
				return false;
			}
		}

		$dbUidsIdMsgsFlags =& $dbStorage->SelectIdMsgAndUidByIdMsgDesc($folder);
		
		$dbUids = $dbUidsFlag = array();
		foreach ($dbUidsIdMsgsFlags as $value)
		{
			$dbUids[] = $value[1];
			$dbUidsFlag[$value[1]] = $value[2];
		}
		unset($dbUidsIdMsgsFlags);
		
		/* array need added to DB */
		//$newUids = array_diff($imapUids, $dbUids);
		$newUids = array();
		foreach ($imapUids as $_imUid) 
		{
			if (!isset($dbUidsFlag[$_imUid]))
			{
				$newUids[] = $_imUid;
			}
		}
		
		if ($this->DownloadedMessagesHandler != null && count($newUids) > 0)
		{
			call_user_func_array($this->DownloadedMessagesHandler, array($foldername, count($newUids)));
		}
		
		
		if ($_isAllUpdate)
		{
			
			/* update flags */
			
			$_flags4Update = array();
			/* intersect uids */
			foreach ($imapUids as $_imUid) 
			{
				if (isset($dbUidsFlag[$_imUid]))
				{
					$flagBD = (int) $dbUidsFlag[$_imUid];
					$flagImap = (int) $this->getIntFlags($imapUidFlags[$_imUid]);
					/* update messages whith different flags */
					if ($flagBD != $flagImap)
					{
						$_flags4Update[$flagImap][] = $_imUid;
					}
				}
			}

			if (count($_flags4Update) > 0)
			{
				foreach ($_flags4Update as $_flag => $_uidArray)
				{
					if (is_array($_uidArray))
					{
						$dbStorage->UpdateMessageFlags($_uidArray, true, $folder, $_flag, $this->Account);
					}
				}
				if ($this->UpdateFolderHandler != null)
				{
					call_user_func_array($this->UpdateFolderHandler, array($folder->IdDb, $folder->FullName));
				}
			}
		
			/* delete from DB */
			
			//$uidsToDelete = array_diff($dbUids, $imapUids);
			$uidsToDelete = array();
			foreach ($dbUids as $_dbUid) 
			{
				if (!isset($imapUidFlags[$_dbUid]))
				{
					//$dbUidsFlag[$_dbUid] = $value[2];
					$uidsToDelete[] = $_dbUid;
				}
			}				
			if (count($uidsToDelete) > 0)
			{
				if ($this->UpdateFolderHandler != null)
				{
					call_user_func_array($this->UpdateFolderHandler, array($folder->IdDb, $folder->FullName));
				}

				// $result &= $dbStorage->SetMessagesFlags($uidsToDelete, true, $folder, MESSAGEFLAGS_Deleted, ACTION_Set);
				$result &= $dbStorage->DeleteMessages($uidsToDelete, true, $folder);
				$result &= $dbStorage->UpdateMailboxSize();
			}
		}
		
		$maxEnvelopesPerSession = 1;
		
		/* get size all messages in DB */
		$mailBoxesSize = $dbStorage->SelectMailboxesSize();
		
		$filters =& $dbStorage->SelectFilters($this->Account->Id, true);

		if ($folder->SyncType == FOLDERSYNC_NewHeadersOnly || $folder->SyncType == FOLDERSYNC_AllHeadersOnly)
		{
			$syncCycles = ceil(count($newUids) / MAX_ENVELOPES_PER_SESSION);
			for ($q = 0; $q < $syncCycles; $q++)
			{
				$cyclesNewUids = array_slice($newUids, $q * MAX_ENVELOPES_PER_SESSION, MAX_ENVELOPES_PER_SESSION);

				$mailMessageCollection = null;
				$mailMessageCollection =& $this->LoadMessageHeadersInOneRequest($folder, $cyclesNewUids, true);

				if ($mailMessageCollection)
				{
					for ($i = 0, $c = $mailMessageCollection->Count(); $i < $c; $i++)
					{
						if ($this->DownloadedMessagesHandler != null && function_exists($this->DownloadedMessagesHandler))
						{
							call_user_func($this->DownloadedMessagesHandler);
						}

						$message =& $mailMessageCollection->Get($i);

						$mailBoxesSize += $message->Size;

						if ($this->_settings->EnableMailboxSizeLimit && $this->Account->MailboxLimit > 0 && $this->Account->MailboxLimit < $mailBoxesSize)
						{
							$result = false;
							setGlobalError(ErrorGetMailLimit);
							break 2;
						}

						if (!$this->ApplyFilters($message, $dbStorage, $folder, $filters))
						{
							$result = false;
						}
					}
				}
			}
		}
		else
		{
			$syncCycles = ceil(count($newUids) / $maxEnvelopesPerSession);
			for ($i = 0; $i < $syncCycles; $i++)
			{
				$mailBoxesSize += $imapSizes[$i + 1];

				if ($this->_settings->EnableMailboxSizeLimit && $this->Account->MailboxLimit > 0 && $this->Account->MailboxLimit < $mailBoxesSize)
				{
					$result = false;
					setGlobalError(ErrorGetMailLimit);
					break;
				}

				$listPartToDownload = ($i != $syncCycles - 1) ? array_slice($newUids, $i * $maxEnvelopesPerSession, $maxEnvelopesPerSession) : array_slice($newUids, $i * $maxEnvelopesPerSession);

				if ($this->DownloadedMessagesHandler != null && function_exists($this->DownloadedMessagesHandler))
				{
					call_user_func($this->DownloadedMessagesHandler);
				}

				$mailMessageCollection = null;
				$mailMessageCollection =& $this->LoadMessages($listPartToDownload, true, $folder, $imapUids, $imapUidFlags, $imapUidSizes);

				if ($mailMessageCollection && $mailMessageCollection->Count() > 0)
				{
					$message =& $mailMessageCollection->Get(0);
					if (!$this->ApplyFilters($message, $dbStorage, $folder, $filters))
					{
						$result = false;
						break;
					}
				}
			}
		}
		
		$result &= $dbStorage->UpdateMailboxSize();
		return $result;
	}

	/**
	 * @param array $messageIdUidSet
	 * @param Folder $fromFolder
	 * @return bool
	 */
	function SpamMessages($messageIdUidSet, $fromFolder, $isSpam = true)
	{
		if (false && $this->Account && $this->Account->IsInternal) // !!! off
		{
			$messageUids = array_values($messageIdUidSet);

			$toFolder = ($isSpam)
				? new Folder($this->Account->Id, -1, FOLDERFULLNAME_SharedSpam, FOLDERNAME_SharedSpam, FOLDERSYNC_AllHeadersOnly)
				: new Folder($this->Account->Id, -1, FOLDERFULLNAME_SharedUnSpam, FOLDERNAME_SharedUnSpam, FOLDERSYNC_AllHeadersOnly);

			return $this->SetEximSpamMessages($messageUids, $fromFolder, $toFolder);
		}
		
		return true;
	}

	/**
	 * @param array $indexs
	 * @param bool $indexsAsUid = false
	 * @return WebMailMessageCollection | null
	 */
	function &LoadMessageHeadersInOneRequest_Old($folder, $indexs, $indexsAsUid = false, $imapFlags = null, $imapSizes = null)
	{
		$messageCollection = null;
		$indexsStr = trim(implode(',', $indexs));
		$preText = ' ';
		if (null === $imapFlags)
		{
			$preText .= 'FLAGS ';
		}
		if (null === $imapSizes)
		{
			$preText .= 'RFC822.SIZE ';
		}

		$rString = 'FETCH '.$indexsStr.' (UID'.$preText.'BODY.PEEK[HEADER])';
//		$rString = 'FETCH '.$indexsStr.' (UID'.$preText.'BODY.PEEK[HEADER.FIELDS (RETURN-PATH RECEIVED MIME-VERSION FROM TO CC DATE SUBJECT X-MSMAIL-PRIORITY IMPORTANCE X-PRIORITY CONTENT-TYPE)])';
		if ($indexsAsUid)
		{
			$rString = 'UID '.$rString;
		}

		$responseArray = $this->_imapMail->getResponseAsArray($rString);
		if (is_array($responseArray))
		{
			$messageCollection = new WebMailMessageCollection();
			$headersString = implode('', $responseArray);

			$pieces = preg_split('/\* [\d]+ FETCH /', $headersString);
			foreach ($pieces as $key => $text)
			{
				$uid = $size = $flags = null;
				$lines = explode("\n", trim($text));
				$firstline = array_shift($lines);
				$lastline = array_pop($lines);
				$matchUid = $matchSize = $matchFlags = array();

				preg_match('/UID (\d+)/', $firstline, $matchUid);
				if (isset($matchUid[1]))
				{
					$uid = (int) $matchUid[1];
				}

				if (null === $imapFlags)
				{
					preg_match('/FLAGS \(([^\)]*)\)/', $firstline, $matchFlags);
					if (isset($matchFlags[1]))
					{
						$flags = trim(trim($matchFlags[1]), '()');
					}
				}
				else if (isset($imapFlags[$uid]))
				{
					$flags = $imapFlags[$uid];
				}

				if (null === $imapSizes)
				{
					preg_match('/RFC822\.SIZE ([\d]+)/', $firstline, $matchSize);
					if (isset($matchSize[1]))
					{
						$size = (int) $matchSize[1];
					}
				}
				else if (isset($imapSizes[$uid]))
				{
					$size = (int) $imapSizes[$uid];
				}

				if (null === $uid)
				{
					$match = array();
					preg_match('/UID (\d+)/', $lastline, $match);
					if (isset($match[1]))
					{
						$uid = (int) $match[1];
					}
				}

				$text = implode("\n", $lines);
				$pieces[$key] = array($uid, trim($text), $size, $flags);
			}

			if (!$this->_imapMail->IsSortSupport())
			{
				arsort($pieces);
			}

			foreach ($pieces as $headerArray)
			{
				if (is_array($headerArray) && count($headerArray) == 4 && $headerArray[0] > 0 && strlen($headerArray[1]) > 10)
				{
					$msg = new WebMailMessage();
					$msg->LoadMessageFromRawBody($headerArray[1]);
					$msg->IdFolder = $folder->IdDb;
					$msg->IdMsg = $headerArray[0];
					$msg->Uid = $headerArray[0];
					$msg->Size = (int) $headerArray[2];
					$this->_setMessageFlags($msg, $headerArray[3]);
					$messageCollection->Add($msg);
					unset($msg);
				}
			}
		}

		return $messageCollection;
	}

	/**
	 * @param array $indexs
	 * @param bool $indexsAsUid = false
	 * @return WebMailMessageCollection | null
	 */
	function &LoadMessageHeadersInOneRequest($folder, $indexs, $indexsAsUid = false, $imapFlags = null, $imapSizes = null)
	{
		$messageCollection = null;
		$indexsStr = trim(implode(',', $indexs));
		$preText = ' ';
		if (null === $imapFlags)
		{
			$preText .= 'FLAGS ';
		}
		if (null === $imapSizes)
		{
			$preText .= 'RFC822.SIZE ';
		}

		$rString = 'FETCH '.$indexsStr.' (UID'.$preText.'BODY.PEEK[HEADER])';
//		$rString = 'FETCH '.$indexsStr.' (UID'.$preText.'BODY.PEEK[HEADER.FIELDS (RETURN-PATH RECEIVED MIME-VERSION FROM TO CC DATE SUBJECT X-MSMAIL-PRIORITY IMPORTANCE X-PRIORITY CONTENT-TYPE)])';
		if ($indexsAsUid)
		{
			$rString = 'UID '.$rString;
		}

		$responseArray = $this->_imapMail->getResponseAsArray($rString);
		if (is_array($responseArray))
		{
			$messageCollection = new WebMailMessageCollection();
			$headersString = implode('', $responseArray);
			unset($responseArray);

			$piecesOut = array();
			$pieces = preg_split('/\* [\d]+ FETCH /', $headersString);

			$tmpArray = array();
			preg_match_all('/\* ([\d]+) FETCH /', $headersString, $tmpArray);
			$piecesFetchId = (isset($tmpArray[1])) ? $tmpArray[1] : array();
			unset($tmpArray, $headersString);
			
			foreach ($pieces as $key => $text)
			{
				if (isset($piecesFetchId[$key - 1]))
				{
					$index = $piecesFetchId[$key - 1];
					$uid = $size = $flags = null;
					$lines = explode("\n", trim($text));
					$firstline = array_shift($lines);
					$lastline = array_pop($lines);
					$matchUid = $matchSize = $matchFlags = array();

					preg_match('/UID (\d+)/', $firstline, $matchUid);
					if (isset($matchUid[1]))
					{
						$uid = (int) $matchUid[1];
					}

					if (null === $imapFlags)
					{
						preg_match('/FLAGS \(([^\)]*)\)/', $firstline, $matchFlags);
						if (isset($matchFlags[1]))
						{
							$flags = trim(trim($matchFlags[1]), '()');
						}
					}
					else if (isset($imapFlags[$uid]))
					{
						$flags = $imapFlags[$uid];
					}

					if (null === $imapSizes)
					{
						preg_match('/RFC822\.SIZE ([\d]+)/', $firstline, $matchSize);
						if (isset($matchSize[1]))
						{
							$size = (int) $matchSize[1];
						}
					}
					else if (isset($imapSizes[$uid]))
					{
						$size = (int) $imapSizes[$uid];
					}

					if (null === $uid)
					{
						$match = array();
						preg_match('/UID (\d+)/', $lastline, $match);
						if (isset($match[1]))
						{
							$uid = (int) $match[1];
						}
					}

					$piecesOut[($indexsAsUid) ? $uid : $index] = array($uid, trim(implode("\n", $lines)), $size, $flags);
				}
			}

			unset($pieces);

			foreach ($indexs as $value)
			{
				if (isset($piecesOut[$value]))
				{
					$headerArray = $piecesOut[$value];
					if (is_array($headerArray) && count($headerArray) == 4 && $headerArray[0] > 0 && strlen($headerArray[1]) > 10)
					{
						$msg = new WebMailMessage();
						$msg->LoadMessageFromRawBody($headerArray[1]);
						$msg->IdFolder = $folder->IdDb;
						$msg->IdMsg = $headerArray[0];
						$msg->Uid = $headerArray[0];
						$msg->Size = (int) $headerArray[2];
						$this->_setMessageFlags($msg, $headerArray[3]);
						$messageCollection->Add($msg);
						unset($msg);
					}
				}
			}
		}

		return $messageCollection;
	}

	/**
	 * @return FolderCollection
	 */
	function GetFolders()
	{
		ConvertUtils::SetLimits();

		$lastD = $this->Account->Delimiter;
		$folderCollection = new FolderCollection();
		$folders =& $this->_imapMail->list_mailbox($this->Account->Delimiter);
		$eximSharedFolders = isset($GLOBALS['EXIM_SHARED_SPAM_FOLDERS']) && is_array($GLOBALS['EXIM_SHARED_SPAM_FOLDERS'])
			? $GLOBALS['EXIM_SHARED_SPAM_FOLDERS'] : false;
		if ($this->Account->IsInternal && $folders && count($folders) > 0 && $eximSharedFolders)
		{
			foreach ($folders as $key => $value)
			{
				if (in_array($value, $eximSharedFolders))
				{
					unset($folders[$key]);
				}
			}
		}
		
		$subsScrFolders = $this->_imapMail->list_subscribed_mailbox($this->Account->Delimiter);

		$existsIndex = array('VirusAdd' => true);
		$folderCollection = $this->GetFolderCollectionFromArrays($folders, $subsScrFolders, $this->Account->Delimiter, $existsIndex);

		if ($lastD != $this->Account->Delimiter)
		{
			$this->Account->UpdateDelimiter();
		}

		/* custom class */
		wm_Custom::StaticUseMethod('ChangeServerImapFoldersAfterGet', array(&$folderCollection));
		
		return $folderCollection;
	}

	/**
	 * @param Folder $folder
	 * @return bool
	 */
	function CreateFolder(&$folder)
	{
		if ($this->_imapMail->create_mailbox($folder->FullName))
		{
			if (!$folder->Hide)
			{
				$this->_imapMail->subscribe_mailbox($folder->FullName);
			}
			return true;
		}
		return false;
	}
	
	function SubscribeFolder(&$folder, $isHide = false)
	{
		if ($isHide)
		{
			return (USE_LSUB) ? false : $this->_imapMail->unsubscribe_mailbox($folder->FullName);
		}
		else
		{
			return $this->_imapMail->subscribe_mailbox($folder->FullName);
		}
	}

	/**
	 * @param Folder $folder
	 * @return bool
	 */
	function DeleteFolder(&$folder)
	{
		if ($this->_imapMail->delete_mailbox($folder->FullName))
		{
			$this->_imapMail->unsubscribe_mailbox($folder->FullName);
			return true;
		}
		return false;;
	}

	/**
	 * @param Folder $folder
	 * @package string $newName
	 * @return bool
	 */
	function RenameFolder(&$folder, $newName)
	{
		if ($folder && $folder->FullName != $newName && $this->_imapMail->rename_mailbox($folder->FullName, $newName))
		{
			if (!$folder->Hide)
			{
				$this->_imapMail->unsubscribe_mailbox($folder->FullName);
				$this->_imapMail->subscribe_mailbox($newName);
			}
			return true;
		}
		return false;
	}

	/**
	 * @return bool
	 */
	function IsQuotaSupport()
	{
		return $this->_imapMail->IsQuotaSupport();
	}

	/**
	 * @return int | false
	 */
	function GetQuota()
	{
		return $this->_imapMail->get_quota();
	}
	
	/**
	 * @return int | false
	 */
	function GetUsedQuota()
	{
		return $this->_imapMail->get_used_quota();
	}
	
	/**
	 * @param WebMailMessage $message
	 * @param Folder $folder
	 * @return bool
	 */
	function SaveMessage(&$message, &$folder)
	{
		$flagsStr = '';
		if(($message->Flags & MESSAGEFLAGS_Seen) == MESSAGEFLAGS_Seen)
		{
			$flagsStr .= ' \Seen';
		}
		if(($message->Flags & MESSAGEFLAGS_Flagged) == MESSAGEFLAGS_Flagged)
		{
			$flagsStr .= ' \Flagged';
		}
		if(($message->Flags & MESSAGEFLAGS_Deleted) == MESSAGEFLAGS_Deleted)
		{
			$flagsStr .= ' \Deleted';
		}
		if(($message->Flags & MESSAGEFLAGS_Answered) == MESSAGEFLAGS_Answered)
		{
			$flagsStr .= ' \Answered';
		}
		return $this->_imapMail->append_mail($folder->FullName, $flagsStr, $message->TryToGetOriginalMailMessage());
	}

	/**
	 * @param WebMailMessageCollection $messages
	 * @param Folder $folder
	 * @return bool
	 */
	function SaveMessages(&$messages, &$folder)
	{
		$result = true;
		for ($i = 0, $c = $messages->Count(); $i < $c; $i++)
		{
			$result &= $this->SaveMessage($messages->Get($i), $folder);
		}
		return $result;
	}

	function SetFolderType(&$folderObj, &$existsIndex)
	{
		switch ($folderObj->Type)
		{
			case FOLDERTYPE_Inbox:
				if (isset($existsIndex['InboxAdd'])) $folderObj->Type = FOLDERTYPE_Custom;
				$existsIndex['InboxAdd'] = true;
				break;
			case FOLDERTYPE_SentItems:
				if (isset($existsIndex['SentAdd'])) $folderObj->Type = FOLDERTYPE_Custom;
				$existsIndex['SentAdd'] = true;
				break;
			case FOLDERTYPE_Drafts:
				if (isset($existsIndex['DraftsAdd'])) $folderObj->Type = FOLDERTYPE_Custom;
				$existsIndex['DraftsAdd'] = true;
				break;
			case FOLDERTYPE_Spam:
				if (isset($existsIndex['SpamAdd'])) $folderObj->Type = FOLDERTYPE_Custom;
				$existsIndex['SpamAdd'] = true;
				break;
			case FOLDERTYPE_Trash:
				if ($this->_settings && $this->_settings->Imap4DeleteLikePop3)
				{
					if (isset($existsIndex['TrashAdd'])) $folderObj->Type = FOLDERTYPE_Custom;
				}
				else 
				{
					$folderObj->Type = FOLDERTYPE_Custom;
				}
				$existsIndex['TrashAdd'] = true;
				break;
			default:
				$folderObj->Type = FOLDERTYPE_Custom;
				break;
		}
	}
	
	/**
	 * @access private
	 * @param Array $uidList
	 * @param string $uid
	 * @return int
	 */
	function _getMessageIndexFromUid(&$uidList, $uid)
	{
		$searchKey = -1;
		if ($uidList)
		{
			$searchKey = array_search($uid, $uidList);
			if ($searchKey === null || $searchKey === false)
			{
				$searchKey = -1;
			}
		}
		return $searchKey;
	}

	/**
	 * @param string $messageUid
	 * @param Folder $folder
	 * @param int $flags
	 * @param short $action
	 * @return bool
	 */
	function SetMessagesFlag($messageUid, &$folder, $flags, $action)
	{
		$messageUidSet = array($messageUid);
		return $this->SetMessagesFlags($messageUidSet, true, $folder, $flags, $action);
	}

	/**
	 * return bool
	 */
	function IsMailBoxEmpty()
	{
		return $this->_imapMail->isMailBoxEmpty();
	}

	/**
	 * @param Array $messageIndexSet
	 * @param bool $indexAsUid
	 * @param Folder $folder
	 * @param int $flags
	 * @param short $action
	 * @return bool
	 */
	function SetMessagesFlags(&$messageIndexSet, $indexAsUid, &$folder, $flags, $action)
	{
		if ($this->_imapMail->open_mailbox($folder->FullName, false))
		{
			$flagsStr = '';
			if(($flags & MESSAGEFLAGS_Seen) == MESSAGEFLAGS_Seen)
			{
				$flagsStr .= ' \Seen';
			}
			if(($flags & MESSAGEFLAGS_Flagged) == MESSAGEFLAGS_Flagged)
			{
				$flagsStr .= ' \Flagged';
			}
			if(($flags & MESSAGEFLAGS_Deleted) == MESSAGEFLAGS_Deleted)
			{
				$flagsStr .= ' \Deleted';
			}
			if (($flags & MESSAGEFLAGS_Answered) == MESSAGEFLAGS_Answered)
			{
				$flagsStr .= ' \Answered';
			}

			$messageIndexes = $actionName = null;
			switch($action)
			{
				case ACTION_Set:
					$actionName = '+FLAGS';
					break;
				case ACTION_Remove:
					$actionName = '-FLAGS';
					break;
			}

			if ($messageIndexSet == null)
			{
				$messageIndexes = '1:*';
				$indexAsUid = false;
				if ($this->isMailBoxEmpty())
				{
					return true;
				}
			}
			else
			{
				$messageIndexes = implode(',', $messageIndexSet);
			}

			if (null !== $actionName && '' !== $flagsStr)
			{
				if ($indexAsUid)
				{
					return $this->_imapMail->uid_store_mail_flag($messageIndexes, $actionName, $flagsStr);
				}
				else
				{
					return $this->_imapMail->store_mail_flag($messageIndexes, $actionName, $flagsStr);
				}
			}
		}
		return false;
	}

	/**
	 * @param Array $messageIndexSet
	 * @param bool $indexAsUid
	 * @param Folder $folder
	 * @return bool
	 */
	function DeleteMessages(&$messageIndexSet, $indexAsUid, &$folder)
	{
		return $this->SetMessagesFlags($messageIndexSet, $indexAsUid, $folder, MESSAGEFLAGS_Deleted, ACTION_Set);
	}
	
	/**
	 * @param Array $messageIndexSet
	 * @param Folder $folder
	 * @return bool
	 */
	function SetDeleteFlagAndPurgeByUids(&$messageUidSet, &$folder)
	{
		return $this->SetMessagesFlags($messageUidSet, true, $folder, MESSAGEFLAGS_Deleted, ACTION_Set) &&
			$this->PurgeUidOrFolder($folder, $messageUidSet);
	}
	
	/**
	 * @param Array $messageIndexSet
	 * @param bool $indexAsUid
	 * @param Folder $folder
	 * @param Folder $toFolder
	 * @return bool
	 */
	function MoveMessages(&$messageIndexSet, $indexAsUid, &$folder, &$toFolder)
	{
		if ($folder->IdDb != $toFolder->IdDb)
		{
			return $this->CopyMessages($messageIndexSet, $indexAsUid, $folder, $toFolder) &
				$this->DeleteMessages($messageIndexSet, $indexAsUid, $folder) &
				$this->PurgeFolder($folder);
		}
		return true;
	}

	/**
	 * @param Folder $folder
	 * @return bool
	 */
	function PurgeFolder(&$folder)
	{
		return $this->_imapMail->open_mailbox($folder->FullName, false) && $this->_imapMail->expunge_mailbox();
	}
	
	/**
	 * @param Folder $folder
	 * @param Array $arrayUids
	 */
	function PurgeUidFolder(&$folder, $arrayUids)
	{
		if (is_array($arrayUids) && count($arrayUids) > 0)
		{
			$strUids = implode(',', $arrayUids);
			return $this->_imapMail->open_mailbox($folder->FullName, false) && $this->_imapMail->expunge_uid_mailbox($strUids);
		}
		
		return true;
	}

	/**
	 * @param Folder $folder
	 * @param Array $arrayUids
	 */
	function PurgeUidOrFolder(&$folder, $arrayUids)
	{
		if (is_array($arrayUids) && count($arrayUids) > 0)
		{
			$strUids = implode(',', $arrayUids);
			if ($this->_imapMail->open_mailbox($folder->FullName, false))
			{
				return $this->_imapMail->expunge_uid_or_not_mailbox($strUids);
			}
		}
		
		return false;
	}
	
	/**
	 * @param Array $messageIndexSet
	 * @param bool $indexAsUid
	 * @param Folder $fromFolder
	 * @param Folder $toFolder
	 * @return bool
	 */
	function CopyMessages(&$messageIndexSet, $indexAsUid, &$fromFolder, &$toFolder)
	{
		$messageIndexes = implode(',', $messageIndexSet);
		if ($this->_imapMail->open_mailbox($fromFolder->FullName, false))
		{
			return ($indexAsUid)
				? $this->_imapMail->uid_copy_mail($messageIndexes, $toFolder->FullName)
				: $this->_imapMail->copy_mail($messageIndexes, $toFolder->FullName);
		}
		return false;
	}

	function SetEximSpamMessages($messageUidSet, $fromFolder, $toFolder)
	{
		$messageUids = trim(implode(',', $messageUidSet));
		if (strlen($messageUids) > 0)
		{
			if ($this->_imapMail->open_mailbox($fromFolder->FullName, false))
			{
				return $this->_imapMail->uid_copy_mail($messageUids, $toFolder->FullName);
			}
		}
		
		return false;
	}

	/**
	 * @param Folder $folder
	 * @return bool
	 */
	function GetFolderMessageCount(&$folder)
	{
		$countArray = $this->_imapMail->get_all_and_unnread_msg_count($folder->FullName);
		if($countArray == null)
		{
			return false;
		}
		$folder->MessageCount = $countArray[HKC_ALL_MSG];
		$folder->UnreadMessageCount = $countArray[HKC_UNSEEN_MSG];
		return true;
	}

	/**
	 * @access private
	 * @param WebMailMessage $message
	 * @param string $flags
	 */
	function _setMessageFlags(&$message, $flags)
	{
		$message->Flags = $this->getIntFlags($flags);
	}

	/**
	 * @param String $strFlags
	 * @return Integer
	 */
	function getIntFlags($flags)
	{
		$intFlags = 0;
		$flags = explode(' ', strtolower($flags));
		foreach($flags as $flag)
		{
			switch(trim($flag))
			{
				case '\seen':		$intFlags |= MESSAGEFLAGS_Seen;		break;
				case '\answered':	$intFlags |= MESSAGEFLAGS_Answered;	break;
				case '\flagged':	$intFlags |= MESSAGEFLAGS_Flagged;	break;
				case '\deleted':	$intFlags |= MESSAGEFLAGS_Deleted;	break;
				case '\draft':		$intFlags |= MESSAGEFLAGS_Draft;	break;
				case '\recent':		$intFlags |= MESSAGEFLAGS_Recent;	break;
			}
		}
		return $intFlags;
	}

	function GetOrderByForImapSort()
	{
		$result = '';
		switch ($this->Account->DefaultOrder)
		{
			case DEFAULTORDER_FromDesc:		$result = 'FROM';				break;
			case DEFAULTORDER_From:			$result = 'REVERSE FROM';		break;
			case DEFAULTORDER_ToDesc:		$result = 'TO';					break;
			case DEFAULTORDER_To:			$result = 'REVERSE TO';			break;
			case DEFAULTORDER_SubjDesc:		$result = 'SUBJECT';			break;
			case DEFAULTORDER_Subj:			$result = 'REVERSE SUBJECT';	break;
			case DEFAULTORDER_DateDesc:		$result = 'ARRIVAL';			break;
			case DEFAULTORDER_Date:			$result = 'REVERSE ARRIVAL';	break;
			case DEFAULTORDER_SizeDesc:		$result = 'SIZE';				break;
			case DEFAULTORDER_Size:			$result = 'REVERSE SIZE';		break;
		}
		return $result;
	}

}
Return current item: AfterLogic WebMail Lite PHP