Your IP : 13.59.14.52


Current Path : /var/www/axolotl/data/www/yar.axolotls.ru/bitrix/modules/dav/classes/general/
Upload File :
Current File : /var/www/axolotl/data/www/yar.axolotls.ru/bitrix/modules/dav/classes/general/exchangeclient.php

<?
// http://msdn.microsoft.com/en-us/library/aa580675(v=EXCHG.140).aspx

abstract class CDavExchangeClient
{
	private $scheme = "http";
	private $server = null;
	private $port = '80';
	private $userName = null;
	private $userPassword = null;

	private $proxyScheme = null;
	private $proxyServer = null;
	private $proxyPort = null;
	private $proxyUserName = null;
	private $proxyUserPassword = null;
	private $proxyUsed = false;

	private $fp = null;
	private $socketTimeout = 5;
	private $connected = false;
	private $userAgent = 'Bitrix Exchange client';
	private $path = '/ews/exchange.asmx';

	private $encoding = "windows-1251";

	private $arError = array();
	private $debug = false;

	public function __construct($scheme, $server, $port, $userName, $userPassword)
	{
		$this->scheme = ((strtolower($scheme) == "https") ? "https" : "http");
		$this->server = $server;
		$this->port = $port;
		$this->userName = $userName;
		$this->userPassword = $userPassword;

		$this->connected = false;
		$this->debug = false;

		$this->proxyScheme = null;
		$this->proxyServer = null;
		$this->proxyPort = null;
		$this->proxyUserName = null;
		$this->proxyUserPassword = null;
		$this->proxyUsed = false;
	}

	public function Debug()
	{
		$this->debug = true;
	}

	public function SetCurrentEncoding($siteId = null)
	{
		$this->encoding = CDav::GetCharset($siteId);
		if (is_null($this->encoding) || empty($this->encoding))
			$this->encoding = "utf-8";
	}

	public function SetProxy($proxyScheme, $proxyServer, $proxyPort, $proxyUserName, $proxyUserPassword)
	{
		$this->proxyScheme = ((strtolower($proxyScheme) == "https") ? "https" : "http");
		$this->proxyServer = $proxyServer;
		$this->proxyPort = $proxyPort;
		$this->proxyUserName = $proxyUserName;
		$this->proxyUserPassword = $proxyUserPassword;

		$this->proxyUsed = (strlen($this->proxyServer) > 0 && strlen($this->proxyPort) > 0);
	}

	public function GetPath()
	{
		return $this->path;
	}

	public function Connect()
	{
		if ($this->connected)
			return true;

		$requestScheme = $this->scheme;
		$requestServer = $this->server;
		$requestPort = $this->port;
		if ($this->proxyUsed)
		{
			$requestScheme = $this->proxySchemes;
			$requestServer = $this->proxyServer;
			$requestPort = $this->proxyPort;
		}

		switch ($requestScheme)
		{
			case 'https':
				if (!function_exists("openssl_verify"))
				{
					$this->arError[] = array("EC0", "OpenSSL PHP extention required");
					$this->connected = false;
					return false;
				}

				$requestScheme = 'ssl://';
				$requestPort = ($requestPort === null) ? 443 : $requestPort;
				break;

			case 'http':
				$requestScheme = '';
				$requestPort = ($requestPort === null) ? 80 : $requestPort;
				break;

			default:
				$this->arError[] = array("EC1", "Invalid protocol");
				$this->connected = false;
				return false;
		}

		//$this->fp = @fsockopen($requestScheme.$requestServer, $requestPort, $errno, $errstr, $this->socketTimeout);
		$this->fp = @stream_socket_client(sprintf('%s:%s', $requestScheme.$requestServer, $requestPort), $errno, $errstr, $this->socketTimeout, STREAM_CLIENT_CONNECT,stream_context_create(array('ssl' => array('verify_peer' => false, 'verify_peer_name' => false))));

		if (!$this->fp)
		{
			$this->arError[] = array($errno, $errstr);
			$this->connected = false;
			return false;
		}
		else
		{
			socket_set_blocking($this->fp, 1);
			$this->connected = true;
			return true;
		}
	}

	public function Disconnect()
	{
		if (!$this->connected)
			return;

		fclose($this->fp);
		$this->connected = false;
	}

	public function GetErrors()
	{
		return $this->arError;
	}

	public function AddError($code, $message)
	{
		$this->arError[] = array($code, $message);
	}

	public function ClearErrors()
	{
		$this->arError = array();
	}

	protected function ParseError($response)
	{
		$code = $response->GetStatus('code');
		$isErrorCode = false;

		if ($code == 401)
		{
			$this->arError[] = array(401, $response->GetStatus('phrase'));
			$isErrorCode = true;
		}
		elseif ($code == 500)
		{
			try
			{
				$xmlDoc = $response->GetBodyXml();
			}
			catch (Exception $e)
			{
				$this->arError[] = array($e->getCode(), $e->getMessage());
				return;
			}

			$arFault = $xmlDoc->GetPath("/Envelope/Body/Fault");
			foreach ($arFault as $fault)
			{
				$errorCode = "";
				$arResponseCode = $fault->GetPath("/Fault/detail/ResponseCode");
				if (count($arResponseCode) > 0)
				{
					$errorCode = $arResponseCode[0]->GetContent();
				}
				else
				{
					$arFaultCode = $fault->GetPath("/Fault/faultcode");
					if (count($arFaultCode) > 0)
						$errorCode = $arFaultCode[0]->GetContent();
				}

				$errorMessage = "";
				$arMessage = $fault->GetPath("/Fault/detail/Message");
				if (count($arMessage) > 0)
				{
					$errorMessage = $arMessage[0]->GetContent();
				}
				else
				{
					$arFaultString = $fault->GetPath("/Fault/faultstring");
					if (count($arFaultString) > 0)
						$errorMessage = $arFaultString[0]->GetContent();
				}

				$this->arError[] = array($this->Encode($errorCode), $this->Encode($errorMessage));
			}
			$isErrorCode = true;
		}

		return $isErrorCode;
	}

	protected function FormatStandartFieldsArray($key, $value, &$arFields)
	{
		$bProcessed = false;

		switch ($key)
		{
			case "BodyType":
				$bProcessed = true;
				$arFields[$key] = (strtolower($value) == "html" ? "HTML" : "Text");
				break;

			case "Importance":
				$bProcessed = true;
				$ar = array("low" => "Low", "normal" => "Normal", "high" => "High");

				$value = strtolower($value);
				if (array_key_exists($value, $ar))
					$arFields[$key] = $ar[$value];
				else
					$this->arError[] = array("WrongImportance", "Available values for Importance are Low, Normal, High");
				break;

			case "LegacyFreeBusyType":
				$bProcessed = true;
				$ar = array("free" => "Free", "tentative" => "Tentative", "busy" => "Busy", "oof" => "OOF", "nodata" => "NoData");

				$value = strtolower($value);
				if (array_key_exists($value, $ar))
					$arFields[$key] = $ar[$value];
				else
					$this->arError[] = array("WrongLegacyFreeBusyType", "Available values for LegacyFreeBusyType are Free, Tentative, Busy, OOF, NoData");
				break;

			case "Sensitivity":
				$bProcessed = true;
				$ar = array("normal" => "Normal", "personal" => "Personal", "private" => "Private", "confidential" => "Confidential");

				$value = strtolower($value);
				if (array_key_exists($value, $ar))
					$arFields[$key] = $ar[$value];
				else
					$this->arError[] = array("WrongSensitivity", "Available values for Sensitivity are Normal, Personal, Private, Confidential");
				break;

			case "Status":
				$bProcessed = true;
				$ar = array("notstarted" => "NotStarted", "inprogress" => "InProgress", "completed" => "Completed", "waitingonothers" => "WaitingOnOthers", "deferred" => "Deferred");

				$value = strtolower($value);
				if (array_key_exists($value, $ar))
					$arFields[$key] = $ar[$value];
				else
					$this->arError[] = array("WrongStatus", "Available values for Status are NotStarted, InProgress, Completed, WaitingOnOthers, Deferred");
				break;
		}

		return $bProcessed;
	}

	protected function FormatRecurrenceFieldsArray($key, $value, &$arFields)
	{
		$bProcessed = false;

		switch ($key)
		{
			case "RecurringStartDate":
			case "RecurringEndDate":
				$bProcessed = true;
				$arFields[$key] = date("Y-m-d", MakeTimeStamp($value));
				break;
			case "RecurringType":
				$bProcessed = true;
				$ar = array(
					"none" => "NONE",
					"monthly_absolute" => "MONTHLY_ABSOLUTE",
					"monthly_relative" => "MONTHLY_RELATIVE",
					"yearly_absolute" => "YEARLY_ABSOLUTE",
					"yearly_relative" => "YEARLY_RELATIVE",
					"monthly" => "MONTHLY",
					"yearly" => "YEARLY",
					"weekly" => "WEEKLY",
					"daily" => "DAILY"
				);

				if (empty($value))
					$value = "NONE";
				$value = strtolower($value);

				if (array_key_exists($value, $ar))
				{
					if ($ar[$value] != "NONE")
					{
						$arFields[$key] = $ar[$value];
						$arFields["Recurrence"] = true; // Error ErrorSchemaValidation in Exchange 2013
					}
				}
				else
				{
					$this->arError[] = array("WrongRecurringType", "Available values for RecurringType are NONE, MONTHLY_ABSOLUTE, MONTHLY_RELATIVE, YEARLY_ABSOLUTE, YEARLY_RELATIVE, WEEKLY, DAILY");
				}
				break;

			case "RecurringDayOfWeekIndex":
				$bProcessed = true;
				$ar = array("first" => "First", "second" => "Second", "third" => "Third", "fourth" => "Fourth", "last" => "Last", 1 => "First", 2 => "Second", 3 => "Third", 4 => "Fourth");

				$value = strtolower($value);
				if (array_key_exists($value, $ar))
					$arFields[$key] = $ar[$value];
				else
					$this->arError[] = array("WrongRecurringDayOfWeekIndex", "Available values for RecurringDayOfWeekIndex are First, Second, Third, Fourth, Last");
				break;

			case "RecurringMonth":
				$bProcessed = true;
				$ar = array("january" => "January", "february" => "February", "march" => "March", "april" => "April", "may" => "May", "june" => "June", "july" => "July", "august" => "August", "september" => "September", "october" => "October", "november" => "November", "december" => "December", 1 => "January", 2 => "February", 3 => "March", 4 => "April", 5 => "May", 6 => "June", 7 => "July", 8 => "August", 9 => "September", 10 => "October", 11 => "November", 12 => "December");

				$value = strtolower($value);
				if (array_key_exists($value, $ar))
					$arFields[$key] = $ar[$value];
				else
					$this->arError[] = array("WrongRecurringMonth", "Available values for RecurringMonth are January, February, March, April, May, June, July, August, September, October, November, December");
				break;

			case "RecurringDaysOfWeek":
				$bProcessed = true;
				$ar = array("sunday" => "Sunday", "monday" => "Monday", "tuesday" => "Tuesday", "wednesday" => "Wednesday", "thursday" => "Thursday", "friday" => "Friday", "saturday" => "Saturday", "day" => "Day", "weekday" => "Weekday", "weekendday" => "WeekendDay", 0 => "Sunday", 1 => "Monday", 2 => "Tuesday", 3 => "Wednesday", 4 => "Thursday", 5 => "Friday", 6 => "Saturday", 7 => "Sunday");

				$value = strtolower($value);
				$arValue = explode(",", $value);
				foreach ($arValue as $value1)
				{
					$arValue1 = explode(" ", $value1);
					foreach ($arValue1 as $value2)
					{
						$value2 = trim($value2);
						if (!empty($value2))
						{
							if (array_key_exists($value2, $ar))
							{
								if (isset($arFields[$key]) && strlen($arFields[$key]) > 0)
									$arFields[$key] .= " ";
								$arFields[$key] .= $ar[$value2];
							}
							else
							{
								$this->arError[] = array("WrongRecurringDaysOfWeek", "Available values for RecurringDaysOfWeek are Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Day, Weekday, WeekendDay");
							}
						}
					}
				}
				break;
		}

		return $bProcessed;
	}

	protected function ConvertRecurrenceToArray($recurrence)
	{
		$arResultItem = array();

		$arAbsoluteMonthlyRecurrence = $recurrence->GetPath("/Recurrence/AbsoluteMonthlyRecurrence");
		if (count($arAbsoluteMonthlyRecurrence) > 0)
		{
			$arResultItem["RECURRING_TYPE"] = "MONTHLY_ABSOLUTE";
			$arAbsoluteMonthlyRecurrenceInterval = $recurrence->GetPath("/Recurrence/AbsoluteMonthlyRecurrence/Interval");
			if (count($arAbsoluteMonthlyRecurrenceInterval) > 0)
				$arResultItem["RECURRING_INTERVAL"] = $arAbsoluteMonthlyRecurrenceInterval[0]->GetContent();
			$arAbsoluteMonthlyRecurrenceDayOfMonth = $recurrence->GetPath("/Recurrence/AbsoluteMonthlyRecurrence/DayOfMonth");
			if (count($arAbsoluteMonthlyRecurrenceDayOfMonth) > 0)
				$arResultItem["RECURRING_DAYOFMONTH"] = $arAbsoluteMonthlyRecurrenceDayOfMonth[0]->GetContent();
		}

		$arRelativeMonthlyRecurrence = $recurrence->GetPath("/Recurrence/RelativeMonthlyRecurrence");
		if (count($arRelativeMonthlyRecurrence) > 0)
		{
			$arResultItem["RECURRING_TYPE"] = "MONTHLY_RELATIVE";
			$arRelativeMonthlyRecurrenceInterval = $recurrence->GetPath("/Recurrence/RelativeMonthlyRecurrence/Interval");
			if (count($arRelativeMonthlyRecurrenceInterval) > 0)
				$arResultItem["RECURRING_INTERVAL"] = $arRelativeMonthlyRecurrenceInterval[0]->GetContent();
			$arRelativeMonthlyRecurrenceDaysOfWeek = $recurrence->GetPath("/Recurrence/RelativeMonthlyRecurrence/DaysOfWeek");
			if (count($arRelativeMonthlyRecurrenceDaysOfWeek) > 0)
				$arResultItem["RECURRING_DAYSOFWEEK"] = $arRelativeMonthlyRecurrenceDaysOfWeek[0]->GetContent();
			$arRelativeMonthlyRecurrenceDayOfWeekIndex = $recurrence->GetPath("/Recurrence/RelativeMonthlyRecurrence/DayOfWeekIndex");
			if (count($arRelativeMonthlyRecurrenceDayOfWeekIndex) > 0)
				$arResultItem["RECURRING_DAYOFWEEKINDEX"] = $arRelativeMonthlyRecurrenceDayOfWeekIndex[0]->GetContent();
		}

		$arAbsoluteYearlyRecurrence = $recurrence->GetPath("/Recurrence/AbsoluteYearlyRecurrence");
		if (count($arAbsoluteYearlyRecurrence) > 0)
		{
			$arResultItem["RECURRING_TYPE"] = "YEARLY_ABSOLUTE";
			$arAbsoluteYearlyRecurrenceDayOfMonth = $recurrence->GetPath("/Recurrence/AbsoluteYearlyRecurrence/DayOfMonth");
			if (count($arAbsoluteYearlyRecurrenceDayOfMonth) > 0)
				$arResultItem["RECURRING_DAYOFMONTH"] = $arAbsoluteYearlyRecurrenceDayOfMonth[0]->GetContent();
			$arAbsoluteYearlyRecurrenceMonth = $recurrence->GetPath("/Recurrence/AbsoluteYearlyRecurrence/Month");
			if (count($arAbsoluteYearlyRecurrenceMonth) > 0)
				$arResultItem["RECURRING_MONTH"] = $arAbsoluteYearlyRecurrenceMonth[0]->GetContent();
		}

		$arRelativeYearlyRecurrence = $recurrence->GetPath("/Recurrence/RelativeYearlyRecurrence");
		if (count($arRelativeYearlyRecurrence) > 0)
		{
			$arResultItem["RECURRING_TYPE"] = "YEARLY_RELATIVE";
			$arRelativeYearlyRecurrenceDaysOfWeek = $recurrence->GetPath("/Recurrence/RelativeYearlyRecurrence/DaysOfWeek");
			if (count($arRelativeYearlyRecurrenceDaysOfWeek) > 0)
				$arResultItem["RECURRING_DAYSOFWEEK"] = $arRelativeYearlyRecurrenceDaysOfWeek[0]->GetContent();
			$arRelativeYearlyRecurrenceDayOfWeekIndex = $recurrence->GetPath("/Recurrence/RelativeYearlyRecurrence/DayOfWeekIndex");
			if (count($arRelativeYearlyRecurrenceDayOfWeekIndex) > 0)
				$arResultItem["RECURRING_DAYOFWEEKINDEX"] = $arRelativeYearlyRecurrenceDayOfWeekIndex[0]->GetContent();
			$arRelativeYearlyRecurrenceMonth = $recurrence->GetPath("/Recurrence/RelativeYearlyRecurrence/Month");
			if (count($arRelativeYearlyRecurrenceMonth) > 0)
				$arResultItem["RECURRING_MONTH"] = $arRelativeYearlyRecurrenceMonth[0]->GetContent();
		}

		$arWeeklyRecurrence = $recurrence->GetPath("/Recurrence/WeeklyRecurrence");
		if (count($arWeeklyRecurrence) > 0)
		{
			$arResultItem["RECURRING_TYPE"] = "WEEKLY";
			$arWeeklyRecurrenceInterval = $recurrence->GetPath("/Recurrence/WeeklyRecurrence/Interval");
			if (count($arWeeklyRecurrenceInterval) > 0)
				$arResultItem["RECURRING_INTERVAL"] = $arWeeklyRecurrenceInterval[0]->GetContent();
			$arWeeklyRecurrenceDaysOfWeek = $recurrence->GetPath("/Recurrence/WeeklyRecurrence/DaysOfWeek");
			if (count($arWeeklyRecurrenceDaysOfWeek) > 0)
				$arResultItem["RECURRING_DAYSOFWEEK"] = $arWeeklyRecurrenceDaysOfWeek[0]->GetContent();
		}

		$arDailyRecurrence = $recurrence->GetPath("/Recurrence/DailyRecurrence");
		if (count($arDailyRecurrence) > 0)
		{
			$arResultItem["RECURRING_TYPE"] = "DAILY";
			$arDailyRecurrenceInterval = $recurrence->GetPath("/Recurrence/DailyRecurrence/Interval");
			if (count($arDailyRecurrenceInterval) > 0)
				$arResultItem["RECURRING_INTERVAL"] = $arDailyRecurrenceInterval[0]->GetContent();
		}

		$arNumberedRecurrence = $recurrence->GetPath("/Recurrence/NumberedRecurrence");
		if (count($arNumberedRecurrence) > 0)
		{
			$arNumberedRecurrenceStartDate = $recurrence->GetPath("/Recurrence/NumberedRecurrence/StartDate");
			if (count($arNumberedRecurrenceStartDate) > 0)
				$arResultItem["RECURRING_STARTDATE"] = CDavICalendarTimeZone::GetFormattedServerDate($arNumberedRecurrenceStartDate[0]->GetContent());
			$arNumberedRecurrenceNumberOfOccurrences = $recurrence->GetPath("/Recurrence/NumberedRecurrence/NumberOfOccurrences");
			if (count($arNumberedRecurrenceNumberOfOccurrences) > 0)
				$arResultItem["RECURRING_NUMBEROFOCCURRENCES"] = $arNumberedRecurrenceNumberOfOccurrences[0]->GetContent();
		}

		$arNoEndRecurrence = $recurrence->GetPath("/Recurrence/NoEndRecurrence");
		if (count($arNoEndRecurrence) > 0)
		{
			$arNoEndRecurrenceStartDate = $recurrence->GetPath("/Recurrence/NoEndRecurrence/StartDate");
			if (count($arNoEndRecurrenceStartDate) > 0)
				$arResultItem["RECURRING_STARTDATE"] = CDavICalendarTimeZone::GetFormattedServerDate($arNoEndRecurrenceStartDate[0]->GetContent());
		}

		$arEndDateRecurrence = $recurrence->GetPath("/Recurrence/EndDateRecurrence");
		if (count($arEndDateRecurrence) > 0)
		{
			$arEndDateRecurrenceStartDate = $recurrence->GetPath("/Recurrence/EndDateRecurrence/StartDate");
			if (count($arEndDateRecurrenceStartDate) > 0)
				$arResultItem["RECURRING_STARTDATE"] = CDavICalendarTimeZone::GetFormattedServerDate($arEndDateRecurrenceStartDate[0]->GetContent());
			$arEndDateRecurrenceEndDate = $recurrence->GetPath("/Recurrence/EndDateRecurrence/EndDate");
			if (count($arEndDateRecurrenceEndDate) > 0)
				$arResultItem["RECURRING_ENDDATE"] = CDavICalendarTimeZone::GetFormattedServerDate($arEndDateRecurrenceEndDate[0]->GetContent());
		}

		return $arResultItem;
	}

	public function Encode($text)
	{
		if (is_null($text) || empty($text))
			return $text;
		if ($this->encoding == "utf-8")
			return $text;

		global $APPLICATION;
		return $APPLICATION->ConvertCharset($text, "utf-8", $this->encoding);
	}

	public function Decode($text)
	{
		if (is_null($text) || empty($text))
			return $text;
		if ($this->encoding == "utf-8")
			return $text;

		global $APPLICATION;
		return $APPLICATION->ConvertCharset($text, $this->encoding, "utf-8");
	}

	public function ExecuteOperation($operationName, $operationBody)
	{
		$request = $this->CreateSOAPRequest("POST", $this->GetPath());
		$request->AddHeader("Content-Type", "text/xml; charset=utf-8");
		$request->AddHeader("SOAPAction", "http://schemas.microsoft.com/exchange/services/2006/messages/".$operationName);
		$request->AddHeader("Connection", "Keep-Alive");
		$request->SetBody($operationBody);

		$this->Connect();
		$response = $this->Send($request);
		$this->Disconnect();

		if (is_null($response))
			return null;

		return $response->GetBody();
	}

	public function Send($request)
	{
		if ($this->debug)
		{
			$f = fopen($_SERVER["DOCUMENT_ROOT"]."/++++++++.+++", "a");
			fwrite($f, "\n>>>>>>>>>>>>>>>>>> REQUEST >>>>>>>>>>>>>>>>\n".$request->ToString()."\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n");
			fclose($f);
		}

		$i = 0;
		while (true)
		{
			$i++;
			if ($i > 3)
				break;

			$this->SendRequest($request);
			$response = $this->GetResponse();

			if (!is_null($response))
			{
				if (($location = $response->GetHeader('Location')) && !is_null($location))
				{
					if ($this->proxyUsed)
						$request->SetPath($this->scheme."://".$this->server.((intval($this->port) > 0) ? ":".$this->port : "").$location);
					else
						$request->SetPath($location);

					continue;
				}
				elseif (($statusCode = $response->GetStatus('code')) && (intval($statusCode) == 401))
				{
					$request = $this->Authenticate($request, $response);
					if (is_null($request))
					{
						$this->AddError("SS1", "Unsupported authentication method (supported: basic, digest)");
						return null;
					}
					continue;
				}
			}

			break;
		}

		if ($this->debug)
		{
			$f = fopen($_SERVER["DOCUMENT_ROOT"]."/++++++++.+++", "a");
			fwrite($f, "\n>>>>>>>>>>>>>>>>>> RESPONSE >>>>>>>>>>>>>>>>\n");
			if (is_null($response))
				fwrite($f, "NULL");
			else
				fwrite($f, $response->Dump());
			fwrite($f, "\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n");
			fclose($f);
		}

		return $response;
	}

	private function Authenticate($request, $response)
	{
		$authenticate = $response->GetHeader('WWW-Authenticate');
		$authenticateProxy = $response->GetHeader('Proxy-Authenticate');
		if (is_null($authenticate) && is_null($authenticateProxy))
			return null;

		if (!is_null($authenticate) && !is_array($authenticate))
			$authenticate = array($authenticate);
		if (!is_null($authenticateProxy) && !is_array($authenticateProxy))
			$authenticateProxy = array($authenticateProxy);

		if (!is_null($authenticate))
		{
			$arAuth = array();
			foreach ($authenticate as $auth)
			{
				$auth = trim($auth);
				$p = strpos($auth, " ");
				if ($p !== false)
					$arAuth[strtolower(substr($auth, 0, $p))] = trim(substr($auth, $p));
				else
					$arAuth[strtolower($auth)] = "";
			}

			if (array_key_exists("digest", $arAuth))
				$request = $this->AuthenticateDigest(CDavExchangeClientResponce::ExtractArray($arAuth["digest"]), $request, $response, "Authorization");
			elseif (array_key_exists("basic", $arAuth))
				$request = $this->AuthenticateBasic(CDavExchangeClientResponce::ExtractArray($arAuth["basic"]), $request, $response, "Authorization");
			else
				return null;
		}

		if (!is_null($authenticateProxy))
		{
			$arAuthProxy = array();
			foreach ($authenticateProxy as $auth)
			{
				$auth = trim($auth);
				$p = strpos($auth, " ");
				if ($p !== false)
					$arAuthProxy[strtolower(substr($auth, 0, $p))] = trim(substr($auth, $p));
				else
					$arAuthProxy[strtolower($auth)] = "";
			}

			if (array_key_exists("digest", $arAuthProxy))
				$request = $this->AuthenticateDigest(CDavExchangeClientResponce::ExtractArray($arAuthProxy["digest"]), $request, $response, "Proxy-Authorization");
			elseif (array_key_exists("basic", $arAuthProxy))
				$request = $this->AuthenticateBasic(CDavExchangeClientResponce::ExtractArray($arAuthProxy["basic"]), $request, $response, "Proxy-Authorization");
			else
				return null;
		}

		return $request;
	}

	private function AuthenticateDigest($arDigestRequest, $request, $response, $verb = "Authorization")
	{
		// qop="auth",algorithm=MD5-sess,nonce="+Upgraded+v1fdcb1e18d2cc7a72322c81c0d8d2a3c332f7908ef0dfcb01aa9fb63930eadf5722dc8f6ce7b82912353531b18360cd62382a6c2433939d3f",charset=utf-8,realm="Digest"

		$cn = md5(uniqid());

		$a1 = md5($this->userName.':'.$arDigestRequest["realm"].':'.$this->userPassword).":".$arDigestRequest["nonce"].":".$cn;
		$a2 = $request->GetMethod().":".$request->GetPath();
		$hash = md5(md5($a1).":".$arDigestRequest["nonce"].":00000001:".$cn.":".$arDigestRequest["qop"].":".md5($a2));

		$request->SetHeader(
			$verb,
			sprintf(
				"Digest username=\"%s\",realm=\"%s\",nonce=\"%s\",uri=\"%s\",cnonce=\"%s\",nc=00000001,algorithm=%s,response=\"%s\",qop=\"%s\",charset=utf-8",
				$this->userName,
				$arDigestRequest["realm"],
				$arDigestRequest["nonce"],
				$request->GetPath(),
				$cn,
				$arDigestRequest["algorithm"],
				$hash,
				$arDigestRequest["qop"]
			)
		);

		return $request;
	}

	private function AuthenticateBasic($arBasicRequest, $request, $response, $verb = "Authorization")
	{
		// realm="test-exch2007"

		$request->SetHeader(
			$verb,
			sprintf(
				"Basic %s",
				base64_encode($this->userName.":".$this->userPassword)
			)
		);

		return $request;
	}

	private function SendRequest($request)
	{
		if (!$this->connected)
			$this->Connect();

		if (!$this->connected)
			return null;

		fputs($this->fp, $request->ToString());
	}

	private function GetResponse()
	{
		if (!$this->connected)
			return null;

		$arHeaders = array();
		$body = "";

		while ($line = fgets($this->fp, 4096))
		{
			if ($line == "\r\n")
				break;

			$arHeaders[] = trim($line);
		}

		if (count($arHeaders) <= 0)
			return null;

		$bChunked = $bConnectionClosed = false;
		$contentLength = null;
		foreach ($arHeaders as $value)
		{
			if (!$bChunked && preg_match("#Transfer-Encoding:\s*chunked#i", $value))
				$bChunked = true;
			if (!$bConnectionClosed && preg_match('#Connection:\s*close#i', $value))
				$bConnectionClosed = true;
			if (is_null($contentLength))
			{
				if (preg_match('#Content-Length:\s*([0-9]*)#i', $value, $arMatches))
					$contentLength = intval($arMatches[1]);
				if (preg_match('#HTTP/1\.1\s+204#i', $value))
					$contentLength = 0;
			}
		}

		if ($bChunked)
		{
			do
			{
				$line = fgets($this->fp, 4096);
				$line = strtolower($line);

				$chunkSize = "";
				$i = 0;
				while ($i < strlen($line))
				{
					$c = substr($line, $i, 1);
					if (in_array($c, array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f")))
						$chunkSize .= $c;
					else
						break;
					$i++;
				}

				$chunkSize = hexdec($chunkSize);

				if ($chunkSize > 0)
				{
					$lb = $chunkSize;
					$body1 = '';
					while ($lb > 0)
					{
						$d = fread($this->fp, $lb);
						if ($d === false)
							break;

						$body1 .= $d;
						$lb = $chunkSize - ((function_exists('mb_strlen') ? mb_strlen($body1, 'latin1') : strlen($body1)));
					}

					$body .= $body1;
				}

				fgets($this->fp, 4096);
			}
			while ($chunkSize);
		}
		elseif ($contentLength === 0)
		{
		}
		elseif ($contentLength > 0)
		{
			$lb = $contentLength;
			while ($lb > 0)
			{
				$d = fread($this->fp, $lb);
				if ($d === false)
					break;

				$body .= $d;
				$lb = $contentLength - ((function_exists('mb_strlen') ? mb_strlen($body, 'latin1') : strlen($body)));
			}
		}
		else
		{
			socket_set_timeout($this->fp, 0);

			while (!feof($this->fp))
			{
				$d = fread($this->fp, 4096);
				if ($d === false)
					break;

				$body .= $d;
				if (substr($body, -9) == "\r\n\r\n0\r\n\r\n")
				{
					$body = substr($body, 0, -9);
					break;
				}
			}

			socket_set_timeout($this->fp, $this->socketTimeout);
		}

		if ($bConnectionClosed)
			$this->Disconnect();

		$responce = new CDavExchangeClientResponce($arHeaders, $body);

		$httpVersion = $responce->GetStatus('version');
		if (is_null($httpVersion) || ($httpVersion != 'HTTP/1.1' && $httpVersion != 'HTTP/1.0'))
			return null;

		return $responce;
	}

	protected function CreateSOAPRequest($method, $path)
	{
		$request = new CDavExchangeClientRequest($this);

		$request->SetMethod($method);
		if ($this->proxyUsed)
			$request->SetPath($this->scheme."://".$this->server.((intval($this->port) > 0) ? ":".$this->port : "").$path);
		else
			$request->SetPath($path);

		$request->AddHeader('Host', $this->server);
		$request->AddHeader('User-Agent', $this->userAgent);

		return $request;
	}

	public static function NormalizeArray(&$arData, $arMap)
	{
		$arKeys = array_keys($arData);
		foreach ($arKeys as $key)
		{
			$keyLower = strtolower($key);
			if (array_key_exists($keyLower, $arMap))
			{
				$value = $arData[$key];
				unset($arData[$key]);
				$arData[$arMap[$keyLower]] = $value;
			}
		}
	}

	public static function InitUserEntityLoadMessages($key, $defaultMessage = "")
	{
		$arResult = array();

		$dbLang = CLanguage::GetList($b = "", $o = "", array());
		while ($arLang = $dbLang->Fetch())
		{
			$MESS = array();

			$lid = preg_replace("/[^a-z0-9]/i", "", $arLang["LID"]);
			$fn = $_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/dav/lang/".$lid."/options.php";
			$fnDef = $_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/dav/lang/en/options.php";
			if (file_exists($fn))
				include($fn);
			elseif (file_exists($fnDef))
				include($fnDef);

			if (isset($MESS["DAV_".$key]))
				$arResult[$arLang["LID"]] = $MESS["DAV_".$key];
			else
				$arResult[$arLang["LID"]] = $defaultMessage;
		}

		return $arResult;
	}

	public static function Test($scheme, $server, $port, $userName, $userPassword, $mailbox, $arPFolders = array(), $bDebug = false)
	{
		$arAvailableFolders = array("calendar", "contacts", "tasks");

		if (!is_array($arPFolders))
			$arPFolders = array($arPFolders);

		$arFolders = array();
		foreach ($arPFolders as $value)
		{
			if (in_array($value, $arAvailableFolders))
				$arFolders[] = $value;
		}

		if (count($arFolders) <= 0)
			$arFolders = $arAvailableFolders;

		$arMessages = array();

		if (in_array("calendar", $arFolders))
		{
			$e = new CDavExchangeCalendar($scheme, $server, $port, $userName, $userPassword);
			if ($bDebug)
				$e->Debug();

			$calendarId = null;
			$r = $e->AddCalendar(array("NAME" => "TestCalendarFolderName4", "MAILBOX" => $mailbox));
			$arMessages = array_merge($arMessages, $e->GetErrors());
			foreach ($r as $v)
				$calendarId = $v;

			if (is_null($calendarId))
			{
				$arMessages[] = array("ERROR", "Calendar folder creation error.");
			}
			else
			{
				$arMessages[] = array("SUCCESS", "Calendar folder was successfully created (Id = ".$calendarId["XML_ID"].", ChangeKey = ".$calendarId["MODIFICATION_LABEL"].").");

				$r = $e->UpdateCalendar($calendarId, array("NAME" => "New TestCalendarFolderName4"));
				$arMessages = array_merge($arMessages, $e->GetErrors());
				$calendarId = null;
				foreach ($r as $v)
					$calendarId = $v;

				if (is_null($calendarId))
				{
					$arMessages[] = array("ERROR", "Calendar folder modification error.");
				}
				else
				{
					$arMessages[] = array("SUCCESS", "Calendar folder was successfully updated (Id = ".$calendarId["XML_ID"].", ChangeKey = ".$calendarId["MODIFICATION_LABEL"].").");

					$bFound = false;
					$r = $e->GetCalendarsList(array("MAILBOX" => $mailbox));
					$arMessages = array_merge($arMessages, $e->GetErrors());
					foreach ($r as $v)
					{
						if (($v["NAME"] == "New TestCalendarFolderName4") && ($v["XML_ID"] == $calendarId["XML_ID"]))
							$bFound = true;
					}

					if (!$bFound)
					{
						$arMessages[] = array("ERROR", "Calendar folder is not found by list.");
					}
					else
					{
						$arMessages[] = array("SUCCESS", "Calendar folder was successfully found by list.");

						$bFound = false;
						$r = $e->GetCalendarById($calendarId["XML_ID"]);
						$arMessages = array_merge($arMessages, $e->GetErrors());
						foreach ($r as $v)
						{
							if (($v["NAME"] == "New TestCalendarFolderName4") && ($v["XML_ID"] == $calendarId["XML_ID"]))
								$bFound = true;
						}

						if (!$bFound)
						{
							$arMessages[] = array("ERROR", "Calendar folder is not found by id.");
						}
						else
						{
							$arMessages[] = array("SUCCESS", "Calendar folder was successfully found by id.");

							$itemId = null;
							$arFields = array(
								"MAILBOX" => $mailbox,
								"CALENDAR_ID" => $calendarId["XML_ID"],
								"NAME" => "TestCalendarItem Name",
								"DETAIL_TEXT" => "TestCalendarItem detail text",
								"DETAIL_TEXT_TYPE" => "html",
								"PROPERTY_IMPORTANCE" => "normal",
								"PROPERTY_REMIND_SETTINGS" => "20_min",
								"ACTIVE_FROM" => "16.10.2011 09:00:00",
								"ACTIVE_TO" => "16.10.2011 09:30:00",
								"PROPERTY_LOCATION" => "Some location",
							);
							$r = $e->Add($arFields);
							$arMessages = array_merge($arMessages, $e->GetErrors());
							foreach ($r as $v)
								$itemId = $v;

							if (is_null($itemId))
							{
								$arMessages[] = array("ERROR", "Calendar item creation error.");
							}
							else
							{
								$arMessages[] = array("SUCCESS", "Calendar item was successfully created (Id = ".$itemId["XML_ID"].", ChangeKey = ".$itemId["MODIFICATION_LABEL"].").");

								$arFields = array(
									"NAME" => "New TestCalendarItem Name",
									"DETAIL_TEXT" => "TestCalendarItem detail text",
									"DETAIL_TEXT_TYPE" => "text",
									"ACTIVE_FROM" => "17.10.2011 09:00:00",
									"ACTIVE_TO" => "17.10.2011 09:30:00",
									"PROPERTY_LOCATION" => "Some new location",
								);
								$r = $e->Update($itemId, $arFields);
								$itemId = null;
								$arMessages = array_merge($arMessages, $e->GetErrors());
								foreach ($r as $v)
									$itemId = $v;

								if (is_null($itemId))
								{
									$arMessages[] = array("ERROR", "Calendar item modification error.");
								}
								else
								{
									$arMessages[] = array("SUCCESS", "Calendar item was successfully updated (Id = ".$itemId["XML_ID"].", ChangeKey = ".$itemId["MODIFICATION_LABEL"].").");

									$bFound = false;
									$r = $e->GetList(
										array("Mailbox" => $mailbox, "CalendarId" => $calendarId["XML_ID"]),
										array("ItemShape" => "AllProperties")
									);
									$arMessages = array_merge($arMessages, $e->GetErrors());
									foreach ($r as $v)
									{
										if (($v["NAME"] == "New TestCalendarItem Name") && ($v["XML_ID"] == $itemId["XML_ID"]))
											$bFound = true;
									}

									if (!$bFound)
									{
										$arMessages[] = array("ERROR", "Calendar item is not found by list.");
									}
									else
									{
										$arMessages[] = array("SUCCESS", "Calendar item was successfully found by list.");

										$bFound = false;
										$r = $e->GetById($itemId["XML_ID"]);
										$arMessages = array_merge($arMessages, $e->GetErrors());
										foreach ($r as $v)
										{
											if (($v["NAME"] == "New TestCalendarItem Name") && ($v["XML_ID"] == $itemId["XML_ID"]))
												$bFound = true;
										}

										if (!$bFound)
										{
											$arMessages[] = array("ERROR", "Calendar item is not found by id.");
										}
										else
										{
											$arMessages[] = array("SUCCESS", "Calendar item was successfully found by id.");

											$r = $e->Delete($itemId["XML_ID"]);
											if (!$r)
											{
												$arMessages[] = array("ERROR", "Calendar item deletion error.");
											}
											else
											{
												$arMessages[] = array("SUCCESS", "Calendar item was successfully deleted.");

												$bFound = false;
												$r = $e->GetList(
													array("Mailbox" => $mailbox, "CalendarId" => $calendarId["XML_ID"]),
													array("ItemShape" => "IdOnly")
												);
												$arMessages = array_merge($arMessages, $e->GetErrors());
												foreach ($r as $v)
													$bFound = true;

												if ($bFound)
												{
													$arMessages[] = array("ERROR", "Calendar folder should be empty.");
												}
												else
												{
													$arMessages[] = array("SUCCESS", "Calendar folder is empty.");

													$r = $e->DeleteCalendar($calendarId["XML_ID"]);
													$arMessages = array_merge($arMessages, $e->GetErrors());
													if ($r)
														$arMessages[] = array("SUCCESS", "Calendar folder was successfully deleted.");
													else
														$arMessages[] = array("ERROR", "Calendar folder deletion error.");
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}

		if (in_array("contacts", $arFolders))
		{
			$e = new CDavExchangeContacts($scheme, $server, $port, $userName, $userPassword);
			if ($bDebug)
				$e->Debug();

			$addressbookId = null;
			$r = $e->AddAddressbook(array("NAME" => "TestAddressbookFolderName4", "MAILBOX" => $mailbox));
			$arMessages = array_merge($arMessages, $e->GetErrors());
			foreach ($r as $v)
				$addressbookId = $v;

			if (is_null($addressbookId))
			{
				$arMessages[] = array("ERROR", "Contacts folder creation error.");
			}
			else
			{
				$arMessages[] = array("SUCCESS", "Contacts folder was successfully created (Id = ".$addressbookId["XML_ID"].", ChangeKey = ".$addressbookId["MODIFICATION_LABEL"].").");

				$r = $e->UpdateAddressbook($addressbookId, array("NAME" => "New TestAddressbookFolderName4"));
				$arMessages = array_merge($arMessages, $e->GetErrors());
				$addressbookId = null;
				foreach ($r as $v)
					$addressbookId = $v;

				if (is_null($addressbookId))
				{
					$arMessages[] = array("ERROR", "Contacts folder modification error.");
				}
				else
				{
					$arMessages[] = array("SUCCESS", "Contacts folder was successfully updated (Id = ".$addressbookId["XML_ID"].", ChangeKey = ".$addressbookId["MODIFICATION_LABEL"].").");

					$bFound = false;
					$r = $e->GetAddressbooksList(array("MAILBOX" => $mailbox));
					$arMessages = array_merge($arMessages, $e->GetErrors());
					foreach ($r as $v)
					{
						if (($v["NAME"] == "New TestAddressbookFolderName4") && ($v["XML_ID"] == $addressbookId["XML_ID"]))
							$bFound = true;
					}

					if (!$bFound)
					{
						$arMessages[] = array("ERROR", "Contacts folder is not found by list.");
					}
					else
					{
						$arMessages[] = array("SUCCESS", "Contacts folder was successfully found by list.");

						$bFound = false;
						$r = $e->GetAddressbookById($addressbookId["XML_ID"]);
						$arMessages = array_merge($arMessages, $e->GetErrors());
						foreach ($r as $v)
						{
							if (($v["NAME"] == "New TestAddressbookFolderName4") && ($v["XML_ID"] == $addressbookId["XML_ID"]))
								$bFound = true;
						}

						if (!$bFound)
						{
							$arMessages[] = array("ERROR", "Contacts folder is not found by id.");
						}
						else
						{
							$arMessages[] = array("SUCCESS", "Contacts folder was successfully found by id.");

							$itemId = null;
							$arFields = array(
								"MAILBOX" => $mailbox,
								"ADDRESSBOOK_ID" => $addressbookId["XML_ID"],
								"NAME" => "TestAddressbookItem Name",
								"LAST_NAME" => "MyLastName",
								"SECOND_NAME" => "MySecondName",
								"EMAIL" => "vas2@sfbdsgdf.df",
								"WORK_POSITION" => "Programmer",
								"WORK_ZIP" => "236001",
								"WORK_CITY" => "Kaliningrad",
								"WORK_STREET" => "Kirov str., 261",
								"PERSONAL_PHONE" => "6547646546",
								"PERSONAL_MOBILE" => "55435656",
								"WORK_PHONE" => "876467343",
								"WORK_FAX" => "345737365",
								"WORK_COMPANY" => "Bitrix",
								"WORK_WWW" => "http://www.1c-bitrix.com",
								"PERSONAL_ICQ" => "535435353",
								"WORK_COUNTRY" => 23,
							);
							$r = $e->Add($arFields);
							$arMessages = array_merge($arMessages, $e->GetErrors());
							foreach ($r as $v)
								$itemId = $v;

							if (is_null($itemId))
							{
								$arMessages[] = array("ERROR", "Contacts item creation error.");
							}
							else
							{
								$arMessages[] = array("SUCCESS", "Contacts item was successfully created (Id = ".$itemId["XML_ID"].", ChangeKey = ".$itemId["MODIFICATION_LABEL"].").");

								$arFields = array(
									"NAME" => "New TestAddressbookItem Name",
									"LAST_NAME" => "My new LastName",
									"SECOND_NAME" => "MySecondName",
									"EMAIL" => "vas2@sfbdsgdf.df",
									"WORK_POSITION" => "Programmer",
									"WORK_ZIP" => "236001",
									"WORK_CITY" => "Kaliningrad",
									"WORK_STREET" => "Kirov str., 261",
									"PERSONAL_PHONE" => "6547646546",
									"PERSONAL_MOBILE" => "55435656",
									"WORK_PHONE" => "876467343",
									"WORK_FAX" => "345737365",
									"WORK_COMPANY" => "Bitrix",
									"WORK_WWW" => "http://www.1c-bitrix.com",
									"PERSONAL_ICQ" => "535435353",
									"WORK_COUNTRY" => 23,
								);
								$r = $e->Update($itemId, $arFields);
								$itemId = null;
								$arMessages = array_merge($arMessages, $e->GetErrors());
								foreach ($r as $v)
									$itemId = $v;

								if (is_null($itemId))
								{
									$arMessages[] = array("ERROR", "Contacts item modification error.");
								}
								else
								{
									$arMessages[] = array("SUCCESS", "Contacts item was successfully updated (Id = ".$itemId["XML_ID"].", ChangeKey = ".$itemId["MODIFICATION_LABEL"].").");

									$bFound = false;
									$r = $e->GetList(
										array("Mailbox" => $mailbox, "AddressbookId" => $addressbookId["XML_ID"]),
										array("ItemShape" => "AllProperties")
									);
									$arMessages = array_merge($arMessages, $e->GetErrors());
									foreach ($r as $v)
									{
										if (($v["NAME"] == "New TestAddressbookItem Name") && ($v["XML_ID"] == $itemId["XML_ID"]))
											$bFound = true;
									}

									if (!$bFound)
									{
										$arMessages[] = array("ERROR", "Contacts item is not found by list.");
									}
									else
									{
										$arMessages[] = array("SUCCESS", "Contacts item was successfully found by list.");

										$bFound = false;
										$r = $e->GetById($itemId["XML_ID"]);
										$arMessages = array_merge($arMessages, $e->GetErrors());
										foreach ($r as $v)
										{
											if (($v["NAME"] == "New TestAddressbookItem Name") && ($v["XML_ID"] == $itemId["XML_ID"]))
												$bFound = true;
										}

										if (!$bFound)
										{
											$arMessages[] = array("ERROR", "Contacts item is not found by id.");
										}
										else
										{
											$arMessages[] = array("SUCCESS", "Contacts item was successfully found by id.");

											$r = $e->Delete($itemId["XML_ID"]);
											if (!$r)
											{
												$arMessages[] = array("ERROR", "Contacts item deletion error.");
											}
											else
											{
												$arMessages[] = array("SUCCESS", "Contacts item was successfully deleted.");

												$bFound = false;
												$r = $e->GetList(
													array("Mailbox" => $mailbox, "AddressbookId" => $addressbookId["XML_ID"]),
													array("ItemShape" => "IdOnly")
												);
												$arMessages = array_merge($arMessages, $e->GetErrors());
												foreach ($r as $v)
													$bFound = true;

												if ($bFound)
												{
													$arMessages[] = array("ERROR", "Contacts folder should be empty.");
												}
												else
												{
													$arMessages[] = array("SUCCESS", "Contacts folder is empty.");

													$r = $e->DeleteAddressbook($addressbookId["XML_ID"]);
													$arMessages = array_merge($arMessages, $e->GetErrors());
													if ($r)
														$arMessages[] = array("SUCCESS", "Contacts folder was successfully deleted.");
													else
														$arMessages[] = array("ERROR", "Contacts folder deletion error.");
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}

		if (in_array("tasks", $arFolders))
		{
			$e = new CDavExchangeTasks($scheme, $server, $port, $userName, $userPassword);
			if ($bDebug)
				$e->Debug();

			$folderId = null;
			$r = $e->AddFolder(array("NAME" => "TestFolderFolderName6", "MAILBOX" => $mailbox));
			$arMessages = array_merge($arMessages, $e->GetErrors());
			foreach ($r as $v)
				$folderId = $v;

			if (is_null($folderId))
			{
				$arMessages[] = array("ERROR", "Tasks folder creation error.");
			}
			else
			{
				$arMessages[] = array("SUCCESS", "Tasks folder was successfully created (Id = ".$folderId["XML_ID"].", ChangeKey = ".$folderId["MODIFICATION_LABEL"].").");

				$r = $e->UpdateFolder($folderId, array("NAME" => "New TestFolderFolderName6"));
				$arMessages = array_merge($arMessages, $e->GetErrors());
				$folderId = null;
				foreach ($r as $v)
					$folderId = $v;

				if (is_null($folderId))
				{
					$arMessages[] = array("ERROR", "Tasks folder modification error.");
				}
				else
				{
					$arMessages[] = array("SUCCESS", "Tasks folder was successfully updated (Id = ".$folderId["XML_ID"].", ChangeKey = ".$folderId["MODIFICATION_LABEL"].").");

					$bFound = false;
					$r = $e->GetFoldersList(array("MAILBOX" => $mailbox));
					$arMessages = array_merge($arMessages, $e->GetErrors());
					foreach ($r as $v)
					{
						if (($v["NAME"] == "New TestFolderFolderName6") && ($v["XML_ID"] == $folderId["XML_ID"]))
							$bFound = true;
					}

					if (!$bFound)
					{
						$arMessages[] = array("ERROR", "Tasks folder is not found by list.");
					}
					else
					{
						$arMessages[] = array("SUCCESS", "Tasks folder was successfully found by list.");

						$bFound = false;
						$r = $e->GetFolderById($folderId["XML_ID"]);
						$arMessages = array_merge($arMessages, $e->GetErrors());
						foreach ($r as $v)
						{
							if (($v["NAME"] == "New TestFolderFolderName6") && ($v["XML_ID"] == $folderId["XML_ID"]))
								$bFound = true;
						}

						if (!$bFound)
						{
							$arMessages[] = array("ERROR", "Tasks folder is not found by id.");
						}
						else
						{
							$arMessages[] = array("SUCCESS", "Tasks folder was successfully found by id.");

							$itemId = null;
							$arFields = array(
								"MAILBOX" => $mailbox,
								"FOLDER_ID" => $folderId["XML_ID"],
								"SUBJECT" => "TestFolderItem Name",
								"BODY" => "Should be done!",
								"BODY_TYPE" => "text",
								"IMPORTANCE" => "High",
								"START_DATE" => "20.10.2011",
								"DUE_DATE" => "25.10.2011",
								"PERCENT_COMPLETE" => "0",
								"STATUS" => "NotStarted",
								"TOTAL_WORK" => "123",
								"REMINDER_MINUTES_BEFORE_START" => 365,
							);
							$r = $e->Add($arFields);
							$arMessages = array_merge($arMessages, $e->GetErrors());
							foreach ($r as $v)
								$itemId = $v;

							if (is_null($itemId))
							{
								$arMessages[] = array("ERROR", "Tasks item creation error.");
							}
							else
							{
								$arMessages[] = array("SUCCESS", "Tasks item was successfully created (Id = ".$itemId["XML_ID"].", ChangeKey = ".$itemId["MODIFICATION_LABEL"].").");

								$arFields = array(
									"SUBJECT" => "New TestFolderItem Name",
									"BODY" => "Should be done!!!",
									"BODY_TYPE" => "text",
									"IMPORTANCE" => "Low",
									"START_DATE" => "20.10.2011",
									"DUE_DATE" => "24.10.2011",
									"PERCENT_COMPLETE" => "0",
									"STATUS" => "NotStarted",
									"TOTAL_WORK" => "23",
									"REMINDER_MINUTES_BEFORE_START" => 365,
								);
								$r = $e->Update($itemId, $arFields);
								$itemId = null;
								$arMessages = array_merge($arMessages, $e->GetErrors());
								foreach ($r as $v)
									$itemId = $v;

								if (is_null($itemId))
								{
									$arMessages[] = array("ERROR", "Tasks item modification error.");
								}
								else
								{
									$arMessages[] = array("SUCCESS", "Tasks item was successfully updated (Id = ".$itemId["XML_ID"].", ChangeKey = ".$itemId["MODIFICATION_LABEL"].").");

									$bFound = false;
									$r = $e->GetList(
										array("Mailbox" => $mailbox, "FolderId" => $folderId["XML_ID"]),
										array("ItemShape" => "AllProperties")
									);
									$arMessages = array_merge($arMessages, $e->GetErrors());
									foreach ($r as $v)
									{
										if (($v["SUBJECT"] == "New TestFolderItem Name") && ($v["XML_ID"] == $itemId["XML_ID"]))
											$bFound = true;
									}

									if (!$bFound)
									{
										$arMessages[] = array("ERROR", "Tasks item is not found by list.");
									}
									else
									{
										$arMessages[] = array("SUCCESS", "Tasks item was successfully found by list.");

										$bFound = false;
										$r = $e->GetById($itemId["XML_ID"]);
										$arMessages = array_merge($arMessages, $e->GetErrors());
										foreach ($r as $v)
										{
											if (($v["SUBJECT"] == "New TestFolderItem Name") && ($v["XML_ID"] == $itemId["XML_ID"]))
												$bFound = true;
										}

										if (!$bFound)
										{
											$arMessages[] = array("ERROR", "Tasks item is not found by id.");
										}
										else
										{
											$arMessages[] = array("SUCCESS", "Tasks item was successfully found by id.");
											$r = $e->Delete($itemId["XML_ID"]);
											if (!$r)
											{
												$arMessages[] = array("ERROR", "Tasks item deletion error.");
											}
											else
											{
												$arMessages[] = array("SUCCESS", "Tasks item was successfully deleted.");

												$bFound = false;
												$r = $e->GetList(
													array("Mailbox" => $mailbox, "FolderId" => $folderId["XML_ID"]),
													array("ItemShape" => "IdOnly")
												);
												$arMessages = array_merge($arMessages, $e->GetErrors());
												foreach ($r as $v)
													$bFound = true;

												if ($bFound)
												{
													$arMessages[] = array("ERROR", "Tasks folder should be empty.");
												}
												else
												{
													$arMessages[] = array("SUCCESS", "Tasks folder is empty.");

													$r = $e->DeleteFolder($folderId["XML_ID"]);
													$arMessages = array_merge($arMessages, $e->GetErrors());
													if ($r)
														$arMessages[] = array("SUCCESS", "Tasks folder was successfully deleted.");
													else
														$arMessages[] = array("ERROR", "Tasks folder deletion error.");
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}

		return $arMessages;
	}
}
?>