From cc70594e3720832a90b4d838bc59da76a1928cc0 Mon Sep 17 00:00:00 2001 From: Lars Kneschke Date: Thu, 17 Oct 2013 12:54:08 +0200 Subject: [PATCH] Implemented basic support for Autodiscover command Change-Id: I57c1bffa249608578129e7680a0cfb816e0b2343 --- autodiscover.php | 188 ++++++++++++++++++ build.xml | 9 + lib/Syncroton/Command/AutoDiscover.php | 126 ++++++++++++ lib/Syncroton/Command/Wbxml.php | 4 +- tests/Syncroton/Command/AutoDiscoverTests.php | 61 ++++++ 5 files changed, 386 insertions(+), 2 deletions(-) create mode 100644 autodiscover.php create mode 100644 lib/Syncroton/Command/AutoDiscover.php create mode 100644 tests/Syncroton/Command/AutoDiscoverTests.php diff --git a/autodiscover.php b/autodiscover.php new file mode 100644 index 0000000..fbfaf0c --- /dev/null +++ b/autodiscover.php @@ -0,0 +1,188 @@ + + */ + +define('SYNCURL', 'https://sync.example.com/Microsoft-Server-ActiveSync'); + +/** + * exception for data not found + * + * @package Syncroton + * @subpackage Exception + */ +class Syncroton_Exception extends Exception +{ +} + +/** + * interface for all Syncroton command classes + * + * @package Syncroton + * @subpackage Command + */ +interface Syncroton_Command_ICommand +{ + /** + * constructor of this class + * + * @param resource $_requestBody + * @param Syncroton_Model_IDevice $_device + * @param string $_policyKey + */ + public function __construct($_requestBody, Syncroton_Model_IDevice $_device, $_policyKey); + + /** + * process the incoming data + */ + public function handle(); + + /** + * create the response + */ + public function getResponse(); + + /** + * return headers of command + * + * @return array list of headers + */ + public function getHeaders(); +} + +/** + * class to handle AutoDiscover command + * + * @package Syncroton + * @subpackage Command + */ +class Syncroton_Command_AutoDiscover implements Syncroton_Command_ICommand +{ + /** + * the domDocucment containing the xml request from the client + * + * @var DOMDocument + */ + protected $requestBody; + + protected $emailAddress; + + public $mobileSyncUrl; + + public $certEnrollUrl; + + /** + * constructor of this class + * + * @param DOMDocument $_requestBody + * @param Syncroton_Model_IDevice $_device + * @param string $_policyKey + */ + public function __construct($requestBody, Syncroton_Model_IDevice $device = null, $policyKey = null) + { + $this->requestBody = $requestBody; + } + + /** + * process the incoming data + */ + public function handle() + { + $xpath = new DomXPath($this->requestBody); + $xpath->registerNamespace('2006', 'http://schemas.microsoft.com/exchange/autodiscover/mobilesync/requestschema/2006'); + + $nodes = $xpath->query('//2006:Autodiscover/2006:Request/2006:EMailAddress'); + if ($nodes->length === 0) { + throw new Syncroton_Exception(); + } + + $this->emailAddress = $nodes->item(0)->nodeValue; + } + + /** + * create the response + * + * @return DOMDocument + */ + public function getResponse() + { + // Creates an instance of the DOMImplementation class + $imp = new DOMImplementation(); + + // Creates a DOMDocument instance + $document = $imp->createDocument("http://schemas.microsoft.com/exchange/autodiscover/mobilesync/requestschema/2006", 'Autodiscover'); + $document->xmlVersion = '1.0'; + $document->encoding = 'UTF-8'; + $document->formatOutput = false; + + $response = $document->documentElement->appendChild($document->createElement('Response')); + + $user = $response->appendChild($document->createElement('User')); + $user->appendChild($document->createElement('EMailAddress', $this->emailAddress)); + + $settings = $document->createElement('Settings'); + + if (!empty($this->mobileSyncUrl)) { + $server = $document->createElement('Server'); + + $server->appendChild($document->createElement('Type', 'MobileSync')); + + $server->appendChild($document->createElement('Url', $this->mobileSyncUrl)); + $server->appendChild($document->createElement('Name', $this->mobileSyncUrl)); + + $settings->appendChild($server); + } + + if (!empty($this->certEnrollUrl)) { + $server = $document->createElement('Server'); + + $server->appendChild($document->createElement('Type', 'CertEnroll')); + + $server->appendChild($document->createElement('Url', $this->certEnrollUrl)); + $server->appendChild($document->createElement('Name')); + $server->appendChild($document->createElement('ServerData', 'CertEnrollTemplate')); + + $settings->appendChild($server); + } + + if ($settings->hasChildNodes()) { + $action = $response->appendChild($document->createElement('Action')); + $action->appendChild($settings); + } + + return $document; + } + + /** + * return headers of command + * + * @return array list of headers + */ + public function getHeaders() + { + return array( + 'Content-Type' => 'text/xml;charset=utf-8' + ); + } +} + +$document = new DOMDocument(); +$document->loadXML(file_get_contents('php://input')); + +$autoDiscover = new Syncroton_Command_AutoDiscover($document); +$autoDiscover->mobileSyncUrl = SYNCURL; + +$autoDiscover->handle(); + +$response = $autoDiscover->getResponse(); + +foreach ($autoDiscover->getHeaders() as $name => $value) { + header($name . ': ' . $value); +} + +echo $response->saveXML(); diff --git a/build.xml b/build.xml index 40ac3de..daa93b1 100644 --- a/build.xml +++ b/build.xml @@ -18,6 +18,15 @@ + + + + + + + + + diff --git a/lib/Syncroton/Command/AutoDiscover.php b/lib/Syncroton/Command/AutoDiscover.php new file mode 100644 index 0000000..c2415a1 --- /dev/null +++ b/lib/Syncroton/Command/AutoDiscover.php @@ -0,0 +1,126 @@ + + */ + +/** + * class to handle AutoDiscover command + * + * @package Syncroton + * @subpackage Command + */ +class Syncroton_Command_AutoDiscover implements Syncroton_Command_ICommand +{ + /** + * the domDocucment containing the xml request from the client + * + * @var DOMDocument + */ + protected $requestBody; + + protected $emailAddress; + + public $mobileSyncUrl; + + public $certEnrollUrl; + + /** + * constructor of this class + * + * @param DOMDocument $_requestBody + * @param Syncroton_Model_IDevice $_device + * @param string $_policyKey + */ + public function __construct($requestBody, Syncroton_Model_IDevice $device = null, $policyKey = null) + { + $this->requestBody = $requestBody; + } + + /** + * process the incoming data + */ + public function handle() + { + $xpath = new DomXPath($this->requestBody); + $xpath->registerNamespace('2006', 'http://schemas.microsoft.com/exchange/autodiscover/mobilesync/requestschema/2006'); + + $nodes = $xpath->query('//2006:Autodiscover/2006:Request/2006:EMailAddress'); + if ($nodes->length === 0) { + throw new Syncroton_Exception(); + } + + $this->emailAddress = $nodes->item(0)->nodeValue; + } + + /** + * create the response + * + * @return DOMDocument + */ + public function getResponse() + { + // Creates an instance of the DOMImplementation class + $imp = new DOMImplementation(); + + // Creates a DOMDocument instance + $document = $imp->createDocument("http://schemas.microsoft.com/exchange/autodiscover/mobilesync/requestschema/2006", 'Autodiscover'); + $document->xmlVersion = '1.0'; + $document->encoding = 'UTF-8'; + $document->formatOutput = false; + + $response = $document->documentElement->appendChild($document->createElement('Response')); + + $user = $response->appendChild($document->createElement('User')); + $user->appendChild($document->createElement('EMailAddress', $this->emailAddress)); + + $settings = $document->createElement('Settings'); + + if (!empty($this->mobileSyncUrl)) { + $server = $document->createElement('Server'); + + $server->appendChild($document->createElement('Type', 'MobileSync')); + + $server->appendChild($document->createElement('Url', $this->mobileSyncUrl)); + $server->appendChild($document->createElement('Name', $this->mobileSyncUrl)); + + $settings->appendChild($server); + } + + if (!empty($this->certEnrollUrl)) { + $server = $document->createElement('Server'); + + $server->appendChild($document->createElement('Type', 'CertEnroll')); + + $server->appendChild($document->createElement('Url', $this->certEnrollUrl)); + $server->appendChild($document->createElement('Name')); + $server->appendChild($document->createElement('ServerData', 'CertEnrollTemplate')); + + $settings->appendChild($server); + } + + if ($settings->hasChildNodes()) { + $action = $response->appendChild($document->createElement('Action')); + $action->appendChild($settings); + } + + return $document; + } + + /** + * return headers of command + * + * @return array list of headers + */ + public function getHeaders() + { + return array( + 'Content-Type' => 'text/xml;charset=utf-8' + ); + } +} diff --git a/lib/Syncroton/Command/Wbxml.php b/lib/Syncroton/Command/Wbxml.php index a252d25..feb20a8 100644 --- a/lib/Syncroton/Command/Wbxml.php +++ b/lib/Syncroton/Command/Wbxml.php @@ -61,14 +61,14 @@ abstract class Syncroton_Command_Wbxml implements Syncroton_Command_ICommand * @var DOMDocument */ protected $_outputDom; - + /** * the domDocucment containing the xml request from the client * * @var DOMDocument */ protected $_requestBody; - + /** * the default namespace * diff --git a/tests/Syncroton/Command/AutoDiscoverTests.php b/tests/Syncroton/Command/AutoDiscoverTests.php new file mode 100644 index 0000000..e86ce69 --- /dev/null +++ b/tests/Syncroton/Command/AutoDiscoverTests.php @@ -0,0 +1,61 @@ + + */ + +/** + * class to test Syncroton_Command_AutoDiscover + * + * @package Syncroton + * @subpackage Tests + */ +class Syncroton_Command_AutoDiscoverTests extends PHPUnit_Framework_TestCase +{ + /** + * test creation of claendar folder + */ + public function testCreateCalendarFolder() + { + $doc = new DOMDocument(); + $doc->loadXML(' + + + chris@example.com + + http://schemas.microsoft.com/exchange/autodiscover/mobilesync/responseschema/2006 + + + + '); + + $autoDiscover = new Syncroton_Command_AutoDiscover($doc); + $autoDiscover->mobileSyncUrl = 'https://sync.example.com/Microsoft-Server-ActiveSync'; + $autoDiscover->certEnrollUrl = 'https://sync.example.com/CertEnroll'; + + $autoDiscover->handle(); + + $responseDoc = $autoDiscover->getResponse(); + #$responseDoc->formatOutput = true; echo $responseDoc->saveXML(); + + $xpath = new DomXPath($responseDoc); + $xpath->registerNamespace('2006', 'http://schemas.microsoft.com/exchange/autodiscover/mobilesync/requestschema/2006'); + + $nodes = $xpath->query('//2006:Autodiscover/Response/User'); + $this->assertEquals(1, $nodes->length, $responseDoc->saveXML()); + + $nodes = $xpath->query('//2006:Autodiscover/Response/Action'); + $this->assertEquals(1, $nodes->length, $responseDoc->saveXML()); + + $nodes = $xpath->query('//2006:Autodiscover/Response/Action/Settings'); + $this->assertEquals(1, $nodes->length, $responseDoc->saveXML()); + + $nodes = $xpath->query('//2006:Autodiscover/Response/Action/Settings/Server'); + $this->assertEquals(2, $nodes->length, $responseDoc->saveXML()); + } +}