/**
  * generate FolderUpdate response
  *
  * @todo currently we support only the main folder which contains all contacts/tasks/events/notes per class
  */
 public function getResponse($_keepSession = FALSE)
 {
     $folderUpdate = $this->_outputDom->documentElement;
     if ($this->_syncKey > '0' && $this->_controller->validateSyncKey($this->_device, $this->_syncKey, 'FolderSync') === false) {
         Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " INVALID synckey");
         $folderUpdate->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', ActiveSync_Command_FolderSync::STATUS_INVALID_SYNC_KEY));
     } else {
         $newSyncKey = $this->_syncKey + 1;
         // create xml output
         $folderUpdate->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', ActiveSync_Command_FolderSync::STATUS_SUCCESS));
         $folderUpdate->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'SyncKey', $newSyncKey));
         $this->_controller->updateSyncKey($this->_device, $newSyncKey, $this->_syncTimeStamp, 'FolderSync');
     }
     return $this->_outputDom;
 }
 /**
  * the singleton pattern
  *
  * @return ActiveSync_Controller
  */
 public static function getInstance()
 {
     if (self::$_instance === NULL) {
         self::$_instance = new ActiveSync_Controller();
     }
     return self::$_instance;
 }
 /**
  * reset sync
  * 
  * @param Zend_Console_Getopt $opts
  */
 public function resetSync(Zend_Console_Getopt $opts)
 {
     $this->_addOutputLogWriter(6);
     $args = $this->_parseArgs($opts, array('user'));
     if ($args['user'] != Tinebase_Core::getUser()->accountLoginName && !$this->_checkAdminRight()) {
         return 1;
     }
     $possibleClasses = array('Calendar', 'Contacts', 'Tasks', 'Email');
     $classesToReset = isset($args['collection']) && in_array($args['collection'], $possibleClasses) ? array($args['collection']) : $possibleClasses;
     $result = ActiveSync_Controller::getInstance()->resetSyncForUser($args['user'], $classesToReset);
     return $result ? 0 : 1;
 }
Example #4
0
 /**
  * process the XML file and add, change, delete or fetches data 
  *
  */
 public function handle()
 {
     $controller = ActiveSync_Controller::getInstance();
     $xml = simplexml_import_dom($this->_inputDom);
     if (isset($xml->DeviceInformation->Set)) {
         $this->_deviceInformationSet = true;
         $this->_device->model = (string) $xml->DeviceInformation->Set->Model;
         $this->_device->imei = (string) $xml->DeviceInformation->Set->IMEI;
         $this->_device->friendlyname = (string) $xml->DeviceInformation->Set->FriendlyName;
         $this->_device->os = (string) $xml->DeviceInformation->Set->OS;
         $this->_device->oslanguage = (string) $xml->DeviceInformation->Set->OSLanguage;
         $this->_device->phonenumber = (string) $xml->DeviceInformation->Set->PhoneNumber;
         $this->_device = $controller->updateDevice($this->_device);
     }
     if (isset($xml->UserInformation->Get)) {
         $this->_userInformationRequested = true;
     }
 }
Example #5
0
 /**
  * generate MoveItems response
  */
 public function getResponse()
 {
     $folderStateBackend = new ActiveSync_Backend_FolderState();
     $moves = $this->_outputDom->documentElement;
     foreach ($this->_moves as $move) {
         $response = $moves->appendChild($this->_outputDom->createElementNS('uri:Move', 'Response'));
         $response->appendChild($this->_outputDom->createElementNS('uri:Move', 'SrcMsgId', $move['srcMsgId']));
         try {
             $folder = $folderStateBackend->getByProperty($move['srcFldId'], 'folderid');
             $dataController = ActiveSync_Controller::dataFactory($folder->class, $this->_device, $this->_syncTimeStamp);
             $newId = $dataController->moveItem($move['srcFldId'], $move['srcMsgId'], $move['dstFldId']);
             $response->appendChild($this->_outputDom->createElementNS('uri:Move', 'Status', ActiveSync_Command_MoveItems::STATUS_SUCCESS));
             $response->appendChild($this->_outputDom->createElementNS('uri:Move', 'DstMsgId', $newId));
         } catch (Tinebase_Exception_NotFound $e) {
             $response->appendChild($this->_outputDom->createElementNS('uri:Move', 'Status', ActiveSync_Command_MoveItems::STATUS_INVALID_SOURCE));
         } catch (Exception $e) {
             $response->appendChild($this->_outputDom->createElementNS('uri:Move', 'Status', ActiveSync_Command_MoveItems::STATUS_INVALID_DESTINATION));
         }
     }
     return $this->_outputDom;
 }
Example #6
0
 /**
  * generate FolderSync response
  *
  * @todo currently we support only the main folder which contains all contacts/tasks/events/notes per class
  * 
  * @param boolean $_keepSession keep session active(don't logout user) when true
  */
 public function getResponse($_keepSession = FALSE)
 {
     $folderSync = $this->_outputDom->documentElement;
     if ($this->_syncKey > '0' && $this->_controller->validateSyncKey($this->_device, $this->_syncKey, 'FolderSync') === false) {
         Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " INVALID synckey provided");
         $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', self::STATUS_INVALID_SYNC_KEY));
     } else {
         $adds = array();
         $deletes = array();
         $count = 0;
         if ($this->_syncKey == 0) {
             $this->_folderStateBackend->resetState($this->_device);
         }
         foreach ($this->_classes as $class) {
             $dataController = ActiveSync_Controller::dataFactory($class, $this->_device, $this->_syncTimeStamp);
             try {
                 $folders = $dataController->getSupportedFolders();
             } catch (Exception $e) {
                 if (Tinebase_Core::isLogLevel(Zend_Log::CRIT)) {
                     Tinebase_Core::getLogger()->crit(__METHOD__ . '::' . __LINE__ . " failed to get folders for class {$class}. " . $e->getMessage());
                 }
                 if (Tinebase_Core::isLogLevel(Zend_Log::CRIT)) {
                     Tinebase_Core::getLogger()->crit(__METHOD__ . '::' . __LINE__ . " failed to get folders for class {$class}. " . $e->getTraceAsString());
                 }
                 continue;
             }
             if ($this->_syncKey == 0) {
                 foreach ($folders as $folderId => $folder) {
                     $adds[$class][$folderId] = $folder;
                     $count++;
                 }
             } else {
                 $allServerEntries = array_keys($folders);
                 $allClientEntries = $this->_folderStateBackend->getClientState($this->_device, $class);
                 // added entries
                 $serverDiff = array_diff($allServerEntries, $allClientEntries);
                 foreach ($serverDiff as $folderId) {
                     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " add {$class} {$folderId}");
                     }
                     $adds[$class][$folderId] = $folders[$folderId];
                     $count++;
                 }
                 // deleted entries
                 $serverDiff = array_diff($allClientEntries, $allServerEntries);
                 foreach ($serverDiff as $folderId) {
                     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " delete {$class} {$folderId}");
                     }
                     $deletes[$class][$folderId] = $folderId;
                     $count++;
                 }
             }
         }
         if ($count > 0) {
             $newSyncKey = $this->_syncKey + 1;
         } else {
             $newSyncKey = $this->_syncKey;
         }
         // create xml output
         $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', self::STATUS_SUCCESS));
         $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'SyncKey', $newSyncKey));
         $changes = $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Changes'));
         $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Count', $count));
         foreach ($adds as $class => $folders) {
             foreach ((array) $folders as $folder) {
                 $add = $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Add'));
                 $add->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'ServerId', $folder['folderId']));
                 $add->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'ParentId', $folder['parentId']));
                 $add->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'DisplayName', $folder['displayName']));
                 $add->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Type', $folder['type']));
                 $this->_addFolderState($class, $folder['folderId']);
                 if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                     Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " {$class} => " . $folder['folderId']);
                 }
             }
         }
         foreach ($deletes as $class => $folders) {
             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                 Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " {$class}");
             }
             foreach ((array) $folders as $folderId) {
                 $delete = $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Delete'));
                 $delete->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'ServerId', $folderId));
                 $this->_deleteFolderState($class, $folderId);
             }
         }
         $this->_controller->updateSyncKey($this->_device, $newSyncKey, $this->_syncTimeStamp, 'FolderSync');
     }
     return $this->_outputDom;
 }
 /**
  * generate ItemOperations response
  */
 public function getResponse()
 {
     // add aditional namespaces for contacts, tasks and email
     $this->_outputDom->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:Contacts', 'uri:Contacts');
     $this->_outputDom->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:Tasks', 'uri:Tasks');
     $this->_outputDom->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:Email', 'uri:Email');
     $this->_outputDom->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:Calendar', 'uri:Calendar');
     $this->_outputDom->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:AirSyncBase', 'uri:AirSyncBase');
     $this->_outputDom->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:AirSync', 'uri:AirSync');
     $folderStateBackend = new ActiveSync_Backend_FolderState();
     $itemOperations = $this->_outputDom->documentElement;
     $itemOperations->appendChild($this->_outputDom->createElementNS('uri:ItemOperations', 'Status', ActiveSync_Command_ItemOperations::STATUS_SUCCESS));
     $response = $itemOperations->appendChild($this->_outputDom->createElementNS('uri:ItemOperations', 'Response'));
     foreach ($this->_fetches as $fetch) {
         $fetchTag = $response->appendChild($this->_outputDom->createElementNS('uri:ItemOperations', 'Fetch'));
         try {
             $dataController = ActiveSync_Controller::dataFactory($fetch['store'], $this->_device, $this->_syncTimeStamp);
             if (isset($fetch['collectionId'])) {
                 $properties = $this->_outputDom->createElementNS('uri:ItemOperations', 'Properties');
                 $dataController->appendXML($properties, $fetch['collectionId'], $fetch['serverId'], $fetch, true);
                 $fetchTag->appendChild($this->_outputDom->createElementNS('uri:ItemOperations', 'Status', ActiveSync_Command_ItemOperations::STATUS_SUCCESS));
                 $fetchTag->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'CollectionId', $fetch['collectionId']));
                 $fetchTag->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'ServerId', $fetch['serverId']));
                 $fetchTag->appendChild($properties);
             } elseif (isset($fetch['fileReference'])) {
                 $properties = $this->_outputDom->createElementNS('uri:ItemOperations', 'Properties');
                 $dataController->appendFileReference($properties, $fetch['fileReference']);
                 $fetchTag->appendChild($this->_outputDom->createElementNS('uri:ItemOperations', 'Status', ActiveSync_Command_ItemOperations::STATUS_SUCCESS));
                 $fetchTag->appendChild($this->_outputDom->createElementNS('uri:AirSyncBase', 'FileReference', $fetch['fileReference']));
                 $fetchTag->appendChild($properties);
             }
         } catch (Tinebase_Exception_NotFound $e) {
             $response->appendChild($this->_outputDom->createElementNS('uri:ItemOperations', 'Status', ActiveSync_Command_ItemOperations::STATUS_ITEM_FAILED_CONVERSION));
         } catch (Exception $e) {
             $response->appendChild($this->_outputDom->createElementNS('uri:ItemOperations', 'Status', ActiveSync_Command_ItemOperations::STATUS_SERVER_ERROR));
         }
     }
     return $this->_outputDom;
 }
Example #8
0
 /**
  * process the XML file and add, change, delete or fetches data 
  *
  * @todo can we get rid of LIBXML_NOWARNING
  * @todo we need to stored the initial data for folders and lifetime as the phone is sending them only when they change
  * @return resource
  */
 public function handle()
 {
     $controller = ActiveSync_Controller::getInstance();
     $intervalStart = time();
     $status = self::STATUS_NO_CHANGES_FOUND;
     // the client does not send a wbxml document, if the Ping parameters did not change compared with the last request
     if ($this->_inputDom instanceof DOMDocument) {
         #$xml = simplexml_load_string($this->_inputDom->saveXML());
         $xml = new SimpleXMLElement($this->_inputDom->saveXML(), LIBXML_NOWARNING);
         $xml->registerXPathNamespace('Ping', 'Ping');
         if (isset($xml->HeartBeatInterval)) {
             $this->_device->pinglifetime = $xml->HeartBeatInterval;
         }
         if (isset($xml->Folders->Folder)) {
             foreach ($xml->Folders->Folder as $folderXml) {
                 #Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " folderType: " . print_r($folderXml, true));
                 #$folderBackend = $this->_backend->factory((string)$folderXml->Class);
                 try {
                     // does the folder exist?
                     #            $folderBackend->getFolder($folderXml->Id);
                     $folder = array('serverEntryId' => (string) $folderXml->Id, 'folderType' => (string) $folderXml->Class);
                     $folders[] = $folder;
                 } catch (Exception $e) {
                     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " " . $e->getMessage());
                     }
                     $status = self::STATUS_FOLDER_NOT_FOUND;
                     break;
                 }
             }
             $this->_device->pingfolder = serialize($folders);
         }
         $this->_device = $controller->updateDevice($this->_device);
     }
     $lifeTime = $this->_device->pinglifetime;
     Tinebase_Core::setExecutionLifeTime($lifeTime);
     $intervalEnd = $intervalStart + $lifeTime;
     $secondsLeft = $intervalEnd;
     $folders = unserialize($this->_device->pingfolder);
     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Folders to monitor({$lifeTime} / {$intervalStart} / {$intervalEnd} / {$status}): " . print_r($folders, true));
     }
     if ($status === self::STATUS_NO_CHANGES_FOUND) {
         $folderWithChanges = array();
         do {
             foreach ((array) $folders as $folder) {
                 $dataController = ActiveSync_Controller::dataFactory($folder['folderType'], $this->_device, $this->_syncTimeStamp);
                 #if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " " . print_r($folder, true));
                 try {
                     $syncState = $controller->getSyncState($this->_device, $folder['folderType'], $folder['serverEntryId']);
                     $count = $this->_getItemEstimate($dataController, $folder, $syncState->lastsync);
                 } catch (ActiveSync_Exception_SyncStateNotFound $e) {
                     // folder got never synchronized to client
                     if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) {
                         Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . " " . $e->getMessage());
                     }
                     if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
                         Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' syncstate not found. enforce sync for folder: ' . $folder['serverEntryId']);
                     }
                     $count = 1;
                 }
                 if ($count > 0) {
                     $folderWithChanges[] = array('serverEntryId' => $folder['serverEntryId'], 'folderType' => $folder['folderType']);
                     $status = self::STATUS_CHANGES_FOUND;
                 }
             }
             if ($status === self::STATUS_CHANGES_FOUND) {
                 break;
             }
             // another process synchronized data already
             if (isset($syncState) && $syncState->lastsync > $this->_syncTimeStamp) {
                 Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " terminate ping process. Some other process updated data already.");
                 break;
             }
             sleep(self::PING_TIMEOUT);
             $secondsLeft = $intervalEnd - time();
             //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " DeviceId: " . $this->_device->deviceid . " seconds left: " . $secondsLeft);
         } while ($secondsLeft > 0);
     }
     Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " DeviceId: " . $this->_device->deviceid . " Lifetime: {$lifeTime} SecondsLeft: {$secondsLeft} Status: {$status})");
     $ping = $this->_outputDom->documentElement;
     $ping->appendChild($this->_outputDom->createElementNS('uri:Ping', 'Status', $status));
     if ($status === self::STATUS_CHANGES_FOUND) {
         $folders = $ping->appendChild($this->_outputDom->createElementNS('uri:Ping', 'Folders'));
         foreach ($folderWithChanges as $changedFolder) {
             $folder = $folders->appendChild($this->_outputDom->createElementNS('uri:Ping', 'Folder', $changedFolder['serverEntryId']));
             #$folder->appendChild($this->_outputDom->createElementNS('uri:Ping', 'Id', $changedFolder['serverEntryId']));
             Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " DeviceId: " . $this->_device->deviceid . " changes in folder: " . $changedFolder['serverEntryId']);
         }
     }
 }
Example #9
0
 /**
  * delete contentstate (aka: forget that we have sent the entry to the client)
  *
  * @param string $_class the class from the xml
  * @param string $_collectionId the collection id from the xml
  * @param string $_contentId the Tine 2.0 id of the entry
  */
 protected function _markContentStateAsDeleted($_class, $_collectionId, $_contentId)
 {
     $contentState = new ActiveSync_Model_ContentState(array('device_id' => $this->_device->getId(), 'class' => $_class, 'collectionid' => $_collectionId, 'contentid' => $_contentId, 'creation_time' => $this->_syncTimeStamp));
     $this->_controller->markContentStateAsDeleted($contentState);
 }
 /**
  * force activesync calendar resync for iOS devices
  */
 public function update_11()
 {
     if (Tinebase_Application::getInstance()->isInstalled('ActiveSync')) {
         $deviceBackend = new ActiveSync_Backend_Device();
         $usersWithiPhones = $deviceBackend->search(new ActiveSync_Model_DeviceFilter(array('devicetype' => 'iphone')))->owner_id;
         $activeSyncController = ActiveSync_Controller::getInstance();
         foreach ($usersWithiPhones as $userId) {
             try {
                 $activeSyncController->resetSyncForUser($userId, 'Calendar');
             } catch (Exception $e) {
                 Tinebase_Exception::log($e, false);
             }
         }
     }
     $this->setApplicationVersion('Calendar', '8.12');
 }
Example #11
0
 /**
  * get application activesync controller
  * 
  * @param ActiveSync_Model_Device $_device
  */
 protected function _getController(ActiveSync_Model_Device $_device)
 {
     if ($this->_controller === null) {
         $this->_controller = ActiveSync_Controller::dataFactory($this->_class, $_device, new Tinebase_DateTime(null, null, 'de_DE'));
     }
     return $this->_controller;
 }
 /**
  * init registry
  */
 protected function _initializeRegistry()
 {
     ActiveSync_Controller::initSyncrotonRegistry();
     $applications = is_object(Tinebase_Core::getUser()) ? Tinebase_Core::getUser()->getApplications() : new Tinebase_Record_RecordSet('Tinebase_Model_Application');
     if ($applications->find('name', 'Addressbook')) {
         Syncroton_Registry::setContactsDataClass('Addressbook_Frontend_ActiveSync');
         Syncroton_Registry::setGALDataClass('Addressbook_Frontend_ActiveSync');
     }
     if ($applications->find('name', 'Calendar')) {
         Syncroton_Registry::setCalendarDataClass('Calendar_Frontend_ActiveSync');
     }
     if ($applications->find('name', 'Felamimail')) {
         Syncroton_Registry::setEmailDataClass('Felamimail_Frontend_ActiveSync');
     }
     if ($applications->find('name', 'Tasks')) {
         Syncroton_Registry::setTasksDataClass('Tasks_Frontend_ActiveSync');
     }
     Syncroton_Registry::set(Syncroton_Registry::DEFAULT_POLICY, ActiveSync_Config::getInstance()->get(ActiveSync_Config::DEFAULT_POLICY));
 }
Example #13
0
 protected function _acknowledgePolicy()
 {
     if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
         Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' acknowledge policy');
     }
     $newPolicyKey = $this->generatePolicyKey();
     $provision = $sync = $this->_outputDom->documentElement;
     $provision->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Status', 1));
     $policies = $provision->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Policies'));
     $policy = $policies->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Policy'));
     $policy->appendChild($this->_outputDom->createElementNS('uri:Provision', 'PolicyType', $this->_policyType));
     $policy->appendChild($this->_outputDom->createElementNS('uri:Provision', 'Status', 1));
     $policy->appendChild($this->_outputDom->createElementNS('uri:Provision', 'PolicyKey', $newPolicyKey));
     $this->_device->policykey = $newPolicyKey;
     ActiveSync_Controller::getInstance()->updateDevice($this->_device);
 }
 /**
  * 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());
         }
     }
 }
 /**
  * (non-PHPdoc)
  * @see ActiveSync_Command_Wbxml::getResponse()
  */
 public function getResponse()
 {
     $controller = ActiveSync_Controller::getInstance();
     $itemEstimate = $this->_outputDom->documentElement;
     foreach ($this->_collections as $collections) {
         foreach ($collections as $collectionData) {
             $response = $itemEstimate->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Response'));
             $dataController = ActiveSync_Controller::dataFactory($collectionData['class'], $this->_device, $this->_syncTimeStamp);
             try {
                 // does the folder exist?
                 $dataController->getFolder($collectionData['collectionId']);
                 $folderExists = true;
             } catch (ActiveSync_Exception_FolderNotFound $asefnf) {
                 $folderExists = false;
             }
             if ($folderExists !== true) {
                 Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . " folder does not exist");
                 $response->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Status', self::STATUS_INVALID_COLLECTION));
                 $collection = $response->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Collection'));
                 $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Class', $collectionData['class']));
                 $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'CollectionId', $collectionData['collectionId']));
                 $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Estimate', 0));
             } elseif ($collectionData['syncKeyValid'] !== true) {
                 Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . " invalid synckey {$collectionData['syncKey']} provided");
                 /*
                 * Android phones (and maybe others) don't take care about status 4(INVALID_SYNC_KEY)
                 * To solve the problem we always return status 1(SUCCESS) even the sync key is invalid with Estimate set to 1.
                 * This way the phone gets forced to sync. Handling invalid synckeys during sync command works without any problems.
                 * 
                    $response->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Status', self::STATUS_INVALID_SYNC_KEY));
                    $collection = $response->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Collection'));
                    $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Class', $collectionData['class']));
                    $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'CollectionId', $collectionData['collectionId']));  
                    $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Estimate', 0));
                 */
                 $response->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Status', self::STATUS_SUCCESS));
                 $collection = $response->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Collection'));
                 $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Class', $collectionData['class']));
                 $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'CollectionId', $collectionData['collectionId']));
                 $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Estimate', 1));
             } else {
                 $response->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Status', self::STATUS_SUCCESS));
                 $collection = $response->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Collection'));
                 $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Class', $collectionData['class']));
                 $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'CollectionId', $collectionData['collectionId']));
                 if ($collectionData['syncKey'] <= 1) {
                     // this is the first sync. in most cases there are data on the server.
                     $count = count($dataController->getServerEntries($collectionData['collectionId'], $collectionData['filterType']));
                 } else {
                     $count = $this->_getItemEstimate($dataController, $collectionData);
                 }
                 $collection->appendChild($this->_outputDom->createElementNS('uri:ItemEstimate', 'Estimate', $count));
             }
             // store current filter type
             $filter = new ActiveSync_Model_FolderStateFilter(array(array('field' => 'device_id', 'operator' => 'equals', 'value' => $this->_device->getId()), array('field' => 'class', 'operator' => 'equals', 'value' => $collectionData['class']), array('field' => 'folderid', 'operator' => 'equals', 'value' => $collectionData['collectionId'])));
             $folderState = $this->_folderStateBackend->search($filter)->getFirstRecord();
             // folderState can be NULL in case of not existing folder
             if ($folderState instanceof ActiveSync_Model_FolderState) {
                 $folderState->lastfiltertype = $collectionData['filterType'];
                 $this->_folderStateBackend->update($folderState);
             }
         }
     }
     return $this->_outputDom;
 }