/** * Returns the current AS Device in it's StateObject * If the data was not changed, it returns false (no need to update any data) * * @access public * @return array/boolean */ public function GetData() { if (!$this->changed) { return false; } // device was updated $this->lastupdatetime = time(); unset($this->ignoredMessageIds); if (!isset(self::$loadedData) || !isset(self::$loadedData->devices) || !is_array(self::$loadedData->devices)) { self::$loadedData = new StateObject(); $devices = array(); } else { $devices = self::$loadedData->devices; } $devices[$this->deviceuser] = $this; // check if RWStatus has to be updated so it can be updated for other users on same device if (isset($this->wipeStatus) && $this->wipeStatus > SYNC_PROVISION_RWSTATUS_OK) { foreach ($devices as $user => $asuserdata) { if ($user == $this->deviceuser) { continue; } if (isset($this->wipeStatus)) { $asuserdata->wipeStatus = $this->wipeStatus; } if (isset($this->wipeRequestBy)) { $asuserdata->wipeRequestBy = $this->wipeRequestBy; } if (isset($this->wipeRequestOn)) { $asuserdata->wipeRequestOn = $this->wipeRequestOn; } if (isset($this->wipeActionOn)) { $asuserdata->wipeActionOn = $this->wipeActionOn; } $devices[$user] = $asuserdata; ZLog::Write(LOGLEVEL_DEBUG, sprintf("Updated remote wipe status for user '%s' on the same device", $user)); } } self::$loadedData->devices = $devices; return self::$loadedData; }
/** * Marks a all folders synchronized to a device for re-synchronization * If no user is set all user which are synchronized for a device are marked for re-synchronization. * If no device id is set all devices of that user are marked for re-synchronization. * If no user and no device are set then ALL DEVICES are marked for resynchronization (use with care!). * * @param string $user (opt) user of the device * @param string $devid (opt)device id which should be wiped * * @return boolean * @access public */ public static function ResyncDevice($user, $devid = false) { // search for target devices if ($devid === false) { $devicesIds = ZPush::GetStateMachine()->GetAllDevices($user); ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZPushAdmin::ResyncDevice(): all '%d' devices for user '%s' found to be re-synchronized", count($devicesIds), $user)); foreach ($devicesIds as $deviceid) { if (!self::ResyncDevice($user, $deviceid)) { ZLog::Write(LOGLEVEL_ERROR, sprintf("ZPushAdmin::ResyncDevice(): wipe devices failed for device '%s' of user '%s'. Aborting", $deviceid, $user)); return false; } } } else { // get devicedata try { $devicedata = ZPush::GetStateMachine()->GetState($devid, IStateMachine::DEVICEDATA); } catch (StateNotFoundException $e) { ZLog::Write(LOGLEVEL_ERROR, sprintf("ZPushAdmin::ResyncDevice(): state for device '%s' can not be found", $devid)); return false; } // loop through all users which currently use this device if ($user === false && $devicedata instanceof StateObject && isset($devicedata->devices) && is_array($devicedata->devices) && count($devicedata->devices) > 1) { foreach (array_keys($devicedata) as $aUser) { if (!self::ResyncDevice($aUser, $devid)) { ZLog::Write(LOGLEVEL_ERROR, sprintf("ZPushAdmin::ResyncDevice(): re-synchronization failed for device '%s' of user '%s'. Aborting", $devid, $aUser)); return false; } } } // load device data $device = new ASDevice($devid, ASDevice::UNDEFINED, $user, ASDevice::UNDEFINED); try { $device->SetData($devicedata, false); if ($device->IsNewDevice()) { ZLog::Write(LOGLEVEL_ERROR, sprintf("ZPushAdmin::ResyncDevice(): data of user '%s' not synchronized on device '%s'. Aborting.", $user, $devid)); return false; } // delete all uuids foreach ($device->GetAllFolderIds() as $folderid) { StateManager::UnLinkState($device, $folderid); } // remove hierarchcache StateManager::UnLinkState($device, false); ZPush::GetStateMachine()->SetState($device->GetData(), $devid, IStateMachine::DEVICEDATA); ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZPushAdmin::ResyncDevice(): all folders synchronized to device '%s' of user '%s' marked to be re-synchronized.", $devid, $user)); } catch (StateNotFoundException $e) { ZLog::Write(LOGLEVEL_ERROR, sprintf("ZPushAdmin::ResyncDevice(): state for device '%s' of user '%s' can not be found or saved", $devid, $user)); return false; } } return true; }
/** * UnLinks all states from a folder id * Old states are removed assisting the StateMachine to get rid of old data. * The UUID is then removed from the device * * @param ASDevice $device * @param string $folderid * @param boolean $removeFromDevice indicates if the device should be * notified that the state was removed * @param boolean $retrieveUUIDFromDevice indicates if the UUID should be retrieved from * device. If not true this parameter will be used as UUID. * * @access public * @return boolean */ public static function UnLinkState(&$device, $folderid, $removeFromDevice = true, $retrieveUUIDFromDevice = true) { if ($retrieveUUIDFromDevice === true) { $savedUuid = $device->GetFolderUUID($folderid); } else { $savedUuid = $retrieveUUIDFromDevice; } if ($savedUuid) { ZLog::Write(LOGLEVEL_DEBUG, sprintf("StateManager::UnLinkState('%s'): saved state '%s' will be deleted.", $folderid, $savedUuid)); ZPush::GetStateMachine()->CleanStates($device->GetDeviceId(), IStateMachine::DEFTYPE, $savedUuid, self::FIXEDHIERARCHYCOUNTER * 2); ZPush::GetStateMachine()->CleanStates($device->GetDeviceId(), IStateMachine::FOLDERDATA, $savedUuid); // CPO ZPush::GetStateMachine()->CleanStates($device->GetDeviceId(), IStateMachine::FAILSAVE, $savedUuid, self::FIXEDHIERARCHYCOUNTER * 2); ZPush::GetStateMachine()->CleanStates($device->GetDeviceId(), IStateMachine::BACKENDSTORAGE, $savedUuid, self::FIXEDHIERARCHYCOUNTER * 2); // remove all messages which could not be synched before $device->RemoveIgnoredMessage($folderid, false); if ($folderid === false && $savedUuid !== false) { ZPush::GetStateMachine()->CleanStates($device->GetDeviceId(), IStateMachine::HIERARCHY, $savedUuid, self::FIXEDHIERARCHYCOUNTER * 2); } } // delete this id from the uuid cache if ($removeFromDevice) { return $device->SetFolderUUID(false, $folderid); } else { return true; } }
/** * Fixes states of the user linking to the states * and removes all obsolete states * * @return boolean * @access public */ public static function FixStatesUserToStatesLinking() { $processed = 0; $deleted = 0; $devices = ZPush::GetStateMachine()->GetAllDevices(false); ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZPushAdmin::FixStatesUserToStatesLinking(): found %d devices", count($devices))); foreach ($devices as $devid) { try { // we work on device level $devicedata = ZPush::GetStateMachine()->GetState($devid, IStateMachine::DEVICEDATA); $knownUuids = array(); // get all known UUIDs for this device foreach (self::ListUsers($devid) as $username) { $device = new ASDevice($devid, ASDevice::UNDEFINED, $username, ASDevice::UNDEFINED); $device->SetData($devicedata, false); // get all known uuids of this device $folders = $device->GetAllFolderIds(); // add a "false" folder id so the hierarchy UUID is retrieved $folders[] = false; foreach ($folders as $folderid) { $uuid = $device->GetFolderUUID($folderid); if ($uuid) { $knownUuids[] = $uuid; } } } } catch (StateNotFoundException $e) { } // get all uuids for deviceid from statemachine $existingStates = ZPush::GetStateMachine()->GetAllStatesForDevice($devid); $processed = count($existingStates); ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZPushAdmin::FixStatesUserToStatesLinking(): found %d valid uuids and %d states for device device '%s'", count($knownUuids), $processed, $devid)); // remove states for all unknown uuids foreach ($existingStates as $obsoleteState) { if ($obsoleteState['type'] === IStateMachine::DEVICEDATA) { continue; } if (!in_array($obsoleteState['uuid'], $knownUuids)) { if (is_numeric($obsoleteState['counter'])) { $obsoleteState['counter']++; } ZPush::GetStateMachine()->CleanStates($devid, $obsoleteState['type'], $obsoleteState['uuid'], $obsoleteState['counter']); $deleted++; } } } return array($processed, $deleted); }