/** * reset sync for user * * @param mixed $user * @param array|string $classesToReset * @return boolean */ public function resetSyncForUser($user, $classesToReset) { if (is_string($classesToReset)) { $classesToReset = array($classesToReset); } if (!$user instanceof Tinebase_Model_User) { try { $user = Tinebase_User::getInstance()->getFullUserById($user); } catch (Tinebase_Exception_NotFound $tenf) { $user = Tinebase_User::getInstance()->getUserByPropertyFromSqlBackend('accountLoginName', $user); } } if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) { Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Resetting sync for user ' . $user->accountDisplayName . ' collections: ' . print_r($classesToReset, true)); } self::initSyncrotonRegistry(); $devices = $this->_getDevicesForUser($user->getId()); foreach ($devices as $device) { if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) { Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Resetting device' . $device->friendlyname . ' / id: ' . $device->getId()); } foreach ($classesToReset as $class) { $folderToReset = $this->_getFoldersForDeviceAndClass($device, $class); if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) { Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Resetting ' . count($folderToReset) . ' folder(s) for class ' . $class); } foreach ($folderToReset as $folderState) { Syncroton_Registry::getSyncStateBackend()->resetState($device->getId(), $folderState->id); } } } return true; }
/** * test reponse with synckey 1 */ public function testGetFoldersSyncKey1() { $this->testGetFoldersSyncKey0(); // rewind back last sync timestamp $syncState = Syncroton_Registry::getSyncStateBackend()->getSyncState($this->_device, 'FolderSync'); $syncState->lastsync = new DateTime('2013-02-09 10:40:36', new DateTimeZone('utc')); $syncState = Syncroton_Registry::getSyncStateBackend()->update($syncState); $createdFolder = Syncroton_Data_Factory::factory(Syncroton_Data_Factory::CLASS_CONTACTS, $this->_device, new DateTime(null, new DateTimeZone('utc')))->createFolder(new Syncroton_Model_Folder(array('serverId' => 'addressbookFolderId2', 'parentId' => null, 'displayName' => 'User created Contacts Folder', 'type' => Syncroton_Command_FolderSync::FOLDERTYPE_CONTACT_USER_CREATED))); // update created folder to validate that created folders are not returned as changes folders Syncroton_Data_Factory::factory(Syncroton_Data_Factory::CLASS_CONTACTS, $this->_device, new DateTime(null, new DateTimeZone('utc')))->updateFolder($createdFolder); Syncroton_Data_Factory::factory(Syncroton_Data_Factory::CLASS_CONTACTS, $this->_device, new DateTime(null, new DateTimeZone('utc')))->updateFolder(new Syncroton_Model_Folder(array('serverId' => 'anotherAddressbookFolderId', 'parentId' => null, 'displayName' => 'User updated Contacts Folder', 'type' => Syncroton_Command_FolderSync::FOLDERTYPE_CONTACT_USER_CREATED))); $doc = new DOMDocument(); $doc->loadXML('<?xml version="1.0" encoding="utf-8"?' . '> <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> <FolderSync xmlns="uri:FolderHierarchy"><SyncKey>1</SyncKey></FolderSync>'); $folderSync = new Syncroton_Command_FolderSync($doc, $this->_device, $this->_device->policykey); $folderSync->handle(); $responseDoc = $folderSync->getResponse(); //$responseDoc->formatOutput = true; echo '<pre>'.htmlspecialchars($responseDoc->saveXML()).'</pre>'; die; $xpath = new DomXPath($responseDoc); $xpath->registerNamespace('FolderHierarchy', 'uri:FolderHierarchy'); $nodes = $xpath->query('//FolderHierarchy:FolderSync/FolderHierarchy:Status'); $this->assertEquals(1, $nodes->length, $responseDoc->saveXML()); $this->assertEquals(Syncroton_Command_FolderSync::STATUS_SUCCESS, $nodes->item(0)->nodeValue, $responseDoc->saveXML()); $nodes = $xpath->query('//FolderHierarchy:FolderSync/FolderHierarchy:SyncKey'); $this->assertEquals(1, $nodes->length, $responseDoc->saveXML()); $this->assertEquals(2, $nodes->item(0)->nodeValue, $responseDoc->saveXML()); $nodes = $xpath->query('//FolderHierarchy:FolderSync/FolderHierarchy:Changes/FolderHierarchy:Add'); $this->assertGreaterThanOrEqual(1, $nodes->length, $responseDoc->saveXML()); $nodes = $xpath->query('//FolderHierarchy:FolderSync/FolderHierarchy:Changes/FolderHierarchy:Add/FolderHierarchy:DisplayName'); $this->assertGreaterThanOrEqual('User created Contacts Folder', $nodes->item(0)->nodeValue, $responseDoc->saveXML()); $nodes = $xpath->query('//FolderHierarchy:FolderSync/FolderHierarchy:Changes/FolderHierarchy:Update'); $this->assertGreaterThanOrEqual(1, $nodes->length, $responseDoc->saveXML()); $nodes = $xpath->query('//FolderHierarchy:FolderSync/FolderHierarchy:Changes/FolderHierarchy:Update/FolderHierarchy:DisplayName'); $this->assertGreaterThanOrEqual('User updated Contacts Folder', $nodes->item(0)->nodeValue, $responseDoc->saveXML()); }
/** * */ public function testPingContacts() { // first do a foldersync $doc = new DOMDocument(); $doc->loadXML('<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> <FolderSync xmlns="uri:FolderHierarchy"><SyncKey>0</SyncKey></FolderSync>'); $folderSync = new Syncroton_Command_FolderSync($doc, $this->_device, $this->_device->policykey); $folderSync->handle(); $folderSync->getResponse(); // request initial synckey $doc = new DOMDocument(); $doc->loadXML('<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"><Collections><Collection><Class>Contacts</Class><SyncKey>0</SyncKey><CollectionId>addressbookFolderId</CollectionId><DeletesAsMoves/><GetChanges/><WindowSize>100</WindowSize><Options><AirSyncBase:BodyPreference><AirSyncBase:Type>1</AirSyncBase:Type><AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize></AirSyncBase:BodyPreference><Conflict>1</Conflict></Options></Collection></Collections></Sync>'); $sync = new Syncroton_Command_Sync($doc, $this->_device, $this->_device->policykey); $sync->handle(); $syncDoc = $sync->getResponse(); #$syncDoc->formatOutput = true; echo $syncDoc->saveXML(); // now do the first sync $doc = new DOMDocument(); $doc->loadXML('<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"><Collections><Collection><Class>Contacts</Class><SyncKey>1</SyncKey><CollectionId>addressbookFolderId</CollectionId><DeletesAsMoves/><GetChanges/><WindowSize>100</WindowSize><Options><AirSyncBase:BodyPreference><AirSyncBase:Type>1</AirSyncBase:Type><AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize></AirSyncBase:BodyPreference><Conflict>1</Conflict></Options></Collection></Collections></Sync>'); $sync = new Syncroton_Command_Sync($doc, $this->_device, $this->_device->policykey); $sync->handle(); $syncDoc = $sync->getResponse(); #$syncDoc->formatOutput = true; echo $syncDoc->saveXML(); $folder = Syncroton_Registry::getFolderBackend()->getFolder($this->_device, 'addressbookFolderId'); $oneSecondAgo = new DateTime(null, new DateTimeZone('utc')); $oneSecondAgo->modify('-1 second'); $tenSecondsAgo = new DateTime(null, new DateTimeZone('utc')); $tenSecondsAgo->modify('-10 second'); // update modify timeStamp of contact $dataController = Syncroton_Data_Factory::factory(Syncroton_Data_Factory::CLASS_CONTACTS, $this->_device, $oneSecondAgo); $contact = $dataController->getEntry(new Syncroton_Model_SyncCollection(array('folder' => 'addressbookFolderId')), 'contact1'); $dataController->updateEntry('addressbookFolderId', 'contact1', $contact); // turn back last sync time $syncState = Syncroton_Registry::getSyncStateBackend()->getSyncState($this->_device, $folder); $syncState->lastsync = $tenSecondsAgo; $syncState = Syncroton_Registry::getSyncStateBackend()->update($syncState); // and now we can start the ping request $doc = new DOMDocument(); $doc->loadXML('<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> <Ping xmlns="uri:Ping"><HeartBeatInterval>10</HeartBeatInterval><Folders><Folder><Id>addressbookFolderId</Id><Class>Contacts</Class></Folder></Folders></Ping>'); $search = new Syncroton_Command_Ping($doc, $this->_device, null); $search->handle(); $responseDoc = $search->getResponse(); #$responseDoc->formatOutput = true; echo $responseDoc->saveXML(); $xpath = new DomXPath($responseDoc); $xpath->registerNamespace('Ping', 'uri:Ping'); $nodes = $xpath->query('//Ping:Ping/Ping:Status'); $this->assertEquals(1, $nodes->length, $responseDoc->saveXML()); $this->assertEquals(Syncroton_Command_Ping::STATUS_CHANGES_FOUND, $nodes->item(0)->nodeValue, $responseDoc->saveXML()); $nodes = $xpath->query('//Ping:Ping/Ping:Folders/Ping:Folder'); $this->assertEquals(1, $nodes->length, $responseDoc->saveXML()); $this->assertEquals('addressbookFolderId', $nodes->item(0)->nodeValue, $responseDoc->saveXML()); }
/** * @return string the id of the newly created contact */ public function testConcurringSyncRequest() { $this->testSyncOfContacts(); $dataController = Syncroton_Data_Factory::factory(Syncroton_Data_Factory::CLASS_CONTACTS, $this->_device, new DateTime(null, new DateTimeZone('UTC'))); $entries = $dataController->getServerEntries('addressbookFolderId', null); // lets add one contact $doc = new DOMDocument(); $doc->loadXML('<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"><Collections> <Collection> <Class>Contacts</Class><SyncKey>4</SyncKey><CollectionId>addressbookFolderId</CollectionId><DeletesAsMoves/><GetChanges/><WindowSize>100</WindowSize> <Options><AirSyncBase:BodyPreference><AirSyncBase:Type>1</AirSyncBase:Type><AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize></AirSyncBase:BodyPreference><Conflict>1</Conflict></Options> <Commands><Add><ClientId>42</ClientId><ApplicationData></ApplicationData></Add></Commands> </Collection> </Collections></Sync>'); $sync = new Syncroton_Command_Sync($doc, $this->_device, $this->_device->policykey); $sync->handle(); $count = count($dataController->getServerEntries('addressbookFolderId', null)); $folder = Syncroton_Registry::getFolderBackend()->getFolder($this->_device, 'addressbookFolderId'); $syncState = Syncroton_Registry::getSyncStateBackend()->getSyncState($this->_device, $folder); $syncState->counter++; $syncState = Syncroton_Registry::getSyncStateBackend()->create($syncState); try { $syncDoc = $sync->getResponse(); $catchedException = false; //} catch (Zend_Db_Statement_Exception $zdse) { } catch (Exception $zdse) { $catchedException = true; } $this->assertTrue($catchedException); $this->assertGreaterThan(count($dataController->getServerEntries('addressbookFolderId', null)), $count); }
/** * testResetSync * * @see 0010584: CLI function for resetting sync on devices */ public function testResetSync() { $class = 'Calendar'; $this->testSyncOfEvents(); $result = ActiveSync_Controller::getInstance()->resetSyncForUser(Tinebase_Core::getUser()->accountLoginName, array($class)); $this->assertTrue($result); // check if synckey = 0 $folderState = Syncroton_Registry::getFolderBackend()->getFolderState($this->_device->id, $class); $this->assertTrue(count($folderState) > 0); foreach ($folderState as $folder) { try { Syncroton_Registry::getSyncStateBackend()->getSyncState($this->_device->id, $folder->id); $this->fail('should not find sync state for folder'); } catch (Exception $e) { $this->assertEquals('id not found', $e->getMessage()); } } }
/** * the constructor * * @param mixed $requestBody * @param Syncroton_Model_Device $device * @param array $requestParameters */ public function __construct($requestBody, Syncroton_Model_IDevice $device, $requestParameters) { $this->_requestBody = $requestBody; $this->_device = $device; $this->_requestParameters = $requestParameters; $this->_policyKey = $requestParameters['policyKey']; $this->_deviceBackend = Syncroton_Registry::getDeviceBackend(); $this->_folderBackend = Syncroton_Registry::getFolderBackend(); $this->_syncStateBackend = Syncroton_Registry::getSyncStateBackend(); $this->_contentStateBackend = Syncroton_Registry::getContentStateBackend(); $this->_policyBackend = Syncroton_Registry::getPolicyBackend(); if (Syncroton_Registry::isRegistered('loggerBackend')) { $this->_logger = Syncroton_Registry::get('loggerBackend'); } $this->_syncTimeStamp = new DateTime(null, new DateTimeZone('UTC')); // set default content type $this->_headers['Content-Type'] = 'application/vnd.ms-sync.wbxml'; if ($this->_logger instanceof Syncroton_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " sync timestamp: " . $this->_syncTimeStamp->format('Y-m-d H:i:s')); } if (isset($this->_defaultNameSpace) && isset($this->_documentElement)) { // Creates an instance of the DOMImplementation class $imp = new DOMImplementation(); // Creates a DOMDocumentType instance $dtd = $imp->createDocumentType('AirSync', "-//AIRSYNC//DTD AirSync//EN", "http://www.microsoft.com/"); // Creates a DOMDocument instance $this->_outputDom = $imp->createDocument($this->_defaultNameSpace, $this->_documentElement, $dtd); $this->_outputDom->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:Syncroton', 'uri:Syncroton'); $this->_outputDom->formatOutput = false; $this->_outputDom->encoding = 'utf-8'; } if ($this->_skipValidatePolicyKey != true) { if (!empty($this->_device->policyId)) { $policy = $this->_policyBackend->get($this->_device->policyId); if ((int) $policy->policyKey != (int) $this->_policyKey) { $this->_outputDom->documentElement->appendChild($this->_outputDom->createElementNS($this->_defaultNameSpace, 'Status', 142)); $sepn = new Syncroton_Exception_ProvisioningNeeded(); $sepn->domDocument = $this->_outputDom; throw $sepn; } // should we wipe the mobile phone? if ($this->_device->remotewipe >= Syncroton_Command_Provision::REMOTEWIPE_REQUESTED) { $this->_outputDom->documentElement->appendChild($this->_outputDom->createElementNS($this->_defaultNameSpace, 'Status', 140)); $sepn = new Syncroton_Exception_ProvisioningNeeded(); $sepn->domDocument = $this->_outputDom; throw $sepn; } } } }