/**
  * tear down tests
  */
 protected function tearDown()
 {
     parent::tearDown();
     if (!$this->_transactionId) {
         Syncroton_Registry::getDeviceBackend()->delete($this->_device->id);
     }
 }
Example #2
0
 public function __construct($userId, CakeRequest $request = null, $body = null)
 {
     if (Syncroton_Registry::isRegistered('loggerBackend')) {
         $this->_logger = Syncroton_Registry::get('loggerBackend');
     }
     $this->_userId = $userId;
     $this->_request = $request instanceof CakeRequest ? $request : new CakeRequest();
     $this->_body = $body !== null ? $body : fopen('php://input', 'r');
     $this->_deviceBackend = Syncroton_Registry::getDeviceBackend();
 }
    /**
     * test xml generation for IPhone
     */
    public function testSetDeviceInformation()
    {
        // delete folder created above
        $doc = new DOMDocument();
        $doc->loadXML('<?xml version="1.0" encoding="utf-8"?>
			<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
			<Settings xmlns="uri:Settings"><DeviceInformation><Set><Model>iPhone</Model><IMEI>086465r87697</IMEI></Set></DeviceInformation></Settings>');
        $folderDelete = new Syncroton_Command_Settings($doc, $this->_device, null);
        $folderDelete->handle();
        $responseDoc = $folderDelete->getResponse();
        #$responseDoc->formatOutput = true; echo $responseDoc->saveXML();
        $xpath = new DomXPath($responseDoc);
        $xpath->registerNamespace('Settings', 'uri:Settings');
        $nodes = $xpath->query('//Settings:Settings/Settings:Status');
        $this->assertEquals(1, $nodes->length, $responseDoc->saveXML());
        $this->assertEquals(Syncroton_Command_Settings::STATUS_SUCCESS, $nodes->item(0)->nodeValue, $responseDoc->saveXML());
        $updatedDevice = Syncroton_Registry::getDeviceBackend()->get($this->_device->id);
        $this->assertEquals('086465r87697', $updatedDevice->imei);
    }
 /**
  * (non-PHPdoc)
  * @see ActiveSync/ActiveSync_TestCase::setUp()
  */
 protected function setUp()
 {
     parent::setUp();
     // speed up tests
     Syncroton_Registry::set(Syncroton_Registry::PING_TIMEOUT, 1);
     Syncroton_Registry::set(Syncroton_Registry::QUIET_TIME, 1);
     $this->_setGeoData = Addressbook_Controller_Contact::getInstance()->setGeoDataForContacts(FALSE);
     Syncroton_Registry::setDatabase(Tinebase_Core::getDb());
     Syncroton_Registry::setTransactionManager(Tinebase_TransactionManager::getInstance());
     Syncroton_Registry::set(Syncroton_Registry::DEVICEBACKEND, new Syncroton_Backend_Device(Tinebase_Core::getDb(), SQL_TABLE_PREFIX . 'acsync_'));
     Syncroton_Registry::set(Syncroton_Registry::FOLDERBACKEND, new Syncroton_Backend_Folder(Tinebase_Core::getDb(), SQL_TABLE_PREFIX . 'acsync_'));
     Syncroton_Registry::set(Syncroton_Registry::SYNCSTATEBACKEND, new Syncroton_Backend_SyncState(Tinebase_Core::getDb(), SQL_TABLE_PREFIX . 'acsync_'));
     Syncroton_Registry::set(Syncroton_Registry::CONTENTSTATEBACKEND, new Syncroton_Backend_Content(Tinebase_Core::getDb(), SQL_TABLE_PREFIX . 'acsync_'));
     Syncroton_Registry::set('loggerBackend', Tinebase_Core::getLogger());
     Syncroton_Registry::setContactsDataClass('Addressbook_Frontend_ActiveSync');
     Syncroton_Registry::setCalendarDataClass('Calendar_Frontend_ActiveSync');
     Syncroton_Registry::setEmailDataClass('Felamimail_Frontend_ActiveSync');
     Syncroton_Registry::setTasksDataClass('Tasks_Frontend_ActiveSync');
     $this->_device = Syncroton_Registry::getDeviceBackend()->create(ActiveSync_TestCase::getTestDevice());
 }
Example #5
0
 /**
  * (non-PHPdoc)
  * @see Syncroton/Syncroton_TestCase::setUp()
  */
 public function setUp()
 {
     Syncroton_Registry::setDatabase(ConnectionManager::getDataSource('test'));
     Syncroton_Registry::getTransactionManager()->startTransaction(Syncroton_Registry::getDatabase());
     Syncroton_Registry::set('loggerBackend', new Syncroton_Log('lil_active_sync'));
     try {
         $device = Syncroton_Registry::getDeviceBackend()->getUserDevice('1234', 'iphone-abcd');
         Syncroton_Registry::getDeviceBackend()->delete($device);
     } catch (Syncroton_Exception_NotFound $e) {
         // do nothing => it's ok
     }
     require_once dirname(dirname(__FILE__)) . DS . 'Backend' . DS . 'DeviceTest.php';
     $this->_device = Syncroton_Registry::getDeviceBackend()->create(DeviceTest::getTestDevice());
     Syncroton_Registry::setContactsDataClass('Syncroton_Data_Contacts');
     Syncroton_Registry::setCalendarDataClass('Syncroton_Data_Calendar');
     Syncroton_Registry::setEmailDataClass('Syncroton_Data_Email');
     Syncroton_Registry::setTasksDataClass('Syncroton_Data_Tasks');
     Syncroton_Registry::setGALDataClass('Syncroton_Data_Contacts');
     // speed up tests
     Syncroton_Registry::set(Syncroton_Registry::PING_TIMEOUT, 1);
     Syncroton_Registry::set(Syncroton_Registry::QUIET_TIME, 1);
 }
Example #6
0
 /**
  * process the XML file and add, change, delete or fetches data
  */
 public function handle()
 {
     // input xml
     $requestXML = simplexml_import_dom($this->_mergeSyncRequest($this->_requestBody, $this->_device));
     if (!isset($requestXML->Collections)) {
         $this->_outputDom->documentElement->appendChild($this->_outputDom->createElementNS('uri:AirSync', 'Status', self::STATUS_RESEND_FULL_XML));
         return $this->_outputDom;
     }
     if (isset($requestXML->HeartbeatInterval)) {
         $this->_heartbeatInterval = (int) $requestXML->HeartbeatInterval;
     } elseif (isset($requestXML->Wait)) {
         $this->_heartbeatInterval = (int) $requestXML->Wait * 60;
     }
     $this->_globalWindowSize = isset($requestXML->WindowSize) ? (int) $requestXML->WindowSize : 100;
     if (!$this->_globalWindowSize || $this->_globalWindowSize > 512) {
         $this->_globalWindowSize = 512;
     }
     if ($this->_globalWindowSize > $this->_maxWindowSize) {
         $this->_globalWindowSize = $this->_maxWindowSize;
     }
     // load options from lastsynccollection
     $lastSyncCollection = array('options' => array());
     if (!empty($this->_device->lastsynccollection)) {
         $lastSyncCollection = json_decode($this->_device->lastsynccollection, true);
         if (!array_key_exists('options', $lastSyncCollection) || !is_array($lastSyncCollection['options'])) {
             $lastSyncCollection['options'] = array();
         }
     }
     $collections = array();
     foreach ($requestXML->Collections->Collection as $xmlCollection) {
         $collectionId = (string) $xmlCollection->CollectionId;
         $collections[$collectionId] = new Syncroton_Model_SyncCollection($xmlCollection);
         // do we have to reuse the options from the previous request?
         if (!isset($xmlCollection->Options) && array_key_exists($collectionId, $lastSyncCollection['options'])) {
             $collections[$collectionId]->options = $lastSyncCollection['options'][$collectionId];
             if ($this->_logger instanceof Syncroton_Log) {
                 $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " restored options to " . print_r($collections[$collectionId]->options, TRUE));
             }
         }
         // store current options for next Sync command request (sticky options)
         $lastSyncCollection['options'][$collectionId] = $collections[$collectionId]->options;
     }
     $this->_device->lastsynccollection = json_encode($lastSyncCollection);
     if ($this->_device->isDirty()) {
         Syncroton_Registry::getDeviceBackend()->update($this->_device);
     }
     foreach ($collections as $collectionData) {
         // has the folder been synchronised to the device already
         try {
             $collectionData->folder = $this->_folderBackend->getFolder($this->_device, $collectionData->collectionId);
         } catch (Syncroton_Exception_NotFound $senf) {
             if ($this->_logger instanceof Syncroton_Log) {
                 $this->_logger->warning(__METHOD__ . '::' . __LINE__ . " folder {$collectionData->collectionId} not found");
             }
             // trigger INVALID_SYNCKEY instead of OBJECT_NOTFOUND when synckey is higher than 0
             // to avoid a syncloop for the iPhone
             if ($collectionData->syncKey > 0) {
                 $collectionData->folder = new Syncroton_Model_Folder(array('deviceId' => $this->_device, 'serverId' => $collectionData->collectionId));
             }
             $this->_collections[$collectionData->collectionId] = $collectionData;
             continue;
         }
         if ($this->_logger instanceof Syncroton_Log) {
             $this->_logger->info(__METHOD__ . '::' . __LINE__ . " SyncKey is {$collectionData->syncKey} Class: {$collectionData->folder->class} CollectionId: {$collectionData->collectionId}");
         }
         // initial synckey
         if ($collectionData->syncKey === 0) {
             if ($this->_logger instanceof Syncroton_Log) {
                 $this->_logger->info(__METHOD__ . '::' . __LINE__ . " initial client synckey 0 provided");
             }
             // reset sync state for this folder
             $this->_syncStateBackend->resetState($this->_device, $collectionData->folder);
             $this->_contentStateBackend->resetState($this->_device, $collectionData->folder);
             $collectionData->syncState = new Syncroton_Model_SyncState(array('device_id' => $this->_device, 'counter' => 0, 'type' => $collectionData->folder, 'lastsync' => $this->_syncTimeStamp));
             $this->_collections[$collectionData->collectionId] = $collectionData;
             continue;
         }
         // check for invalid sycnkey
         if (($collectionData->syncState = $this->_syncStateBackend->validate($this->_device, $collectionData->folder, $collectionData->syncKey)) === false) {
             if ($this->_logger instanceof Syncroton_Log) {
                 $this->_logger->warning(__METHOD__ . '::' . __LINE__ . " invalid synckey {$collectionData->syncKey} provided");
             }
             // reset sync state for this folder
             $this->_syncStateBackend->resetState($this->_device, $collectionData->folder);
             $this->_contentStateBackend->resetState($this->_device, $collectionData->folder);
             $this->_collections[$collectionData->collectionId] = $collectionData;
             continue;
         }
         $dataController = Syncroton_Data_Factory::factory($collectionData->folder->class, $this->_device, $this->_syncTimeStamp);
         switch ($collectionData->folder->class) {
             case Syncroton_Data_Factory::CLASS_CALENDAR:
                 $dataClass = 'Syncroton_Model_Event';
                 break;
             case Syncroton_Data_Factory::CLASS_CONTACTS:
                 $dataClass = 'Syncroton_Model_Contact';
                 break;
             case Syncroton_Data_Factory::CLASS_EMAIL:
                 $dataClass = 'Syncroton_Model_Email';
                 break;
             case Syncroton_Data_Factory::CLASS_NOTES:
                 $dataClass = 'Syncroton_Model_Note';
                 break;
             case Syncroton_Data_Factory::CLASS_TASKS:
                 $dataClass = 'Syncroton_Model_Task';
                 break;
             default:
                 throw new Syncroton_Exception_UnexpectedValue('invalid class provided');
                 break;
         }
         $clientModifications = array('added' => array(), 'changed' => array(), 'deleted' => array(), 'forceAdd' => array(), 'forceChange' => array(), 'toBeFetched' => array());
         // handle incoming data
         if ($collectionData->hasClientAdds()) {
             $adds = $collectionData->getClientAdds();
             if ($this->_logger instanceof Syncroton_Log) {
                 $this->_logger->info(__METHOD__ . '::' . __LINE__ . " found " . count($adds) . " entries to be added to server");
             }
             foreach ($adds as $add) {
                 if ($this->_logger instanceof Syncroton_Log) {
                     $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " add entry with clientId " . (string) $add->ClientId);
                 }
                 try {
                     if ($this->_logger instanceof Syncroton_Log) {
                         $this->_logger->info(__METHOD__ . '::' . __LINE__ . " adding entry as new");
                     }
                     $serverId = $dataController->createEntry($collectionData->collectionId, new $dataClass($add->ApplicationData));
                     $clientModifications['added'][$serverId] = array('clientId' => (string) $add->ClientId, 'serverId' => $serverId, 'status' => self::STATUS_SUCCESS, 'contentState' => $this->_contentStateBackend->create(new Syncroton_Model_Content(array('device_id' => $this->_device, 'folder_id' => $collectionData->folder, 'contentid' => $serverId, 'creation_time' => $this->_syncTimeStamp, 'creation_synckey' => $collectionData->syncKey + 1))));
                 } catch (Exception $e) {
                     if ($this->_logger instanceof Syncroton_Log) {
                         $this->_logger->warning(__METHOD__ . '::' . __LINE__ . " failed to add entry " . $e->getMessage());
                     }
                     $clientModifications['added'][] = array('clientId' => (string) $add->ClientId, 'status' => self::STATUS_SERVER_ERROR);
                 }
             }
         }
         // handle changes, but only if not first sync
         if ($collectionData->syncKey > 1 && $collectionData->hasClientChanges()) {
             $changes = $collectionData->getClientChanges();
             if ($this->_logger instanceof Syncroton_Log) {
                 $this->_logger->info(__METHOD__ . '::' . __LINE__ . " found " . count($changes) . " entries to be updated on server");
             }
             foreach ($changes as $change) {
                 $serverId = (string) $change->ServerId;
                 try {
                     $dataController->updateEntry($collectionData->collectionId, $serverId, new $dataClass($change->ApplicationData));
                     $clientModifications['changed'][$serverId] = self::STATUS_SUCCESS;
                 } catch (Syncroton_Exception_AccessDenied $e) {
                     $clientModifications['changed'][$serverId] = self::STATUS_CONFLICT_MATCHING_THE_CLIENT_AND_SERVER_OBJECT;
                     $clientModifications['forceChange'][$serverId] = $serverId;
                 } catch (Syncroton_Exception_NotFound $e) {
                     // entry does not exist anymore, will get deleted automaticaly
                     $clientModifications['changed'][$serverId] = self::STATUS_OBJECT_NOT_FOUND;
                 } catch (Exception $e) {
                     if ($this->_logger instanceof Syncroton_Log) {
                         $this->_logger->warning(__METHOD__ . '::' . __LINE__ . " failed to update entry " . $e);
                     }
                     // something went wrong while trying to update the entry
                     $clientModifications['changed'][$serverId] = self::STATUS_SERVER_ERROR;
                 }
             }
         }
         // handle deletes, but only if not first sync
         if ($collectionData->hasClientDeletes()) {
             $deletes = $collectionData->getClientDeletes();
             if ($this->_logger instanceof Syncroton_Log) {
                 $this->_logger->info(__METHOD__ . '::' . __LINE__ . " found " . count($deletes) . " entries to be deleted on server");
             }
             foreach ($deletes as $delete) {
                 $serverId = (string) $delete->ServerId;
                 try {
                     // check if we have sent this entry to the phone
                     $state = $this->_contentStateBackend->getContentState($this->_device, $collectionData->folder, $serverId);
                     try {
                         $dataController->deleteEntry($collectionData->collectionId, $serverId, $collectionData);
                     } catch (Syncroton_Exception_NotFound $e) {
                         if ($this->_logger instanceof Syncroton_Log) {
                             $this->_logger->crit(__METHOD__ . '::' . __LINE__ . ' tried to delete entry ' . $serverId . ' but entry was not found');
                         }
                     } catch (Syncroton_Exception $e) {
                         if ($this->_logger instanceof Syncroton_Log) {
                             $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' tried to delete entry ' . $serverId . ' but a error occured: ' . $e->getMessage());
                         }
                         $clientModifications['forceAdd'][$serverId] = $serverId;
                     }
                     $this->_contentStateBackend->delete($state);
                 } catch (Syncroton_Exception_NotFound $senf) {
                     if ($this->_logger instanceof Syncroton_Log) {
                         $this->_logger->info(__METHOD__ . '::' . __LINE__ . ' ' . $serverId . ' should have been removed from client already');
                     }
                     // should we send a special status???
                     //$collectionData->deleted[$serverId] = self::STATUS_SUCCESS;
                 }
                 $clientModifications['deleted'][$serverId] = self::STATUS_SUCCESS;
             }
         }
         // handle fetches, but only if not first sync
         if ($collectionData->syncKey > 1 && $collectionData->hasClientFetches()) {
             // the default value for GetChanges is 1. If the phone don't want the changes it must set GetChanges to 0
             // some prevoius versions of iOS did not set GetChanges to 0 for fetches. Let's enforce getChanges to false here.
             $collectionData->getChanges = false;
             $fetches = $collectionData->getClientFetches();
             if ($this->_logger instanceof Syncroton_Log) {
                 $this->_logger->info(__METHOD__ . '::' . __LINE__ . " found " . count($fetches) . " entries to be fetched from server");
             }
             $toBeFecthed = array();
             foreach ($fetches as $fetch) {
                 $serverId = (string) $fetch->ServerId;
                 $toBeFetched[$serverId] = $serverId;
             }
             $collectionData->toBeFetched = $toBeFetched;
         }
         $this->_collections[$collectionData->collectionId] = $collectionData;
         $this->_modifications[$collectionData->collectionId] = $clientModifications;
     }
 }
 /**
  * return active device
  * 
  * @param string $_deviceType
  * @return ActiveSync_Model_Device
  */
 protected function _getDevice($_deviceType)
 {
     if (!isset($this->objects['devices'][$_deviceType])) {
         $this->objects['devices'][$_deviceType] = Syncroton_Registry::getDeviceBackend()->create(ActiveSync_TestCase::getTestDevice($_deviceType));
     }
     return $this->objects['devices'][$_deviceType];
 }
 /**
  * addnote method
  *
  * @return void
  */
 public function addnote()
 {
     App::uses('ConnectionManager', 'Model');
     Syncroton_Registry::setDatabase(ConnectionManager::getDataSource('default'));
     Syncroton_Registry::setNotesDataClass('Syncroton_Data_Notes');
     Syncroton_Registry::set('loggerBackend', new Syncroton_Log('lil_active_sync2'));
     $device = Syncroton_Registry::getDeviceBackend()->getUserDevice('miha', 'ApplC33JKLWDDTWD');
     Syncroton_Data_Factory::factory(Syncroton_Data_Factory::CLASS_NOTES, $device, new DateTime(null, new DateTimeZone('utc')))->createEntry('', new Syncroton_Model_Note(array('subject' => 'Second note')));
     return new CakeResponse(array('body' => 'success'));
 }
    /**
     * test xml generation for IPhone
     */
    public function testRemoteWipeStep2()
    {
        $this->testRemoteWipeStep1();
        $doc = new DOMDocument();
        $doc->loadXML('<?xml version="1.0" encoding="utf-8"?>
			<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
			<Provision xmlns="uri:Provision"><RemoteWipe><Status>1</Status></RemoteWipe></Provision>');
        $provision = new Syncroton_Command_Provision($doc, $this->_device, $this->_device->policykey);
        $provision->handle();
        $responseDoc = $provision->getResponse();
        #$responseDoc->formatOutput = true; echo $responseDoc->saveXML();
        $this->_device = Syncroton_Registry::getDeviceBackend()->get($this->_device);
        $this->assertEquals(Syncroton_Command_Provision::REMOTEWIPE_CONFIRMED, $this->_device->remotewipe);
        $xpath = new DomXPath($responseDoc);
        $xpath->registerNamespace('Provision', 'uri:Provision');
        $nodes = $xpath->query('//Provision:Provision/Provision:Status');
        $this->assertEquals(1, $nodes->length, $responseDoc->saveXML());
        $this->assertEquals(Syncroton_Command_FolderSync::STATUS_SUCCESS, $nodes->item(0)->nodeValue, $responseDoc->saveXML());
        $nodes = $xpath->query('//Provision:Provision/Provision:RemoteWipe');
        $this->assertEquals(1, $nodes->length, $responseDoc->saveXML());
    }
Example #10
0
 public function testDeleteEntry()
 {
     try {
         $device = Syncroton_Registry::getDeviceBackend()->getUserDevice('1234', 'iphone-abcd');
         Syncroton_Registry::getDeviceBackend()->delete($device);
     } catch (Syncroton_Exception_NotFound $e) {
         // do nothing => it's ok
     }
     require_once dirname(dirname(__FILE__)) . DS . 'Backend' . DS . 'DeviceTest.php';
     $device = Syncroton_Registry::getDeviceBackend()->create(DeviceTest::getTestDevice(Syncroton_Model_Device::TYPE_IPHONE));
     $dataController = Syncroton_Data_Factory::factory(Syncroton_Data_Factory::CLASS_CONTACTS, $device, new DateTime(null, new DateTimeZone('UTC')));
     $entries = $dataController->getServerEntries('addressbookFolderId', null);
     $dataController->deleteEntry('addressbookFolderId', $entries[0], array());
     $newEntries = $dataController->getServerEntries('addressbookFolderId', null);
     $this->assertArrayNotHasKey($entries[0], $newEntries);
 }
Example #11
0
 /**
  * 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;
             }
         }
     }
 }