Location: PHPKode > scripts > AfterLogic WebMail Lite PHP > afterlogic-webmail-lite-php/webmail/common/class_contactstorage.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.'common/class_settings.php');
	require_once(WM_ROOTPATH.'common/class_account.php');
	require_once(WM_ROOTPATH.'common/class_log.php');
	
class ContactsDbDriver extends ContactsDriver implements IContactsDriver
{
	/**
	 * @var MySqlStorage
	 */
	var $_db;
	
	/**
	 * Initialize driver class params
	 */
	public function InitDriver()
	{
		$this->_db =& DbStorageCreator::CreateDatabaseStorage($this->_account, $this->_settings);
		$this->_db->Connect();
	}
	
	/**
	 * @param	mix		$contactId
	 * @return	AddressBookRecord
	 */
	public function GetContact($contactId)
	{
		return $this->_db->SelectAddressBookRecord($contactId);
	}
	
	/**
	 * @param	int			$groupId
	 * @param	int			$lookForType
	 * @param	string		$lookForField
	 * @return	array		array(contact_count, group_count)
	 */
	public function GetContactsAndGroupsCount($groupId, $lookForType, $lookForField)
	{
		$countArray = array(0, 0);
		if ($lookForField === '')
		{
			$countArray =& $this->_db->SelectAddressContactsAndGroupsCount($lookForType, $this->_account->IdUser);
		}
		else
		{
			if ($groupId == -1)
			{
				$countArray =& $this->_db->SelectAddressContactsAndGroupsCount($lookForType, $this->_account->IdUser, $lookForField);
			}
			else
			{
				$countArray =& $this->_db->SelectAddressContactsAndGroupsCount($lookForType, $this->_account->IdUser, $lookForField, $groupId);
			}
		}
		return $countArray;
	}

	/**
	 * @param	array		$counts			array(contact_count, group_count)
	 * @param	int			$page
	 * @param	string		$sortField
	 * @param	int			$sortOrder
	 * @param	int			$groupId
	 * @param	int			$lookForType
	 * @param	string		$lookForField
	 * @return	ContactCollection
	 */
	public function GetContactsAndGroups($counts, $page, $sortField, $sortOrder, $groupId, $lookForType, $lookForField)
	{
		$contacts = null;
		$countContactsAndGroups = $counts[0] + $counts[1];

		if ($countContactsAndGroups < ($page - 1) * $this->_account->ContactsPerPage)
		{
			$page = 1;
		}

		if ($lookForField === '')
		{
			$contacts =& $this->_db->LoadContactsAndGroups($page, $sortField, $sortOrder);
		}
		else
		{
			if ($countContactsAndGroups > 0)
			{
				$contacts =& $this->_db->SearchContactsAndGroups($page, $lookForField, $groupId, $sortField, $sortOrder, $lookForType);
			}
		}
		
		return $contacts;
	}
	
	/**
	 * @param	int		$groupId
	 * @return	array
	 */
	public function GetContactsOfGroup($groupId)
	{
		return $this->_db->SelectAddressGroupContacts($groupId);
	}
	
	/**
	 * @param	int		$contactId
	 * @return	AddressGroup
	 */
	public function GetGroup($groupId)
	{
		return $this->_db->SelectGroupById($groupId);
	}
	
	/**
	 * @return	array	array(id => name)
	 */
	public function GetGroups()
	{
		return $this->_db->SelectUserAddressGroupNames();
	}
	
	/**
	 * @param	int		$contactId
	 * @return	array	array(id => name)
	 */
	public function GetGroupsOfContact($contactId)
	{
		return $this->_db->SelectAddressGroupContact($contactId);
	}
	
	/**
	 * @return	bool
	 */
	public function DeleteContact($contactId)
	{
		return $this->_db->DeleteAddressBookRecord($contactId);
	}
	
	/**
	 * @return	bool
	 */
	public function DeleteGroup($groupId)
	{
		return $this->_db->DeleteAddressGroup($groupId);
	}
	
	/**
	 * @param	int		$contactId
	 * @param	int		$groupId
	 * @return	bool
	 */
	public function AddContactToGroup($contactId, $groupId)
	{
		$return = true;
		$return &= $this->_db->DeleteAddressGroupsContacts($contactId, $groupId);
		$return &= $this->_db->InsertAddressGroupContact($contactId, $groupId);
		return $return;
	}
	
	/**
	 * @param	int		$contactId
	 * @param	int		$groupId
	 * @return	bool
	 */
	public function InsertContactToGroup($contactId, $groupId)
	{
		return $this->_db->InsertAddressGroupContact($contactId, $groupId);
	}
	
	/**
	 * @param	AddressBookRecord	$contact
	 * @return	bool
	 */
	public function IsContactExist($name, $email)
	{
		return $this->_db->ExistAddressBookRecordDoublet($name, $email, $this->_account->IdUser);
	}
	
	/**
	 * @param	AddressBookRecord	$contact
	 * @return	bool
	 */
	public function CreateContact($contact)
	{
		return $this->_db->InsertAddressBookRecord($contact);
	}
	
	/**
	 * @param	AddressBookRecord	$contact
	 * @return	bool
	 */
	public function UpdateContact($contact)
	{
		if ($this->_db->UpdateAddressBookRecord($contact))
		{
			$result = $this->_db->DeleteAddressGroupsContactsByIdAddress($contact->IdAddress);
			if ($result && $contact->GroupsIds && count($contact->GroupsIds) > 0)
			{
				foreach ($contact->GroupsIds as $groupId)
				{
					$result &= $this->InsertContactToGroup($contact->IdAddress, $groupId);
				}	
			}
			return $result;
		}
		return false;
	}
	
	/**
	 * @param	string	$name
	 * @return	bool
	 */
	public function IsGroupExist($name)
	{
		return $this->_db->CheckExistsAddresGroupByName($name, $this->_account->IdUser);
	}
	
	/**
	 * @param	AddressGroup	$group
	 * @return	bool
	 */
	public function CreateGroup($group)
	{
		return $this->_db->InsertAddressGroup($group);
	}
	
	/**
	 * @param	AddressGroup	$group
	 * @return	bool
	 */
	public function UpdateGroup($group)
	{
		if ($this->_db->UpdateAddressGroup($group))
		{
			$result = $this->_db->DeleteAddressGroupsContactsByIdGroup($group->Id);
			if ($result && $group->ContactsIds && count($group->ContactsIds) > 0)
			{
				foreach ($group->ContactsIds as $contactId)
				{
					$result &= $this->InsertContactToGroup($contactId, $group->Id);
				}	
			}
			return $result;
		}
		
		return false;
	}
}

class ContactsLDAPDriver extends ContactsDriver implements IContactsDriver
{
	const OBJECT_CLASS_CONTACT = 'pabperson';
	const OBJECT_CLASS_GROUP = 'pabGroup';
	
	/**
	 * @var	string
	 */
	var $_pabURI;

	var $_host;
	var $_port;
	var $_search_dn;


	/**
	 * @var	resource
	 */
	var $_link;

	/**
	 * @var	resource
	 */
	var $_search;
	
	public function InitDriver()
	{
		$this->_pabURI = isset($this->_account->CustomValues['paburi']) ? $this->_account->CustomValues['paburi'] : '';
		$this->_link = null;
		$this->_search = null;

		$this->WriteLog('ldap: parse pbaURI = '.$this->_pabURI);
		$uriParseResult = ConvertUtils::LdapUriParse($this->_pabURI);
		$this->_host = $uriParseResult['host'];
		$this->_port = $uriParseResult['port'];
		$this->_search_dn = $uriParseResult['search_dn'];
	}

	private function _connect()
	{
		if (!extension_loaded('ldap'))
		{
			$errorString = 'Can\'t load LDAP extension.';
			$this->WriteLog('ldap: error: '.$errorString, LOG_LEVEL_ERROR);
			setGlobalError($errorString);
			return false;
		}
		if (!is_resource($this->_link))
		{
			$this->WriteLog('ldap: connect to '.$this->_host.':'.$this->_port);
			$this->_link = @ldap_connect($this->_host, $this->_port);
			if ($this->_link)
			{
				@register_shutdown_function(array(&$this, 'RegDisconnect'));

				@ldap_set_option($this->_link, LDAP_OPT_PROTOCOL_VERSION, 3);
				@ldap_set_option($this->_link, LDAP_OPT_REFERRALS, 0);

				$this->WriteLog('ldap: bind '.LDAP_CONTACT_BIND_DN.'/'.LDAP_CONTACT_PASSWORD);
				if (!@ldap_bind($this->_link, LDAP_CONTACT_BIND_DN, LDAP_CONTACT_PASSWORD))
				{
					$this->_checkBoolReturn(false);
					$this->_disconnect();
					return false;
				}
			}
			else
			{
				$this->_checkBoolReturn(false);
				return false;
			}
		}
		
		return true;
	}

	public function RegDisconnect()
	{
		static $isReg = false;
		if (!$isReg)
		{
			$this->_disconnect();
			$isReg = true;
		}
	}

	private function _disconnect()
	{
		if (is_resource($this->_link))
		{
			$this->WriteLog('ldap: ldap_unbind("'.LDAP_CONTACT_BIND_DN.'")');
			@ldap_unbind($this->_link, LDAP_CONTACT_BIND_DN);
			$this->WriteLog('ldap: diconnect');
			@ldap_close($this->_link);
			$this->_link = null;
		}
	}

	private function _search($objectFilter)
	{
		//if (!is_resource($this->_search))
		//{
			$this->WriteLog('ldap: ldap_search("'.$this->_search_dn.'", "'.$objectFilter.'")');
			$this->_search = @ldap_search($this->_link, $this->_search_dn, $objectFilter);
			$this->_checkBoolReturn($this->_search);
		//}
		return is_resource($this->_search);
	}

	/**
	 * Order a search in ascending and descending order.
	 * @url http://ru.php.net/manual/en/function.ldap-sort.php#85317
	 *
	 * @param resource from ldap_connect()
	 * @param resource from ldap_search()
	 * @param string of attribute to order
	 * @param string "asc" or "desc"
	 * @param integer page number
	 * @param integer entries per page
	 * @return array
	 */
	function _ldapSortPaginate($rConnection, $rSearch, $sField, $sOrder = 'asc', $iPage = null, $iPerPage = null)
	{
		$iTotalEntries = ldap_count_entries($rConnection, $rSearch);
		if ($iPage === null || $iPerPage === null)
		{
			# fetch all in one page
			$iStart = 0;
			$iEnd = $iTotalEntries - 1;
		}
		else
		{
			$iPage -= 1;
			$iPage = ($iPage < 0) ? 0 : $iPage;

			# calculate range of page
			if ($sOrder === 'desc')
			{
				$iStart = $iTotalEntries - (($iPage + 1) * $iPerPage);
			}
			else
			{
				$iStart = $iPage * $iPerPage;
			}

			$iStart = ($iStart < 0) ? 0 : $iStart;
			$iEnd = $iStart + $iPerPage - 1;
			$iEnd = ($iEnd > $iTotalEntries - 1) ? $iTotalEntries - 1 : $iEnd;
		}

		# fetch entries
		ldap_sort($rConnection, $rSearch, $sField);
		$aList = array();
		for ($iCurrent = 0, $rEntry = ldap_first_entry($rConnection, $rSearch);
			$iCurrent <= $iEnd && is_resource($rEntry);
			$iCurrent++, $rEntry = ldap_next_entry($rConnection, $rEntry)
		)
		{
			if ($iCurrent >= $iStart)
			{
				array_push($aList, ldap_get_attributes($rConnection, $rEntry));
			}
		}
		
		# if order is desc revert page's entries
		return ($sOrder === 'desc') ? array_reverse($aList) : $aList;
	}


	function _initAddressBookRecordByLdapEntries(&$addressBookRecord, $entry)
	{
		$map = $this->getContactMap(true);
		foreach ($entry as $key => $row)
		{
			if (isset($map[$key]))
			{
				$addressBookRecord->{$map[$key]} = isset($row[0]) ? $row[0] : '';
			}
		}
	}

	/**
	 * @param	mix		$contactId
	 * @return	AddressBookRecord
	 */
	public function GetContact($contactId)
	{
		$addressBookRecord = null;
		if ($this->_connect())
		{
			if ($this->_search('(&(objectClass='.self::OBJECT_CLASS_CONTACT.')(un='.$contactId.'))'))
			{
				$return = ldap_get_entries($this->_link, $this->_search);
				$this->_checkBoolReturn($return);
				if ($return && isset($return[0]))
				{
					$row = $return[0];
					if ($row && isset($row['un'][0]))
					{
						$addressBookRecord = new AddressBookRecord();
						$addressBookRecord->IdAddress = $row['un'][0];
						$addressBookRecord->IdUser = $_SESSION[USER_ID];

						$this->_initAddressBookRecordByLdapEntries($addressBookRecord, $row);
						
						$addressBookRecord->UseFriendlyName = true;

						$addressBookRecord->PrimaryEmail = PRIMARYEMAIL_Business;

						$dateofbirth = isset($row['dateofbirth'][0]) ? $row['dateofbirth'][0] : '';
						if (strlen($dateofbirth) > 0)
						{
							$dateofbirthArray = explode('/', $dateofbirth, 3);
							if (count($dateofbirthArray) === 3)
							{
								$addressBookRecord->BirthdayDay = (int) $dateofbirthArray[0];
								$addressBookRecord->BirthdayMonth = (int) $dateofbirthArray[1];
								$addressBookRecord->BirthdayYear = (int) $dateofbirthArray[2];
							}
						}

						if (isset($row['memberofpabgroup']))
						{
							unset($row['memberofpabgroup']['count']);

							$addressBookRecord->GroupsIds = array_values($row['memberofpabgroup']);
							$addressBookRecord->GroupsIds = is_array($addressBookRecord->GroupsIds)
								? $addressBookRecord->GroupsIds : array();
						}

						$addressBookRecord->FullName = trim($addressBookRecord->FirstName.' '.$addressBookRecord->SurName);
					}
				}
			}
		}
		
		return $addressBookRecord;
	}

	/**
	 * @param	int			$groupId
	 * @param	int			$lookForType
	 * @param	string		$lookForField
	 * @return	array		array(contact_count, group_count)
	 */
	public function GetContactsAndGroupsCount($groupId, $lookForType, $lookForField)
	{
		$countArray = array(0, 0);
		if ($this->_connect())
		{
			$filter = '(objectClass='.self::OBJECT_CLASS_CONTACT.')';
			if (strlen($lookForField) > 0)
			{
				$condition = ($lookForType == 1) ? $lookForField.'*' : '*'.$lookForField.'*';
				$groupCondition = ($groupId != -1 && strlen($groupId) > 0) ? '(memberofpabgroup='.$groupId.')' : '';
				$filter = '(&(objectClass='.self::OBJECT_CLASS_CONTACT.')'.$groupCondition.'(|(cn='.$condition.')(mail='.$condition.')))';
			}
			if ($this->_search($filter))
			{
				$cnt = ldap_count_entries($this->_link, $this->_search);
				$this->_checkBoolReturn($cnt);
				if (false !== $cnt)
				{
					$countArray[0] = $cnt;
				}
			}

			if ($groupId == -1 || strlen($groupId) == 0)
			{
				$filter = '(objectClass='.self::OBJECT_CLASS_GROUP.')';
				if (strlen($lookForField) > 0)
				{
					$condition = ($lookForType == 1) ? $lookForField.'*' : '*'.$lookForField.'*';
					$filter = '(&(objectClass='.self::OBJECT_CLASS_GROUP.')(cn='.$condition.'))';
				}
				if ($this->_search($filter))
				{
					$cnt = ldap_count_entries($this->_link, $this->_search);
					$this->_checkBoolReturn($cnt);
					if (false !== $cnt)
					{
						$countArray[1] = $cnt;
					}
				}
			}
		}
		$this->WriteLog('ldap: return counts = ['.$countArray[0].', '.$countArray[0].']');
		return $countArray;
	}

	/**
	 * @param	array		$counts			array(contact_count, group_count)
	 * @param	int			$page
	 * @param	string		$sortField
	 * @param	int			$sortOrder
	 * @param	int			$groupId
	 * @param	int			$lookForType
	 * @param	string		$lookForField
	 * @return	ContactCollection
	 */
	public function GetContactsAndGroups($counts, $page, $sortField, $sortOrder, $groupId, $lookForType, $lookForField)
	{
		$contacts = null;
		$countContactsAndGroups = $counts[0] + $counts[1];

		if ($countContactsAndGroups < ($page - 1) * $this->_account->ContactsPerPage)
		{
			$page = 1;
		}
		
		if ($this->_connect())
		{
			$filter = '(|(objectClass='.self::OBJECT_CLASS_CONTACT.')(objectClass='.self::OBJECT_CLASS_GROUP.'))';
			if (strlen($lookForField) > 0)
			{
				$condition = ($lookForType == 1) ? $lookForField.'*' : '*'.$lookForField.'*';
				$groupCondition = ($groupId != -1 && strlen($groupId) > 0) ? '(memberofpabgroup='.$groupId.')' : '';
				$filter = '(&(|(objectClass='.self::OBJECT_CLASS_CONTACT.')(objectClass='.self::OBJECT_CLASS_GROUP.'))'.$groupCondition.'(|(mail='.$condition.')(cn='.$condition.')))';
			}
			if ($this->_search($filter))
			{
				$sortField = (int) $sortField;
				$sortOrder = (int) $sortOrder;

				$pagSortField = 'mail';
				switch ($sortField)
				{
					case 1:
						$pagSortField = 'cn';
						break;
					case 2:
						$pagSortField = 'mail';
						break;
				}

				$pagSortOrder = (0 === $sortOrder) ? 'asc' : 'desc';
				$return = $this->_ldapSortPaginate($this->_link, $this->_search, $pagSortField, $pagSortOrder, $page, $this->_account->ContactsPerPage);
				if ($return)
				{
					$contacts = new ContactCollection();
					$k = 0;

					while (isset($return[$k]))
					{
						if ($lookForType == 1 && $k > SUGGESTCONTACTS)
						{
							break;
						}

						$row = $return[$k];
						if (is_array($row) && isset($row['un'][0], $row['objectClass']) && is_array($row['objectClass']))
						{
							$contact = new Contact();
							$contact->Id = $row['un'][0];
							$contact->IsGroup = in_array(self::OBJECT_CLASS_GROUP, $row['objectClass']);;
							$contact->Name = isset($row['cn'][0]) ? $row['cn'][0] : '';
							$contact->Email = isset($row['mail'][0]) ? $row['mail'][0] : '';
							$contact->Frequency = 0;
							$contact->UseFriendlyName = true;

							$contacts->Add($contact);
							unset($contact);
						}
						
						$k++;
					}
				}
			}
		}
		return $contacts;
	}

	/**
	 * @param	int		$groupId
	 * @return	ContactCollection
	 */
	public function GetContactsOfGroup($groupId)
	{
		$contacts = null;
		if ($this->_connect())
		{
			if ($this->_search('(&(objectClass='.self::OBJECT_CLASS_CONTACT.')(memberofpabgroup='.$groupId.'))'))
			{
				$contacts = new ContactCollection();
				$return = ldap_get_entries($this->_link, $this->_search);
				$this->_checkBoolReturn($return);
				if ($return)
				{
					$k = 0;
					while (isset($return[$k]))
					{
						$row = $return[$k];
						if (is_array($row) && isset($row['un'][0]))
						{
							$contact = new Contact();
							$contact->Id = $row['un'][0];
							$contact->Name = isset($row['cn'][0]) ? $row['cn'][0] : '';
							$contact->Email = isset($row['mail'][0]) ? $row['mail'][0] : '';
							$contact->UseFriendlyName = true;

							$contacts->Add($contact);
							unset($contact);
						}

						$k++;
					}
				}
			}
		}
		
		return $contacts;
	}

	/**
	 * @param	int		$contactId
	 * @return	AddressGroup
	 */
	public function GetGroup($groupId)
	{
		$group = null;
		if ($this->_connect())
		{
			if ($this->_search('(&(objectClass='.self::OBJECT_CLASS_GROUP.')(un='.$groupId.'))'))
			{
				$return = ldap_get_entries($this->_link, $this->_search);
				$this->_checkBoolReturn($return);
				if ($return && isset($return[0]))
				{
					$row = $return[0];
					if ($row && isset($row['un'][0]))
					{
						$group = new AddressGroup();
						$group->Id = $row['un'][0];
						$group->IdUser = $_SESSION[USER_ID];
						$group->Name = isset($row['cn'][0]) ? $row['cn'][0]: '';
						$group->IsOrganization = false;
					}
				}
			}
		}
		return $group;
	}

	/**
	 * @return	array	array(id => name)
	 */
	public function GetGroups()
	{
		$groups = array();
		if ($this->_connect())
		{
			if ($this->_search('(objectClass='.self::OBJECT_CLASS_GROUP.')'))
			{
				$return = ldap_get_entries($this->_link, $this->_search);
				$this->_checkBoolReturn($return);
				if ($return)
				{
					$k = 0;
					while (isset($return[$k]))
					{
						$row = $return[$k];
						if (isset($row['un'][0]))
						{
							$groups[$row['un'][0]] = isset($row['cn'][0]) ? $row['cn'][0] : '';
						}
						$k++;
					}
				}
			}
		}
		return $groups;
	}

	/**
	 * @param	int		$contactId
	 * @return	array	array(id => name)
	 */
	public function GetGroupsOfContact($contactId)
	{
		$groups = array();
		$contact = $this->GetContact($contactId);
		if ($contact && count($contact->GroupsIds) > 0)
		{
			foreach ($contact->GroupsIds as $id)
			{
				$group = $this->GetGroup($id);
				if ($group)
				{
					$groups[$id] = $group->Name;
				}
			}
		}
		return $groups;
	}

	/**
	 * @return	bool
	 */
	public function DeleteContact($contactId)
	{
		$return = false;
		if ($this->_connect())
		{
			$this->WriteLog('ldap: ldap_delete: un='.$contactId.','.$this->_search_dn);
			$return = @ldap_delete($this->_link, 'un='.$contactId.','.$this->_search_dn);
			$this->_checkBoolReturn($return);
		}
		return $return;
	}

	/**
	 * @return	bool
	 */
	public function DeleteGroup($groupId)
	{
		$return = false;
		if ($this->_connect())
		{
			$this->WriteLog('ldap: ldap_delete("un='.$groupId.','.$this->_search_dn.'")');
			$return = @ldap_delete($this->_link, 'un='.$groupId.','.$this->_search_dn);
			$this->_checkBoolReturn($return);
		}
		return $return;
	}

	/**
	 * @param	int		$contactId
	 * @param	int		$groupId
	 * @return	bool
	 */
	public function AddContactToGroup($contactId, $groupId)
	{
		$return = false;
		if ($this->_connect())
		{
			$contact = $this->GetContact($contactId);
			if ($contact)
			{
				if (!is_array($contact->GroupsIds) || !in_array($groupId, $contact->GroupsIds))
				{
					$contact->GroupsIds = is_array($contact->GroupsIds) ? $contact->GroupsIds : array();
					$contact->GroupsIds[] = $groupId;

					$entry = array('memberofpabgroup' => $contact->GroupsIds);
					$this->WriteLog('ldap: ldap_modify("un='.$contactId.','.$this->_search_dn.'", $entry)');
					$return = @ldap_modify($this->_link, 'un='.$contactId.','.$this->_search_dn, $entry);
					$this->_checkBoolReturn($return);
				}
			}
		}
		return $return;
	}

	/**
	 * @param	int		$contactId
	 * @param	int		$groupId
	 * @return	bool
	 */
	public function InsertContactToGroup($contactId, $groupId)
	{
		return $this->AddContactToGroup($contactId, $groupId);
	}

	/**
	 * @param	int		$contactId
	 * @param	int		$groupId
	 * @return	bool
	 */
	public function DeleteContactFromGroup($contactId, $groupId)
	{
		$return = false;
		if ($this->_connect())
		{
			$contact = $this->GetContact($contactId);
			if ($contact)
			{
				if (is_array($contact->GroupsIds) && in_array($groupId, $contact->GroupsIds))
				{
					for ($i = 0, $c = count($contact->GroupsIds); $i < $c; $i++)
					{
						if ($groupId == $contact->GroupsIds[$i])
						{
							unset($contact->GroupsIds[$i]);
						}
					}

					$entry = array('memberofpabgroup' => $contact->GroupsIds);
					$this->WriteLog('ldap: ldap_modify("un='.$contactId.','.$this->_search_dn.'", $entry)');
					$return = @ldap_modify($this->_link, 'un='.$contactId.','.$this->_search_dn, $entry);
					$this->_checkBoolReturn($return);
				}
				else
				{
					$return = true;
				}
			}
		}
		return $return;
	}

	/**
	 * @param	string	$name
	 * @param	string	$email
	 * @return	bool
	 */
	public function IsContactExist($name, $email)
	{
		if ($this->_connect())
		{
			$contactNameSearch = (strlen($name) > 0) ? '(cn='.$name.')' : '';
			if ($this->_search('(&(objectClass='.self::OBJECT_CLASS_CONTACT.')'.$contactNameSearch.'(mail='.$email.'))'))
			{
				$cnt = ldap_count_entries($this->_link, $this->_search);
				return ($cnt && $cnt > 0);
			}
		}
		return false;
	}

	/**
	 * @param	AddressGroup	$group
	 * @return	array
	 */
	function getGroupEntryFromAddressGroup($group)
	{
		return array(
				'un' => $group->Id,
				'cn' => $group->Name,
				'objectClass' => array('top', 'pabGroup')
			);
	}

	/**
	 * @param	AddressBookRecord	$addressBookRecord
	 * @return	array
	 */
	function getContactEntryFromAddressBookRecord($addressBookRecord)
	{
		$entry = array(
				'un' => $addressBookRecord->IdAddress,
				'sn' => '',
				'cn' => '',
				'dtmfSwapped' => '',
				'dtmf' => '',
				'objectClass' =>
					array(
						'top',
						'person',
						'pabDtmf',
						'cmgpabPerson',
						'pabperson',
						'organizationalPerson',
						'inetOrgPerson'
					)
			);

		$map = $this->getContactMap();
		foreach ($map as $entryKey => $objectKey)
		{
			if (strlen($addressBookRecord->{$objectKey}) > 0)
			{
				$entry[$entryKey] = $addressBookRecord->{$objectKey};
			}
		}

		if ($addressBookRecord->BirthdayDay && $addressBookRecord->BirthdayMonth && $addressBookRecord->BirthdayYear)
		{
			$entry['dateOfBirth'] = $addressBookRecord->BirthdayDay.'/'.$addressBookRecord->BirthdayMonth.'/'.$addressBookRecord->BirthdayYear;
		}

		if (is_array($addressBookRecord->GroupsIds))
		{
			foreach($addressBookRecord->GroupsIds as $groupId)
			{
				$entry['memberofpabgroup'][] = $groupId;
			}
		}

		$entry['memberofpabgroup'] = isset($entry['memberofpabgroup']) ? $entry['memberofpabgroup'] : array();

		return $entry;
	}
	
	function getContactMap($lowerKeys = false)
	{
		$return = array(
			'personalTitle' => 'Title',
			'givenName' => 'FirstName',
			'sn' => 'SurName',
			'nickname' => 'NickName',
			'cn' => 'FullName',

			'homeemail' => 'HomeEmail',
			'homestreet' => 'HomeStreet',
			'homelocalityname' => 'HomeCity',
			'homestateorprovincename' => 'HomeState',
			'homepostcode' => 'HomeZip',
			'homeCountry' => 'HomeCountry',
			'homefax' => 'HomeFax',
			'homemobilephonenumber' => 'HomeMobile',
			'homePhone' => 'HomePhone',

			'mail' => 'BusinessEmail',
			'o' => 'BusinessCompany',
			'title' => 'BusinessJobTitle',
			'departmentnumber' => 'BusinessDepartment',
			'street' => 'BusinessStreet',
			'l' => 'BusinessCity',
			'st' => 'BusinessState',
			'postalCode' => 'BusinessZip',
			'co' => 'BusinessCountry',
			'labeledUri' => 'BusinessWeb',
			'facsimileTelephoneNumber' => 'BusinessFax',
			'telephoneNumber' => 'BusinessPhone',
			'mobile' => 'BusinessMobile',
		);

		return $lowerKeys ? array_change_key_case($return, CASE_LOWER) : $return;
	}

	/**
	 * @param	AddressBookRecord	$contact
	 * @return	bool
	 */
	public function CreateContact($contact)
	{
		$return = false;
		if ($this->_connect())
		{
			$un = 'contact_'.md5($contact->FullName.$contact->BusinessEmail.time());
			$contact->IdAddress = $un;
			$contact->FullName = trim($contact->FirstName.' '.$contact->SurName);

			$entry = $this->getContactEntryFromAddressBookRecord($contact);
			if (isset($entry['memberofpabgroup']) && is_array($entry['memberofpabgroup']) && count($entry['memberofpabgroup']) == 0)
			{
				unset($entry['memberofpabgroup']);
			}

			$this->WriteLog('ldap: ldap_add("un='.$un.','.$this->_search_dn.'", $entry)');
			$this->WriteLog('ldap: $entry = '.print_r($entry, true));
			$return = @ldap_add($this->_link, 'un='.$un.','.$this->_search_dn, $entry);
			$this->_checkBoolReturn($return);
		}
		return $return;
	}

	/**
	 * @param	AddressBookRecord	$contact
	 * @return	bool
	 */
	public function UpdateContact($contact)
	{
		$return = false;
		if ($this->_connect())
		{
			$contact->FullName = trim($contact->FirstName.' '.$contact->SurName);
			
			$entry = $this->getContactEntryFromAddressBookRecord($contact);

			$this->WriteLog('ldap: ldap_modify("un='.$contact->IdAddress.','.$this->_search_dn.'", $entry)');
			$this->WriteLog('ldap: $entry = '.print_r($entry, true));
			$return = @ldap_modify($this->_link, 'un='.$contact->IdAddress.','.$this->_search_dn, $entry);
			$this->_checkBoolReturn($return);
		}
		return $return;
	}

	/**
	 * @param	string	$name
	 * @return	bool
	 */
	public function IsGroupExist($name)
	{
		if ($this->_connect())
		{
			if ($this->_search('(&(objectClass='.self::OBJECT_CLASS_GROUP.')(cn='.$name.'))'))
			{
				$cnt = ldap_count_entries($this->_link, $this->_search);
				return ($cnt && $cnt > 0);
			}
		}
		return false;
	}

	/**
	 * @param	AddressGroup	$group
	 * @return	bool
	 */
	public function CreateGroup($group)
	{
		$return = false;
		if ($this->_connect())
		{
			$un = 'group_'.md5($group->Name.time());
			$group->Id = $un;
			$entry = $this->getGroupEntryFromAddressGroup($group);

			$this->WriteLog('ldap: ldap_add("un='.$un.','.$this->_search_dn.'", $entry)');
			$this->WriteLog('ldap: $entry = '.print_r($entry, true));
			$return = @ldap_add($this->_link, 'un='.$un.','.$this->_search_dn, $entry);
			$this->_checkBoolReturn($return);
		}
		return $return;
	}

	/**
	 * @param	AddressGroup	$group
	 * @return	bool
	 */
	public function UpdateGroup($group)
	{
		$return = false;
		if ($this->_connect())
		{
			$entry = array(
				'cn' => $group->Name
			);

			$contacts = $this->GetContactsOfGroup($group->Id);
			$serverIds = array();

			if ($contacts && $contacts->Count() > 0)
			{
				$contactKeys = array_keys($contacts->Instance());
				foreach ($contactKeys as $key)
				{
					$contact =& $contacts->Get($key);
					if ($contact)
					{
						$serverIds[] = $contact->Id;
					}
					unset($contact);
				}
			}

			$deleteIds = array();
			foreach ($serverIds as $id)
			{
				if (!in_array($id, $group->ContactsIds))
				{
					$deleteIds[] = $id;
				}
			}

			foreach ($deleteIds as $id)
			{
				$this->DeleteContactFromGroup($id, $group->Id);
			}

			$this->WriteLog('ldap: ldap_modify: un='.$group->Id.','.$this->_search_dn);
			$return = ldap_modify($this->_link, 'un='.$group->Id.','.$this->_search_dn, $entry);
			$this->_checkBoolReturn($return);
		}
		return $return;
	}

	private function _checkBoolReturn($return)
	{
		if (false === $return)
		{
			$this->WriteLog('ldap: error #'hide@address.com($this->_link).': 'hide@address.com($this->_link), LOG_LEVEL_ERROR);
		}
		return $return;
	}
}

interface IContactsDriver
{
	/**
	 * @param	int			$groupId
	 * @param	int			$lookForType
	 * @param	string		$lookForField
	 * @return	array		array(contact_count, group_count)
	 */
	public function GetContactsAndGroupsCount($groupId, $lookForType, $lookForField);
	
	/**
	 * @param	array		$counts			array(contact_count, group_count)
	 * @param	int			$page
	 * @param	string		$sortField
	 * @param	int			$sortOrder
	 * @param	int			$groupId
	 * @param	int			$lookForType
	 * @param	string		$lookForField
	 * @return	ContactCollection
	 */
	public function GetContactsAndGroups($counts, $page, $sortField, $sortOrder, $groupId, $lookForType, $lookForField);
	
	/**
	 * @param	int		$groupId
	 * @return	array
	 */
	public function GetContactsOfGroup($groupId);
	
	/**
	 * @param	int		$contactId
	 * @return	AddressBookRecord
	 */
	public function GetContact($contactId);
	
	/**
	 * @param	int		$contactId
	 * @return	AddressGroup
	 */
	public function GetGroup($groupId);
	
	/**
	 * @return	array	array(id => name)
	 */
	public function GetGroups();
	
	/**
	 * @param	int		$contactId
	 * @return	array	array(id => name)
	 */
	public function GetGroupsOfContact($contactId);
	
	/**
	 * @return	bool
	 */
	public function DeleteContact($contactId);
	
	/**
	 * @return	bool
	 */
	public function DeleteGroup($groupId);
	
	/**
	 * @param	int		$contactId
	 * @param	int		$groupId
	 * @return	bool
	 */
	public function AddContactToGroup($contactId, $groupId);
	
	/**
	 * @param	int		$contactId
	 * @param	int		$groupId
	 * @return	bool
	 */
	public function InsertContactToGroup($contactId, $groupId);
	
	/**
	 * @param	string	$name
	 * * @param	string	$email
	 * @return	bool
	 */
	public function IsContactExist($name, $email);
	
	/**
	 * @param	AddressBookRecord	$contact
	 * @return	bool
	 */
	public function CreateContact($contact);
	
	/**
	 * @param	AddressBookRecord	$contact
	 * @return	bool
	 */
	public function UpdateContact($contact);
	
	/**
	 * @param	string	$name
	 * @return	bool
	 */
	public function IsGroupExist($name);
	
	/**
	 * @param	AddressGroup	$group
	 * @return	bool
	 */
	public function CreateGroup($group);
	
	/**
	 * @param	AddressGroup	$group
	 * @return	bool
	 */
	public function UpdateGroup($group);
	
}

abstract class ContactsDriver
{
	/**
	 * @var Account
	 */
	var $_account;
	
	/**
	 * @var Settings
	 */
	var $_settings;
	
	/**
	 * @param	Account		$account
	 * @param	Settings	$settings
	 * @return	ContactsDriver
 	 */
	final function ContactsDriver($account, $settings)
	{
		$this->InitMain($account, $settings);
		$this->InitDriver();
	}

	public function InitMain($account, $settings)
	{
		$this->_account = $account;
		$this->_settings = $settings;
	}
	
	/**
	 * Initialize driver class params
	 */
	abstract public function InitDriver();

	/**
	 * @param string $string
	 */
	public function WriteLog($string, $logLevel = LOG_LEVEL_DEBUG)
	{
		$log =& CLog::CreateInstance();
		$log->WriteLine($string, $logLevel);
	}
}

final class ContactCreator
{
	static $instance;

	private function ContactCreator() {}
	
	/**
	 * @param	Account		$account
	 * @param	Settings	$settings
	 * @return	ContactsDbDriver
	 */
	static public function &CreateContactStorage($account, $settings)
	{
		if (!self::$instance)
		{
			self::$instance = USE_LDAP_CONTACT
				? new ContactsLDAPDriver($account, $settings)
				: new ContactsDbDriver($account, $settings);
		}
		else
		{
			self::$instance->InitMain($account, $settings);
		}
		
		return self::$instance;
	}
}
	
Return current item: AfterLogic WebMail Lite PHP