Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions lib/Horde/ActiveSync/Collections.php
Original file line number Diff line number Diff line change
Expand Up @@ -1232,10 +1232,14 @@ public function pollForChanges($heartbeat, $interval, array $options = [])
$rw_check_countdown = 5;
if ($this->_as->provisioning != Horde_ActiveSync::PROVISIONING_NONE) {
$rwstatus = $this->_as->state->getDeviceRWStatus($this->_as->device->id, true);
$accountOnlyStatus = $this->_as->state->getAccountOnlyRWStatus(
$this->_as->device->id,
true
);
if ($rwstatus == Horde_ActiveSync::RWSTATUS_PENDING
|| $rwstatus == Horde_ActiveSync::RWSTATUS_WIPED
|| $rwstatus == Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_PENDING
|| $rwstatus == Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_WIPED) {
|| $accountOnlyStatus == Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_PENDING
|| $accountOnlyStatus == Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_WIPED) {
return self::COLLECTION_ERR_FOLDERSYNC_REQUIRED;
}
}
Expand Down
13 changes: 11 additions & 2 deletions lib/Horde/ActiveSync/Request/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,21 @@ public function checkPolicyKey($sentKey, $requestType = null)

// Did we request a remote wipe?
$rwStatus = $this->_state->getDeviceRWStatus($this->_device->id);
if ($rwStatus == Horde_ActiveSync::RWSTATUS_PENDING
|| $rwStatus == Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_PENDING) {
if ($rwStatus == Horde_ActiveSync::RWSTATUS_PENDING) {
$this->_requireProvisionWbxml($requestType, Horde_ActiveSync_Status::REMOTEWIPE_REQUESTED);
return false;
}

$accountOnlyStatus = $this->_state->getAccountOnlyRWStatus($this->_device->id);
if ($accountOnlyStatus == Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_PENDING) {
$this->_requireProvisionWbxml($requestType, Horde_ActiveSync_Status::REMOTEWIPE_REQUESTED);
return false;
}
if ($accountOnlyStatus == Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_WIPED) {
$this->_requireProvisionWbxml($requestType, Horde_ActiveSync_Status::DEVICE_NOT_PROVISIONED);
return false;
}

// Validate the stored key against the device key, honoring
// the value of _provisioning.
if ((empty($storedKey) || $storedKey != $sentKey)
Expand Down
61 changes: 43 additions & 18 deletions lib/Horde/ActiveSync/Request/Provision.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,23 @@ protected function _handle()
return $this->_globalError(self::STATUS_PROTERROR);
}
if ($status == self::STATUS_CLIENT_SUCCESS) {
if ($wipeTag === Horde_ActiveSync::PROVISION_ACCOUNTONLYREMOTEWIPE) {
return $this->_completeAccountOnlyWipeAck();
}
$this->_state->setDeviceRWStatus(
$this->_devId,
$wipeTag === Horde_ActiveSync::PROVISION_ACCOUNTONLYREMOTEWIPE
? Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_WIPED
: Horde_ActiveSync::RWSTATUS_WIPED
$this->_device->id,
Horde_ActiveSync::RWSTATUS_WIPED
);
}
$policytype = Horde_ActiveSync::POLICYTYPE_XML;
} else {
if ($this->_state->getAccountOnlyRWStatus($this->_device->id)
== Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_WIPED) {
$this->_sendNoProvisionNeededResponse(self::STATUS_SUCCESS);

return true;
}

if ($deviceinfo = $this->_handleSettings()) {
$deviceinfo['version'] = $this->_device->version;
$this->_device->setDeviceProperties($deviceinfo);
Expand Down Expand Up @@ -177,11 +185,12 @@ protected function _handle()
return $this->_globalError(self::STATUS_PROTERROR);
}
if ($status == self::STATUS_CLIENT_SUCCESS) {
if ($wipeTag === Horde_ActiveSync::PROVISION_ACCOUNTONLYREMOTEWIPE) {
return $this->_completeAccountOnlyWipeAck();
}
$this->_state->setDeviceRWStatus(
$this->_device->id,
$wipeTag === Horde_ActiveSync::PROVISION_ACCOUNTONLYREMOTEWIPE
? Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_WIPED
: Horde_ActiveSync::RWSTATUS_WIPED
Horde_ActiveSync::RWSTATUS_WIPED
);
}
}
Expand Down Expand Up @@ -282,30 +291,46 @@ protected function _handle()
// Remote wipe if requested.
$rwstatus = $this->_state->getDeviceRWStatus($this->_device->id);
if ($rwstatus == Horde_ActiveSync::RWSTATUS_PENDING
|| $rwstatus == Horde_ActiveSync::RWSTATUS_WIPED
|| $rwstatus == Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_PENDING
|| $rwstatus == Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_WIPED) {
$isAccountOnly = ($rwstatus == Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_PENDING
|| $rwstatus == Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_WIPED);
|| $rwstatus == Horde_ActiveSync::RWSTATUS_WIPED) {
$this->_encoder->startTag(
$isAccountOnly
? Horde_ActiveSync::PROVISION_ACCOUNTONLYREMOTEWIPE
: Horde_ActiveSync::PROVISION_REMOTEWIPE,
Horde_ActiveSync::PROVISION_REMOTEWIPE,
false,
true
);
$this->_state->setDeviceRWStatus(
$this->_device->id,
$isAccountOnly
? Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_WIPED
: Horde_ActiveSync::RWSTATUS_WIPED
Horde_ActiveSync::RWSTATUS_WIPED
);
} elseif ($this->_state->getAccountOnlyRWStatus($this->_device->id)
== Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_PENDING) {
$this->_encoder->startTag(
Horde_ActiveSync::PROVISION_ACCOUNTONLYREMOTEWIPE,
false,
true
);
}
$this->_encoder->endTag(); //provision

return true;
}

/**
* Finalize a successful account-only remote wipe acknowledgment.
*
* @return boolean
*/
protected function _completeAccountOnlyWipeAck()
{
$this->_state->setAccountOnlyRWStatus(
$this->_device->id,
$this->_device->user,
Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_WIPED
);
$this->_sendNoProvisionNeededResponse(self::STATUS_SUCCESS);

return true;
}

/**
* Send a WBXML response to the output stream indicating that no
* provision requests are necessary.
Expand Down
41 changes: 40 additions & 1 deletion lib/Horde/ActiveSync/State/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,32 @@ public function getDeviceRWStatus($devId, $refresh = false)
return $this->_deviceInfo->rwstatus;
}

/**
* Obtain the account-only remote wipe status for the loaded device user.
*
* @param string $devId The device id.
* @param boolean $refresh If true, reload from storage.
*
* @return integer
*/
public function getAccountOnlyRWStatus($devId, $refresh = false)
{
if (empty($this->_deviceInfo) || $this->_deviceInfo->id != $devId) {
throw new Horde_ActiveSync_Exception('Device not loaded.');
}

if ($refresh) {
$this->loadDeviceInfo(
$this->_deviceInfo->id,
$this->_deviceInfo->user,
['force' => true]
);
}

return $this->_deviceInfo->accountOnlyRwstatus
?? Horde_ActiveSync::RWSTATUS_NA;
}

/**
* Set the backend driver
* (should really only be called by a backend object when passing this
Expand Down Expand Up @@ -1317,12 +1343,25 @@ abstract public function resetAllPolicyKeys();
* Set a new remotewipe status for the device
*
* @param string $devId The device id.
* @param string $status A Horde_ActiveSync::RWSTATUS_* constant.
* @param string $status A device-level Horde_ActiveSync::RWSTATUS_*
* constant. Account-only wipe statuses must be set
* via setAccountOnlyRWStatus().
*
* @throws Horde_ActiveSync_Exception
*/
abstract public function setDeviceRWStatus($devId, $status);

/**
* Set account-only remote wipe status for a device user.
*
* @param string $devId The device id.
* @param string $user The device user.
* @param string $status A Horde_ActiveSync::RWSTATUS_* constant.
*
* @throws Horde_ActiveSync_Exception
*/
abstract public function setAccountOnlyRWStatus($devId, $user, $status);

/**
* Obtain the device object.
*
Expand Down
62 changes: 58 additions & 4 deletions lib/Horde/ActiveSync/State/Mongo.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ class Horde_ActiveSync_State_Mongo extends Horde_ActiveSync_State_Base implement
public const DEVICE_USER = 'device_user';
public const DEVICE_USERS_USER = 'users.device_user';
public const DEVICE_USERS_POLICYKEY = 'users.device_policykey';
public const DEVICE_ACCOUNTONLY_RWSTATUS = 'device_accountonly_rwstatus';
public const DEVICE_USERS_ACCOUNTONLY_RWSTATUS = 'users.device_accountonly_rwstatus';
public const DEVICE_POLICYKEY = 'device_policykey';

/**
Expand Down Expand Up @@ -1120,6 +1122,8 @@ public function loadDeviceInfo($devId, $user = null, $params = [])
foreach ($device_data['users'] as $user_entry) {
if ($user_entry[self::DEVICE_USER] == $user) {
$device['policykey'] = $user_entry[self::DEVICE_POLICYKEY];
$device['accountOnlyRwstatus'] = $user_entry[self::DEVICE_ACCOUNTONLY_RWSTATUS]
?? Horde_ActiveSync::RWSTATUS_NA;
break;
}
}
Expand Down Expand Up @@ -1347,6 +1351,13 @@ public function resetAllPolicyKeys()
*/
public function setDeviceRWStatus($devId, $status)
{
if ($status == Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_PENDING
|| $status == Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_WIPED) {
throw new Horde_ActiveSync_Exception(
'Account-only remote wipe status must be set via setAccountOnlyRWStatus().'
);
}

$query = [self::MONGO_ID => $devId];
$new_data = [self::DEVICE_RWSTATUS => $status];
$update = ['$set' => $new_data];
Expand All @@ -1357,8 +1368,7 @@ public function setDeviceRWStatus($devId, $status)
throw new Horde_ActiveSync_Exception($e);
}

if ($status == Horde_ActiveSync::RWSTATUS_PENDING
|| $status == Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_PENDING) {
if ($status == Horde_ActiveSync::RWSTATUS_PENDING) {
$new_data[self::DEVICE_USERS_POLICYKEY] = 0;
Comment thread
TDannhauer marked this conversation as resolved.
$cursor = $this->_db->selectCollection(self::COLLECTION_DEVICE)
->find($query, ['users' => true]);
Expand All @@ -1379,6 +1389,52 @@ public function setDeviceRWStatus($devId, $status)
}
}

/**
* Set account-only remote wipe status for a device user.
*
* @param string $devId The device id.
* @param string $user The device user.
* @param string $status A Horde_ActiveSync::RWSTATUS_* constant.
*
* @throws Horde_ActiveSync_Exception
*/
public function setAccountOnlyRWStatus($devId, $user, $status)
{
$query = [
self::MONGO_ID => $devId,
self::DEVICE_USERS_USER => $user,
];
$update = [
'$set' => [
self::DEVICE_USERS_ACCOUNTONLY_RWSTATUS => $status,
],
];
try {
$this->_db->selectCollection(self::COLLECTION_DEVICE)->update($query, $update);
} catch (Exception $e) {
$this->_logger->err($e->getMessage());
throw new Horde_ActiveSync_Exception($e);
}

if ($status == Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_PENDING) {
try {
$this->_db->selectCollection(self::COLLECTION_DEVICE)->update(
$query,
['$set' => [self::DEVICE_USERS_POLICYKEY => 0]]
);
} catch (Exception $e) {
$this->_logger->err($e->getMessage());
throw new Horde_ActiveSync_Exception($e);
}
}

if (!empty($this->_deviceInfo)
&& $this->_deviceInfo->id == $devId
&& $this->_deviceInfo->user == $user) {
$this->_deviceInfo->accountOnlyRwstatus = $status;
}
}

/**
* Reset the sync state for this device, for the specified collection.
*
Expand Down Expand Up @@ -1518,8 +1574,6 @@ public function removeState(array $options)
'$or' => [
[self::DEVICE_RWSTATUS => Horde_ActiveSync::RWSTATUS_PENDING],
[self::DEVICE_RWSTATUS => Horde_ActiveSync::RWSTATUS_WIPED],
[self::DEVICE_RWSTATUS => Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_PENDING],
[self::DEVICE_RWSTATUS => Horde_ActiveSync::RWSTATUS_ACCOUNTONLY_WIPED],
],
];
try {
Expand Down
Loading
Loading