From c3c08cf27fc07e8358e3615fadf693c0531b98c8 Mon Sep 17 00:00:00 2001 From: "Michael J. Rubinsky" Date: Wed, 12 May 2010 10:56:37 -0400 Subject: [PATCH] Allow each device to have mulitple user accounts SQL update script must be run. It's necessary to force the device to refresh - sorry, Jan ;). You might be able to get away with only refreshing one collection (like calendars), or even just pretend to edit the account settings and re-save them (which usually produces a foldersync request). Alternatively, you can manually add the username/device mapping if it's known to the users table, and add the username to the other new username fields in the map table and state table. to the database tables if they are known. --- framework/ActiveSync/lib/Horde/ActiveSync.php | 7 +- .../lib/Horde/ActiveSync/Driver/Horde.php | 2 +- .../lib/Horde/ActiveSync/Request/Base.php | 6 +- .../lib/Horde/ActiveSync/Request/Ping.php | 4 +- .../ActiveSync/lib/Horde/ActiveSync/State/Base.php | 69 ++++-- .../ActiveSync/lib/Horde/ActiveSync/State/File.php | 29 ++- .../lib/Horde/ActiveSync/State/History.php | 234 +++++++++++++-------- .../test/Horde/ActiveSync/HordeDriverTest.php | 16 +- horde/config/conf.xml | 2 + horde/lib/Prefs/Ui.php | 8 +- horde/scripts/sql/create.mssql.sql | 21 +- horde/scripts/sql/create.mysql.sql | 21 +- horde/scripts/sql/create.oci8.sql | 19 +- horde/scripts/sql/create.pgsql.sql | 19 +- horde/scripts/sql/create.sql | 19 +- horde/scripts/sql/create.sybase.sql | 24 ++- horde/scripts/sql/create.xml | 61 ++++-- horde/scripts/sql/horde_activesync.sql | 21 +- .../2010-05-11_horde_activesync_adduserkey.sql | 21 ++ horde/templates/prefs/activesync.html | 3 +- 20 files changed, 413 insertions(+), 193 deletions(-) create mode 100644 horde/scripts/upgrades/2010-05-11_horde_activesync_adduserkey.sql diff --git a/framework/ActiveSync/lib/Horde/ActiveSync.php b/framework/ActiveSync/lib/Horde/ActiveSync.php index fa68ee8f1..a49832370 100644 --- a/framework/ActiveSync/lib/Horde/ActiveSync.php +++ b/framework/ActiveSync/lib/Horde/ActiveSync.php @@ -850,7 +850,7 @@ class Horde_ActiveSync throw new Horde_ActiveSync_Exception('Device failed to send device id.'); } $state = $this->_driver->getStateObject(); - if (!empty($devId) && !$state->deviceExists($devId)) { + if (!empty($devId) && !$state->deviceExists($devId, $this->_driver->getUser())) { $get = $this->_request->getGetParams(); $device = new StdClass(); $device->userAgent = $this->_request->getHeader('User-Agent'); @@ -860,6 +860,9 @@ class Horde_ActiveSync $device->user = $this->_driver->getUser(); $device->id = $devId; $state->setDeviceInfo($device); + } elseif (!empty($devId)) { + // @TODO: Check if the empty check is necessary + $device = $state->getDeviceInfo($devId, $this->_driver->getUser()); } /* Load the request handler to handle the request */ @@ -871,7 +874,7 @@ class Horde_ActiveSync $this->_encoder, $this->_request, $this, - $devId, + $device, $this->_provisioning); $request->setLogger($this->_logger); diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde.php b/framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde.php index ade5cafb2..d10ed1564 100644 --- a/framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde.php +++ b/framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde.php @@ -478,7 +478,7 @@ class Horde_ActiveSync_Driver_Horde extends Horde_ActiveSync_Driver_Base * @param string $id The server's uid for the message if this is a * change to an existing message. * @param Horde_ActiveSync_Message_Base $message The activesync message - * @param stdClass $device The device information + * @param object $device The device information * * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#changeMessage($folderid, $id, $message) */ diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/Request/Base.php b/framework/ActiveSync/lib/Horde/ActiveSync/Request/Base.php index bea0b85c3..ca053aeea 100644 --- a/framework/ActiveSync/lib/Horde/ActiveSync/Request/Base.php +++ b/framework/ActiveSync/lib/Horde/ActiveSync/Request/Base.php @@ -110,7 +110,7 @@ abstract class Horde_ActiveSync_Request_Base Horde_ActiveSync_Wbxml_Encoder $encoder, Horde_Controller_Request_Http $request, Horde_ActiveSync $as, - $devId, + $device, $provisioning) { /* Backend driver */ @@ -133,7 +133,7 @@ abstract class Horde_ActiveSync_Request_Base $this->_state = &$driver->getStateObject(); /* Device info */ - $this->_device = $this->_state->getDeviceInfo($devId); + $this->_device = $device; } /** @@ -149,7 +149,7 @@ abstract class Horde_ActiveSync_Request_Base * header - which is against the specification. Check the user agent * for Android (maybe need version sniffing in the future) and set the * policykey to null for those devices. */ - $this->_device = $this->_state->getDeviceInfo($this->_device->id); + $this->_device = $this->_state->getDeviceInfo($this->_device->id, $this->_driver->getUser()); if (strpos($this->_device->userAgent, 'Android') !== false) { $sentKey = null; } diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/Request/Ping.php b/framework/ActiveSync/lib/Horde/ActiveSync/Request/Ping.php index dc9256547..e604dc21f 100644 --- a/framework/ActiveSync/lib/Horde/ActiveSync/Request/Ping.php +++ b/framework/ActiveSync/lib/Horde/ActiveSync/Request/Ping.php @@ -84,12 +84,12 @@ class Horde_ActiveSync_Request_Ping extends Horde_ActiveSync_Request_Base /* Initialize the state machine */ $this->_state = &$this->_driver->getStateObject(); - $this->_state->getDeviceInfo($this->_device->id); + $this->_state->getDeviceInfo($this->_device->id, $this->_driver->getUser()); /* See if we have an existing PING state. Need to do this here, before * we read in the PING request since the PING request is allowed to omit * sections if they have been sent previously */ - $collections = array_values($this->_state->initPingState($this->_device->id)); + $collections = array_values($this->_state->initPingState($this->_device)); $lifetime = $this->_checkHeartbeat($this->_state->getHeartbeatInterval()); /* Build the $collections array if we receive request from PIM */ diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/State/Base.php b/framework/ActiveSync/lib/Horde/ActiveSync/State/Base.php index 7c5a0d3fd..4e53c91fb 100644 --- a/framework/ActiveSync/lib/Horde/ActiveSync/State/Base.php +++ b/framework/ActiveSync/lib/Horde/ActiveSync/State/Base.php @@ -93,7 +93,7 @@ abstract class Horde_ActiveSync_State_Base /** * Device info cache * - * @var array + * @var object */ protected $_deviceInfo; @@ -123,6 +123,9 @@ abstract class Horde_ActiveSync_State_Base public function __construct($params = array()) { $this->_params = $params; + if (empty($params['logger'])) { + $this->_logger = new Horde_Support_Stub(); + } } /** @@ -167,8 +170,13 @@ abstract class Horde_ActiveSync_State_Base */ public function getPolicyKey($devId) { - $info = $this->getDeviceInfo($devId); - return $info->policykey; + //@TODO - combine _devId and _deviceInfo + /* See if we have it already */ + if (empty($this->_deviceInfo) || $this->_devId != $devId) { + throw new Horde_ActiveSync_Exception('Device not loaded.'); + } + + return $this->_deviceInfo->policykey; } /** @@ -180,8 +188,13 @@ abstract class Horde_ActiveSync_State_Base */ public function getDeviceRWStatus($devId) { - $info = $this->getDeviceInfo($devId); - return $info->rwstatus; + //@TODO - combine _devId and _deviceInfo + /* See if we have it already */ + if (empty($this->_deviceInfo) || $this->_devId != $devId) { + throw new Horde_ActiveSync_Exception('Device not loaded.'); + } + + return $this->_deviceInfo->rwstatus; } /** @@ -441,9 +454,9 @@ abstract class Horde_ActiveSync_State_Base /** * Load/initialize the ping state for the specified device. * - * @param string $devId + * @param object $device */ - abstract public function initPingState($devId); + abstract public function initPingState($device); /** * Load the ping state for the given device id @@ -476,6 +489,29 @@ abstract class Horde_ActiveSync_State_Base abstract public function updateState($type, $change, $origin = Horde_ActiveSync::CHANGE_ORIGIN_NA); /** + * Save folder data for a specific device. This is needed for BC with older + * activesync versions that use GETHIERARCHY requests to get the folder info + * instead of maintaining the folder state with FOLDERSYNC requests. + * + * @param object $device The device object + * @param array $folders The folder data + * + * @return boolean + * @throws Horde_ActiveSync_Exception + */ + abstract public function setFolderData($device, $folders); + + /** + * Get the folder data for a specific device + * + * @param object $device The device object + * @param string $class The folder class to fetch (Calendar, Contacts etc.) + * + * @return mixed Either an array of folder data || false + */ + abstract public function getFolderData($device, $class); + + /** * Get all items that have changed since the last sync time * * @param integer $flags @@ -517,27 +553,28 @@ abstract class Horde_ActiveSync_State_Base /** * Obtain the device object. * - * @param string $devId + * @param object $device + * @param string $user * * @return StdClass */ - abstract public function getDeviceInfo($devId); + abstract public function getDeviceInfo($device, $user); /** * Check that a given device id is known to the server. This is regardless * of Provisioning status. * - * @param string $devId + * @param string $devId The device id to check + * @param string $user The device should be owned by this user. * * @return boolean */ - abstract public function deviceExists($devId); + abstract public function deviceExists($devId, $user); /** * Set new device info * - * @param string $devId The device id. - * @param StdClass $data The device information + * @param object $device The device information * * @return boolean */ @@ -577,13 +614,11 @@ abstract class Horde_ActiveSync_State_Base abstract public function listDevices(); /** - * Get the last time a particular device issued a SYNC request. - * - * @param string $devId The device id + * Get the last time the currently loaded device issued a SYNC request. * * @return integer The timestamp of the last sync, regardless of collection * @throws Horde_ActiveSync_Exception */ - abstract public function getLastSyncTimestamp($devId); + abstract public function getLastSyncTimestamp(); } \ No newline at end of file diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/State/File.php b/framework/ActiveSync/lib/Horde/ActiveSync/State/File.php index 8752834d1..e5051d8f1 100644 --- a/framework/ActiveSync/lib/Horde/ActiveSync/State/File.php +++ b/framework/ActiveSync/lib/Horde/ActiveSync/State/File.php @@ -337,27 +337,21 @@ class Horde_ActiveSync_State_File extends Horde_ActiveSync_State_Base /** * Obtain the device object. * - * @param string $devId + * @param string $devId The device id to obtain + * @param string $user The user account to use * - * @return StdClass + * @return object The device info object + * @throws Horde_ActiveSync_Exception */ - public function getDeviceInfo($devId) + public function getDeviceInfo($devId, $user) { $this->_devId = $devId; - $file = $this->_stateDir . '/' . $this->_backend->getUser() . '/info-' . $devId; + $file = $this->_stateDir . '/' . $user . '/info-' . $devId; if (file_exists($file)) { return unserialize(file_get_contents($file)); + } else { + throw new Horde_ActiveSync_Exception('Device not found.'); } - - /* Default structure */ - $device = new StdClass(); - $device->policykey = 0; - $device->rwstatus = Horde_ActiveSync::RWSTATUS_NA; - $device->deviceType = ''; - $device->userAgent = ''; - $device->id = $devId; - - return $device; } /** @@ -381,12 +375,13 @@ class Horde_ActiveSync_State_File extends Horde_ActiveSync_State_Base * of Provisioning status. * * @param string $devId + * @param string $user * * @return boolean */ - public function deviceExists($devId) + public function deviceExists($devId, $user) { - return file_exists($this->_stateDir . '/' . $this->_backend->getUser() . '/info-' . $devId); + return file_exists($this->_stateDir . '/' . $user . '/info-' . $devId); } /** @@ -609,7 +604,7 @@ class Horde_ActiveSync_State_File extends Horde_ActiveSync_State_Base * @return integer The timestamp of the last sync, regardless of collection * @throws Horde_ActiveSync_Exception */ - public function getLastSyncTimestamp($devId) + public function getLastSyncTimestamp() { throw new Horde_ActiveSync_Exception('Not Implemented'); } diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/State/History.php b/framework/ActiveSync/lib/Horde/ActiveSync/State/History.php index 373390f5b..553bcc0db 100644 --- a/framework/ActiveSync/lib/Horde/ActiveSync/State/History.php +++ b/framework/ActiveSync/lib/Horde/ActiveSync/State/History.php @@ -11,6 +11,7 @@ * contains the current folder state on the PIM. * sync_devid: The device id. * sync_folderid: The folder id for this sync. + * sync_user: The user for this synckey * * syncMapTable (horde_activesync_map): * message_uid - The server uid for the object @@ -19,15 +20,20 @@ * sync_key - The syncKey that was current at the time the change * was received. * sync_devid - The device id this change was done on. + * sync_user - The user that initiated the change. * * syncDeviceTable (horde_activesync_device: * device_id - The unique id for this device * device_type - The device type the PIM identifies itself with * device_agent - The user agent string sent by the device - * device_ping - The device's current PING state information. * device_policykey - The current policykey for this device * device_rwstatus - The current remote wipe status for this device - * device_user - The user this device belongs to. + * + * syncUsersTable (horde_activesync_device_users: + * device_user + * device_id + * device_ping + * device_folders * * * Copyright 2010 The Horde Project (http://www.horde.org) @@ -69,6 +75,7 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base protected $_syncStateTable; protected $_syncMapTable; protected $_syncDeviceTable; + protected $_syncUsersTable; /** * Const'r @@ -80,6 +87,7 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base * 'syncMapTable' - Name of table for remembering what changes * are due to PIM import so we don't mirror the * changes back to the PIM on next Sync + * 'syncUsersTable' - Name of table for mapping users to devices. * * @return Horde_ActiveSync_StateMachine_File */ @@ -93,6 +101,7 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base $this->_syncStateTable = $params['statetable']; $this->_syncMapTable = $params['maptable']; $this->_syncDeviceTable = $params['devicetable']; + $this->_syncUsersTable = $params['userstable']; $this->_db = $params['db']; } @@ -194,7 +203,7 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base /* Update state table to remember this last synctime and key */ $sql = 'INSERT INTO ' . $this->_syncStateTable - . ' (sync_key, sync_data, sync_devid, sync_time, sync_folderid) VALUES (?, ?, ?, ?, ?)'; + . ' (sync_key, sync_data, sync_devid, sync_time, sync_folderid, sync_user) VALUES (?, ?, ?, ?, ?, ?)'; /* Remember any left over changes */ if ($this->_type == 'foldersync') { @@ -209,7 +218,8 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base $data, $this->_devId, $this->_thisSyncTS, - !empty($this->_collection['id']) ? $this->_collection['id'] : 'foldersync'); + !empty($this->_collection['id']) ? $this->_collection['id'] : 'foldersync', + $this->_deviceInfo->user); try { $this->_db->insert($sql, $params); } catch (Horde_Db_Exception $e) { @@ -282,13 +292,13 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base * activesync versions that use GETHIERARCHY requests to get the folder info * instead of maintaining the folder state with FOLDERSYNC requests. * - * @param string $devId The device Id - * @param array $folders The folder data + * @param object $device The device object + * @param array $folders The folder data * * @return boolean * @throws Horde_ActiveSync_Exception */ - public function setFolderData($devId, $folders) + public function setFolderData($device, $folders) { if (!is_array($folders) || empty ($folders)) { return false; @@ -316,10 +326,10 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base $unique_folders[Horde_ActiveSync::FOLDER_TYPE_CONTACT] = Horde_ActiveSync::FOLDER_TYPE_DUMMY; } - /* Storage to SQL? */ - $sql = 'UPDATE ' . $this->_syncDeviceTable . ' SET device_folders = ? WHERE device_id = ?'; + /* Store it*/ + $sql = 'UPDATE ' . $this->_syncUsersTable . ' SET device_folders = ? WHERE device_id = ? AND device_user = ?'; try { - return $this->_db->update($sql, array(serialize($folders), $devId)); + return $this->_db->update($sql, array(serialize($folders), $device->id, $device->user)); } catch (Horde_Db_Exception $e) { throw new Horde_ActiveSync_Exception($e); } @@ -328,16 +338,16 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base /** * Get the folder data for a specific device * - * @param string $devId The device id - * @param string $class The folder class to fetch (Calendar, Contacts etc.) + * @param object $device The device object + * @param string $class The folder class to fetch (Calendar, Contacts etc.) * * @return mixed Either an array of folder data || false */ - public function getFolderData($devId, $class) + public function getFolderData($device, $class) { - $sql = 'SELECT device_folders FROM ' . $this->_syncDeviceTable . ' WHERE device_id = ?'; + $sql = 'SELECT device_folders FROM ' . $this->_syncUsersTable . ' WHERE device_id = ? AND device_user = ?'; try { - $folders = $this->_db->selectValue($sql, array($devId)); + $folders = $this->_db->selectValue($sql, array($device->id, $device->user)); } catch (Horde_Db_Exception $e) { throw new Horde_ActiveSync_Exception($e); } @@ -382,12 +392,12 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base * * @return The $collection array */ - public function initPingState($devId) + public function initPingState($device) { /* This would normally already be loaded by getDeviceInfo() but we * should verify we have the correct device loaded etc... */ - if (!isset($this->_pingState) || $this->_devId !== $devId) { - $this->getDeviceInfo($devId); + if (!isset($this->_pingState) || $this->_devId !== $device->id) { + throw new Horde_ActiveSync_Exception('Device not loaded'); } /* Need to get the last sync time for this collection */ @@ -398,22 +408,26 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base * Obtain the device object. For this driver, we also store the PING data * in the device table. * - * @param string $devId + * @param string $devId The device id to obtain + * @param string $user The user to retrieve user-specific device info for * - * @return StdClass + * @return object The device obejct + * @throws Horde_ActiveSync_Exception */ - public function getDeviceInfo($devId) + public function getDeviceInfo($devId, $user) { + //@TODO - combine _devId and _deviceInfo /* See if we have it already */ if ($this->_devId == $devId && !empty($this->_deviceInfo)) { return $this->_deviceInfo; } $this->_devId = $devId; - $query = 'SELECT device_type, device_agent, device_ping, device_policykey, device_rwstatus, device_user, device_supported FROM ' - . $this->_syncDeviceTable . ' WHERE device_id = ?'; + $query = 'SELECT device_type, device_agent, device_ping, device_policykey, device_rwstatus, device_supported FROM ' + . $this->_syncDeviceTable . ' d INNER JOIN ' . $this->_syncUsersTable . ' u ON d.device_id = u.device_id WHERE u.device_id = ? AND u.device_user = ?'; try { - $result = $this->_db->selectOne($query, array($devId)); + $this->_logger->debug('SQL QUERY: ' . $query . ' VALUES: ' . $devId . ' ' . $user); + $result = $this->_db->selectOne($query, array($devId, $user)); } catch (Horde_Db_Exception $e) { throw new Horde_ActiveSync_Exception($e); } @@ -424,7 +438,7 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base $this->_deviceInfo->deviceType = $result['device_type']; $this->_deviceInfo->userAgent = $result['device_agent']; $this->_deviceInfo->id = $devId; - $this->_deviceInfo->user = $result['device_user']; + $this->_deviceInfo->user = $user; $this->_deviceInfo->supported = unserialize($result['device_supported']); if ($result['device_ping']) { $this->_pingState = empty($result['device_ping']) ? array() : unserialize($result['device_ping']); @@ -432,15 +446,7 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base $this->resetPingState(); } } else { - /* Default structure */ - $this->_deviceInfo->policykey = 0; - $this->_deviceInfo->rwstatus = Horde_ActiveSync::RWSTATUS_NA; - $this->_deviceInfo->deviceType = ''; - $this->_deviceInfo->userAgent = ''; - $this->_deviceInfo->id = $devId; - $this->_deviceInfo->user = $this->_backend->getUser(); - $this->setDeviceInfo($this->_deviceInfo); - $this->resetPingState(); + throw new Horde_ActiveSync_Exception('Device not found.'); } return $this->_deviceInfo; @@ -449,34 +455,55 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base /** * Set new device info * - * @param StdClass $data The device information + * @param object $data The device information * * @return boolean */ public function setDeviceInfo($data) { - /* Delete the old entry, just in case */ - $this->_deviceInfo = $data; + /* Make sure we have the device entry */ try { - $query = 'DELETE FROM ' . $this->_syncDeviceTable . ' WHERE device_id = ?'; - $this->_db->execute($query, array($data->id)); - - $query = 'INSERT INTO ' . $this->_syncDeviceTable - . '(device_type, device_agent, device_ping, device_policykey, device_rwstatus, device_id, device_user, device_supported)' - . ' VALUES(?, ?, ?, ?, ?, ?, ?, ?)'; - - $values = array($data->deviceType, - $data->userAgent, - '', - $data->policykey, - $data->rwstatus, - $data->id, - $data->user, - (!empty($data->supported) ? serialize($data->supported) : '')); + if (!$this->deviceExists($data->id)) { + $this->_logger->debug('[' . $data->id . '] Device entry does not exist, creating it.'); + $query = 'INSERT INTO ' . $this->_syncDeviceTable + . ' (device_type, device_agent, device_policykey, device_rwstatus, device_id, device_supported)' + . ' VALUES(?, ?, ?, ?, ?, ?)'; + $values = array( + $data->deviceType, + $data->userAgent, + $data->policykey, + $data->rwstatus, + $data->id, + (!empty($data->supported) ? serialize($data->supported) : '') + ); + $this->_db->execute($query, $values); + } + } catch(Horde_Db_Exception $e) { + throw new Horde_ActiveSync_Exception($e); + } - $this->_devId = $data->id; + $this->_deviceInfo = $data; - return $this->_db->insert($query, $values); + /* See if we have the user already also */ + try { + $query = 'SELECT COUNT(*) FROM ' . $this->_syncUsersTable . ' WHERE device_id = ? AND device_user = ?'; + $cnt = $this->_db->selectValue($query, array($data->id, $data->user)); + if (!$cnt) { + $this->_logger->debug('[' . $data->id . '] Device entry does not exist for user ' . $data->user . ', creating it.'); + $query = 'INSERT INTO ' . $this->_syncUsersTable + . ' (device_ping, device_id, device_user)' + . ' VALUES(?, ?, ?)'; + + $values = array( + '', + $data->id, + $data->user + ); + $this->_devId = $data->id; + return $this->_db->insert($query, $values); + } else { + return true; + } } catch (Horde_Db_Exception $e) { throw new Horde_ActiveSync_Exception($e); } @@ -484,17 +511,27 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base /** * Check that a given device id is known to the server. This is regardless - * of Provisioning status. + * of Provisioning status. If $user is provided, checks that the device + * is attached to the provided username. * - * @param string $devId + * @param string $devId The device id to check. + * @param string $user The device should be owned by this user. * * @return boolean */ - public function deviceExists($devId) + public function deviceExists($devId, $user = null) { - $query = 'SELECT COUNT(*) FROM ' . $this->_syncDeviceTable . ' WHERE device_id = ?'; + if (!empty($user)) { + $query = 'SELECT COUNT(*) FROM ' . $this->_syncDeviceTable . ' d INNER JOIN ' + . $this->_syncUsersTable . ' u ON d.device_id = u.device_id WHERE ' + . ' d.device_id = ? AND u.device_user = ?'; + $values = array($devId, $user); + } else { + $query = 'SELECT COUNT(*) FROM ' . $this->_syncDeviceTable . ' WHERE device_id = ?'; + $values = array($devId); + } try { - return $this->_db->selectValue($query, array($devId)); + return $this->_db->selectValue($query, $values); } catch (Horde_Db_Exception $e) { throw new Horde_ActiveSync_Exception($e); } @@ -508,32 +545,38 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base */ public function listDevices($user = null) { - $sql = 'SELECT * from ' . $this->_syncDeviceTable; - $values = array(); - if ($user) { - $sql .= ' WHERE device_user = ?'; - $values[] = $user; + if (!empty($user)) { + $query = 'SELECT d.device_id device_id, device_type, device_agent,' + . ' device_policykey, device_rwstatus, device_user FROM ' + . $this->_syncDeviceTable . ' d INNER JOIN ' . $this->_syncUsersTable + . ' u ON d.device_id = u.device_id WHERE u.device_user = ?'; + $values = array($user); + } else { + $query = 'SELECT * from ' . $this->_syncDeviceTable; + $values = array(); } try { - return $this->_db->selectAll($sql, $values); + return $this->_db->selectAll($query, $values); } catch (Horde_Db_Exception $e) { throw new Horde_ActiveSync_Exception($e); } } /** - * Get the last time a particular device issued a SYNC request. - * - * @param string $devId The device id + * Get the last time the loaded device issued a SYNC request. * * @return integer The timestamp of the last sync, regardless of collection * @throws Horde_ActiveSync_Exception */ - public function getLastSyncTimestamp($devId) + public function getLastSyncTimestamp() { - $sql = 'SELECT sync_time FROM ' . $this->_syncStateTable . ' WHERE sync_devid = ?'; + if (empty($this->_deviceInfo)) { + throw new Horde_ActiveSync_Exception('Device not loaded.'); + } + + $sql = 'SELECT MAX(sync_time) FROM ' . $this->_syncStateTable . ' WHERE sync_devid = ? AND sync_user = ?'; try { - return $this->_db->selectValue($sql, array($devId)); + return $this->_db->selectValue($sql, array($this->_devId, $this->_deviceInfo->user)); } catch (Horde_Db_Exception $e) { throw new Horde_ActiveSync_Exception($e); } @@ -607,10 +650,10 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base } $state = serialize(array('lifetime' => $this->_pingState['lifetime'], 'collections' => $this->_pingState['collections'])); - $query = 'UPDATE ' . $this->_syncDeviceTable . ' SET device_ping = ? WHERE device_id = ?'; + $query = 'UPDATE ' . $this->_syncUsersTable . ' SET device_ping = ? WHERE device_id = ? AND device_user = ?'; try { - return $this->_db->update($query, array($state, $this->_devId)); + return $this->_db->update($query, array($state, $this->_devId, $this->_deviceInfo->user)); } catch (Horde_Db_Exception $e) { throw new Horde_ActiveSync_Exception($e); } @@ -718,8 +761,8 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base */ public function setPolicyKey($devId, $key) { - if (empty($this->_deviceInfo)) { - $this->getDeviceInfo($devId); + if (empty($this->_deviceInfo) || $devId != $this->_deviceInfo->id) { + throw new Horde_ActiveSync_Exception('Device not loaded'); } $query = 'UPDATE ' . $this->_syncDeviceTable . ' SET device_policykey = ? WHERE device_id = ?'; @@ -741,15 +784,15 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base */ public function setDeviceRWStatus($devId, $status) { - if (empty($this->_deviceInfo)) { - $this->getDeviceInfo($devId); + if (empty($this->_deviceInfo) || $devId != $this->_deviceInfo->id) { + throw new Horde_ActiveSync_Exception('Device not loaded'); } $query = 'UPDATE ' . $this->_syncDeviceTable . ' SET device_rwstatus = ?'; $values = array($status); if ($status == Horde_ActiveSync::RWSTATUS_PENDING) { - /* Need to clear the policykey to force a provision */ + /* Need to clear the policykey to force a PROVISION */ $query .= ',device_policykey = ?'; $values[] = 0; } @@ -766,20 +809,30 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base * Explicitly remove a state from storage. * * @param string $synckey The specific state to remove - * @param string $devId Remove all information for this device (ignores synckey) + * @param string $devId Remove all information for this device. + * @param string $user When removing device info, restrict to removing + * data for this user only. * * @throws Horde_ActiveSyncException */ - public function removeState($synckey = null, $devId = null) + public function removeState($synckey = null, $devId = null, $user = null) { $state_query = 'DELETE FROM ' . $this->_syncStateTable . ' WHERE'; $map_query = 'DELETE FROM ' . $this->_syncMapTable . ' WHERE'; - if ($devId) { + if ($devId && $user) { + $state_query .= ' sync_devid = ? AND sync_user = ?'; + $map_query .= ' sync_devid = ? AND sync_user = ?'; + $user_query = 'DELETE FROM ' . $this->_syncUsersTable . ' WHERE device_id = ? AND device_user = ?'; + $values = array($devId, $user); + $this->_logger->debug('[' . $devId . '] Removing device state for user ' . $user . '.'); + } elseif ($devId){ $state_query .= ' sync_devid = ?'; $map_query .= ' sync_devid = ?'; + $user_query = 'DELETE FROM ' . $this->_syncUsersTable . ' WHERE device_id = ?'; $device_query = 'DELETE FROM ' . $this->_syncDeviceTable . ' WHERE device_id = ?'; $values = array($devId); - $this->_logger->debug('[' . $devId . '] Removing device state.'); + $this->_logger->debug('[' . $devId . '] Removing device state for user ' . $user . '.'); + } else { $state_query .= ' sync_key = ?'; $map_query .= ' sync_key = ?'; @@ -790,8 +843,19 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base try { $this->_db->delete($state_query, $values); $this->_db->delete($map_query, $values); + if (!empty($user_query)) { + $this->_db->delete($user_query, $values); + } if (!empty($device_query)) { $this->_db->delete($device_query, $values); + } elseif (!empty($user_query)) { + /* If there was a user_deletion, check if we should remove the + * device entry as well */ + $sql = 'SELECT COUNT(*) FROM ' . $this->_syncUsersTable . ' WHERE device_id = ?'; + if (!$this->_db->selectValue($sql, array($devId))) { + $query = 'DELETE FROM ' . $this->_syncDeviceTable . ' WHERE device_id = ?'; + $this->_db->delete($query, array($devId)); + } } } catch (Horde_Db_Exception $e) { throw new Horde_ActiveSync_Exception($e); @@ -807,9 +871,9 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base */ protected function _getPIMChangeTS($uid) { - $sql = 'SELECT sync_modtime FROM ' . $this->_syncMapTable . ' WHERE message_uid = ? AND sync_devid = ?'; + $sql = 'SELECT sync_modtime FROM ' . $this->_syncMapTable . ' WHERE message_uid = ? AND sync_devid = ? AND sync_user = ?'; try { - return $this->_db->selectValue($sql, array($uid, $this->_devId)); + return $this->_db->selectValue($sql, array($uid, $this->_devId, $this->_deviceInfo->user)); } catch (Horde_Db_Exception $e) { throw new Horde_ActiveSync_Exception($e); } @@ -818,7 +882,7 @@ class Horde_ActiveSync_State_History extends Horde_ActiveSync_State_Base /** * Check for the existence of ANY entries in the map table for this device. * An extra database query for each sync, but the payoff is that we avoid - * having to state every message change we send to the PIM if there are no + * having to stat every message change we send to the PIM if there are no * PIM generated changes for this sync period. * * @return boolean diff --git a/framework/ActiveSync/test/Horde/ActiveSync/HordeDriverTest.php b/framework/ActiveSync/test/Horde/ActiveSync/HordeDriverTest.php index 5f87fc0e1..b090abbe8 100644 --- a/framework/ActiveSync/test/Horde/ActiveSync/HordeDriverTest.php +++ b/framework/ActiveSync/test/Horde/ActiveSync/HordeDriverTest.php @@ -226,9 +226,13 @@ class Horde_ActiveSync_HordeDriverTest extends Horde_Test_Case /* Fixtures - don't really need data, since the change is not actually done */ $message = new Horde_ActiveSync_Message_Contact(); + /* Mock device object */ + $device = new stdClass(); + $device->supported = array(); + /* Try adding a new contact */ try { - $results = $driver->ChangeMessage(Horde_ActiveSync_Driver_Horde::CONTACTS_FOLDER, 0, $message); + $results = $driver->ChangeMessage(Horde_ActiveSync_Driver_Horde::CONTACTS_FOLDER, 0, $message, $device); } catch (Horde_ActiveSync_Exception $e) { $this->fail($e->getMessage()); } @@ -237,7 +241,7 @@ class Horde_ActiveSync_HordeDriverTest extends Horde_Test_Case /* Try editing a contact */ try { - $results = $driver->ChangeMessage(Horde_ActiveSync_Driver_Horde::CONTACTS_FOLDER, 'localhost@123.123', $message); + $results = $driver->ChangeMessage(Horde_ActiveSync_Driver_Horde::CONTACTS_FOLDER, 'localhost@123.123', $message, $device); } catch (Horde_ActiveSync_Exception $e) { $this->fail($e->getMessage()); } @@ -247,7 +251,7 @@ class Horde_ActiveSync_HordeDriverTest extends Horde_Test_Case /* Try adding a new appointment */ $message = new Horde_ActiveSync_Message_Appointment(); try { - $results = $driver->ChangeMessage(Horde_ActiveSync_Driver_Horde::APPOINTMENTS_FOLDER, 0, $message); + $results = $driver->ChangeMessage(Horde_ActiveSync_Driver_Horde::APPOINTMENTS_FOLDER, 0, $message, $device); } catch (Horde_ActiveSync_Exception $e) { $this->fail($e->getMessage()); } @@ -256,7 +260,7 @@ class Horde_ActiveSync_HordeDriverTest extends Horde_Test_Case /* Try editing an appointment */ try { - $results = $driver->ChangeMessage(Horde_ActiveSync_Driver_Horde::APPOINTMENTS_FOLDER, 'localhost@123.123', $message); + $results = $driver->ChangeMessage(Horde_ActiveSync_Driver_Horde::APPOINTMENTS_FOLDER, 'localhost@123.123', $message, $device); } catch (Horde_ActiveSync_Exception $e) { $this->fail($e->getMessage()); } @@ -266,7 +270,7 @@ class Horde_ActiveSync_HordeDriverTest extends Horde_Test_Case /* Try adding a new task */ $message = new Horde_ActiveSync_Message_Task(); try { - $results = $driver->ChangeMessage(Horde_ActiveSync_Driver_Horde::TASKS_FOLDER, 0, $message); + $results = $driver->ChangeMessage(Horde_ActiveSync_Driver_Horde::TASKS_FOLDER, 0, $message, $device); } catch (Horde_ActiveSync_Exception $e) { $this->fail($e->getMessage()); } @@ -275,7 +279,7 @@ class Horde_ActiveSync_HordeDriverTest extends Horde_Test_Case /* Try editing an appointment */ try { - $results = $driver->ChangeMessage(Horde_ActiveSync_Driver_Horde::TASKS_FOLDER, 'localhost@123.123', $message); + $results = $driver->ChangeMessage(Horde_ActiveSync_Driver_Horde::TASKS_FOLDER, 'localhost@123.123', $message, $device); } catch (Horde_ActiveSync_Exception $e) { $this->fail($e->getMessage()); } diff --git a/horde/config/conf.xml b/horde/config/conf.xml index a17c8381a..47e43e3c5 100644 --- a/horde/config/conf.xml +++ b/horde/config/conf.xml @@ -1991,6 +1991,8 @@ data:">horde_activesync_state horde_activesync_map + horde_activesync_device_users diff --git a/horde/lib/Prefs/Ui.php b/horde/lib/Prefs/Ui.php index 1deed0866..2826a7911 100644 --- a/horde/lib/Prefs/Ui.php +++ b/horde/lib/Prefs/Ui.php @@ -416,12 +416,14 @@ class Horde_Prefs_Ui $t->setOption('gettext', true); $selfurl = $ui->selfUrl(); $t->set('reset', $selfurl->copy()->add('reset', 1)); + $t->set('username', Horde_Auth::getAuth()); $devices = $stateMachine->listDevices(Horde_Auth::getAuth()); $devs = array(); $i = 1; foreach ($devices as $device) { $device['class'] = fmod($i++, 2) ? 'rowOdd' : 'rowEven'; - $ts = $stateMachine->getLastSyncTimestamp($device['device_id']); + $stateMachine->getDeviceInfo($device['device_id'], Horde_Auth::getAuth()); + $ts = $stateMachine->getLastSyncTimestamp(); $device['ts'] = empty($ts) ? _("None") : strftime($GLOBALS['prefs']->getValue('date_format') . ' %H:%M', $ts); switch ($device['device_rwstatus']) { case Horde_ActiveSync::RWSTATUS_PENDING: @@ -702,11 +704,11 @@ class Horde_Prefs_Ui } elseif ($ui->vars->reset) { $devices = $stateMachine->listDevices(Horde_Auth::getAuth()); foreach ($devices as $device) { - $stateMachine->removeState(null, $device['device_id']); + $stateMachine->removeState(null, $device['device_id'], $ui->vars->removeuser); } $GLOBALS['notification']->push(_("All state removed for your devices. They will resynchronize next time they connect to the server.")); } elseif ($ui->vars->removedevice) { - $stateMachine->removeState(null, $ui->vars->removedevice); + $stateMachine->removeState(null, $ui->vars->removedevice, $ui->vars->removeuser); } } diff --git a/horde/scripts/sql/create.mssql.sql b/horde/scripts/sql/create.mssql.sql index 3b88ce9ee..69f5e2d6a 100644 --- a/horde/scripts/sql/create.mssql.sql +++ b/horde/scripts/sql/create.mssql.sql @@ -236,6 +236,7 @@ CREATE TABLE horde_activesync_state ( sync_data TEXT, sync_devid VARCHAR(255), sync_folderid VARCHAR(255), + sync_user VARCHAR(255) NOT NULL, -- PRIMARY KEY (sync_key) ); @@ -250,10 +251,12 @@ CREATE TABLE horde_activesync_map ( sync_modtime INT, sync_key VARCHAR(255) NOT NULL, sync_devid VARCHAR(255) NOT NULL, - sync_folderid VARCHAR(255) NOT NULL + sync_folderid VARCHAR(255) NOT NULL, + sync_user VARCHAR(255) NOT NULL ); GO +CREATE INDEX activesync_map_user_idx ON horde_activesync_map (sync_user); CREATE INDEX activesync_map_devid_idx ON horde_activesync_map (sync_devid); CREATE INDEX activesync_map_message_idx ON horde_activesync_map (message_uid); GO @@ -262,17 +265,23 @@ CREATE TABLE horde_activesync_device ( device_id VARCHAR(255) NOT NULL, device_type VARCHAR(255) NOT NULL, device_agent VARCHAR(255) NOT NULL, - device_ping TEXT, device_supported TEXT, device_policykey BIGINT DEFAULT 0, device_rwstatus INT, - device_folders TEXT, - device_user VARCHAR(255), - -- PRIMARY KEY (device_id) ); GO -CREATE INDEX activesync_device_user_idx ON horde_activesync_device (device_user); +CREATE TABLE horde_activesync_device_users ( + device_id VARCHAR(255) NOT NULL, + device_user VARCHAR(255) NOT NULL, + device_ping TEXT, + device_folders TEXT, +-- + PRIMARY KEY (device_id, device_user) +); GO + +CREATE INDEX activesync_device_users_idx ON horde_activesync_device_users (device_user); +GO \ No newline at end of file diff --git a/horde/scripts/sql/create.mysql.sql b/horde/scripts/sql/create.mysql.sql index c18e95e77..6812d0d63 100644 --- a/horde/scripts/sql/create.mysql.sql +++ b/horde/scripts/sql/create.mysql.sql @@ -259,6 +259,7 @@ CREATE TABLE horde_activesync_state ( sync_data TEXT, sync_devid VARCHAR(255), sync_folderid VARCHAR(255), + sync_user VARCHAR(255) NOT NULL, -- PRIMARY KEY (sync_key) ); @@ -271,27 +272,35 @@ CREATE TABLE horde_activesync_map ( sync_modtime INTEGER, sync_key VARCHAR(255) NOT NULL, sync_devid VARCHAR(255) NOT NULL, - sync_folderid VARCHAR(255) NOT NULL + sync_folderid VARCHAR(255) NOT NULL, + sync_user VARCHAR(255) NOT NULL ); CREATE INDEX activesync_map_devid_idx ON horde_activesync_map (sync_devid); CREATE INDEX activesync_map_message_idx ON horde_activesync_map (message_uid); +CREATE INDEX activesync_map_user_idx ON horde_activesync_map (sync_user); + CREATE TABLE horde_activesync_device ( device_id VARCHAR(255) NOT NULL, device_type VARCHAR(255) NOT NULL, device_agent VARCHAR(255) NOT NULL, - device_ping TEXT, device_supported TEXT, device_policykey BIGINT DEFAULT 0, device_rwstatus INTEGER, - device_folders TEXT, - device_user VARCHAR(255), - -- PRIMARY KEY (device_id) ); -CREATE INDEX activesync_device_user_idx ON horde_activesync_device (device_user); +CREATE TABLE horde_activesync_device_users ( + device_id VARCHAR(255) NOT NULL, + device_user VARCHAR(255) NOT NULL, + device_ping TEXT, + device_folders TEXT, +-- + PRIMARY KEY (device_id, device_user) +); + +CREATE INDEX activesync_device_users_idx ON horde_activesync_device_users (device_user); -- Done. diff --git a/horde/scripts/sql/create.oci8.sql b/horde/scripts/sql/create.oci8.sql index 67ca21b55..cfca2ae80 100644 --- a/horde/scripts/sql/create.oci8.sql +++ b/horde/scripts/sql/create.oci8.sql @@ -284,6 +284,7 @@ CREATE TABLE horde_activesync_state ( sync_data CLOB, sync_devid VARCHAR2(255), sync_folderid VARCHAR2(255), + sync_user VARCHAR2(255) NOT NULL, -- PRIMARY KEY (sync_key) ); @@ -296,26 +297,34 @@ CREATE TABLE horde_activesync_map ( sync_modtime NUMBER(16), sync_key VARCHAR2(255) NOT NULL, sync_devid VARCHAR2(255) NOT NULL, - sync_folderid VARCHAR2(255) NOT NULL + sync_folderid VARCHAR2(255) NOT NULL, + sync_user VARCHAR2(255) NOT NULL ); CREATE INDEX activesync_map_devid_idx ON horde_activesync_map (sync_devid); CREATE INDEX activesync_map_message_idx ON horde_activesync_map (message_uid); +CREATE INDEX activesync_map_user_idx ON horde_activesync_map (sync_user); + CREATE TABLE horde_activesync_device ( device_id VARCHAR2(255) NOT NULL, device_type VARCHAR2(255) NOT NULL, device_agent VARCHAR2(255) NOT NULL, - device_ping CLOB, device_supported CLOB, device_policykey NUMBER(16) DEFAULT 0, device_rwstatus NUMBER(8), - device_folders CLOB, - device_user VARCHAR2(255), -- PRIMARY KEY (device_id) ); -CREATE INDEX activesync_device_user_idx ON horde_activesync_device (device_user); +CREATE TABLE horde_activesync_device_users ( + device_id VARCHAR2(255) NOT NULL, + device_user VARCHAR2(255) NOT NULL, + device_ping CLOB, + device_folders CLOB, +-- + PRIMARY KEY (device_id, device_user) +); +CREATE INDEX activesync_device_users_idx ON horde_activesync_device_users (device_user); exit diff --git a/horde/scripts/sql/create.pgsql.sql b/horde/scripts/sql/create.pgsql.sql index 9a3dd6536..229b8ca8b 100644 --- a/horde/scripts/sql/create.pgsql.sql +++ b/horde/scripts/sql/create.pgsql.sql @@ -220,6 +220,7 @@ CREATE TABLE horde_activesync_state ( sync_data TEXT, sync_devid VARCHAR(255), sync_folderid VARCHAR(255), + sync_user VARCHAR(255) NOT NULL, -- PRIMARY KEY (sync_key) ); @@ -232,27 +233,33 @@ CREATE TABLE horde_activesync_map ( sync_modtime INT, sync_key VARCHAR(255) NOT NULL, sync_devid VARCHAR(255) NOT NULL, - sync_folderid VARCHAR(255) NOT NULL + sync_folderid VARCHAR(255) NOT NULL, + sync_user VARCHAR(255) NOT NULL ); CREATE INDEX activesync_map_devid_idx ON horde_activesync_map (sync_devid); CREATE INDEX activesync_map_message_idx ON horde_activesync_map (message_uid); +CREATE INDEX activesync_map_user_idx ON horde_activesync_map (sync_user); CREATE TABLE horde_activesync_device ( device_id VARCHAR(255) NOT NULL, device_type VARCHAR(255) NOT NULL, device_agent VARCHAR(255) NOT NULL, - device_ping TEXT, device_supported TEXT, device_policykey BIGINT DEFAULT 0, device_rwstatus INT, - device_folders TEXT, - device_user VARCHAR(255), - -- PRIMARY KEY (device_id) ); -CREATE INDEX activesync_device_user_idx ON horde_activesync_device (device_user); +CREATE TABLE horde_activesync_device_users ( + device_id VARCHAR(255) NOT NULL, + device_user VARCHAR(255) NOT NULL, + device_ping TEXT, + device_folders TEXT, +-- + PRIMARY KEY (device_id, device_user) +); +CREATE INDEX activesync_device_users_idx ON horde_activesync_device_users (device_user); COMMIT; diff --git a/horde/scripts/sql/create.sql b/horde/scripts/sql/create.sql index aca818fcb..012d75a40 100644 --- a/horde/scripts/sql/create.sql +++ b/horde/scripts/sql/create.sql @@ -227,6 +227,7 @@ CREATE TABLE horde_activesync_state ( sync_data TEXT, sync_devid VARCHAR(255), sync_folderid VARCHAR(255), + sync_user VARCHAR(255) NOT NULL, -- PRIMARY KEY (sync_key) ); @@ -239,25 +240,31 @@ CREATE TABLE horde_activesync_map ( sync_modtime INTEGER, sync_key VARCHAR(255) NOT NULL, sync_devid VARCHAR(255) NOT NULL, - sync_folderid VARCHAR(255) NOT NULL + sync_folderid VARCHAR(255) NOT NULL, + sync_user VARCHAR(255) NOT NULL ); CREATE INDEX activesync_map_devid_idx ON horde_activesync_map (sync_devid); CREATE INDEX activesync_map_message_idx ON horde_activesync_map (message_uid); +CREATE INDEX activesync_map_user_idx ON horde_activesync_map (sync_user); CREATE TABLE horde_activesync_device ( device_id VARCHAR(255) NOT NULL, device_type VARCHAR(255) NOT NULL, device_agent VARCHAR(255) NOT NULL, - device_ping TEXT, device_supported TEXT, device_policykey BIGINT DEFAULT 0, device_rwstatus INTEGER, - device_folders TEXT, - device_user VARCHAR(255), - -- PRIMARY KEY (device_id) ); -CREATE INDEX activesync_device_user_idx ON horde_activesync_device (device_user); \ No newline at end of file +CREATE TABLE horde_activesync_device_users ( + device_id VARCHAR(255) NOT NULL, + device_user VARCHAR(255) NOT NULL, + device_ping TEXT, + device_folders TEXT, +-- + PRIMARY KEY (device_id, device_user) +); +CREATE INDEX activesync_device_users_idx ON horde_activesync_device_users (device_user); diff --git a/horde/scripts/sql/create.sybase.sql b/horde/scripts/sql/create.sybase.sql index 02854d82f..d8749ea7b 100644 --- a/horde/scripts/sql/create.sybase.sql +++ b/horde/scripts/sql/create.sybase.sql @@ -181,6 +181,7 @@ CREATE TABLE horde_activesync_state ( sync_data text, sync_devid varchar(255), sync_folderid varchar(255), + sync_user varchar(255), -- PRIMARY KEY (sync_key) ); @@ -191,7 +192,8 @@ CREATE TABLE horde_activesync_map ( sync_modtime numeric(10, 0), sync_key varchar(255) NOT NULL, sync_devid varchar(255) NOT NULL, - sync_folderid varchar(255) NOT NULL + sync_folderid varchar(255) NOT NULL, + sync_user varchar(255) ); go @@ -199,18 +201,24 @@ CREATE TABLE horde_activesync_device ( device_id varchar(255) NOT NULL, device_type varchar(255) NOT NULL, device_agent varchar(255) NOT NULL, - device_ping text, device_supported text, device_policykey number(11, 0) DEFAULT 0, device_rwstatus number(10, 0), - device_folders text, - device_user varchar(255), - -- PRIMARY KEY (device_id) ); go +CREATE TABLE horde_activesync_device_users ( + device_id varchar(255) NOT NULL, + device_user varchar(255) NOT NULL, + device_ping text, + device_folders text, +-- + PRIMARY KEY (device_id, device_user) +); +go + -- CREATE TABLE horde_datatree_seq ( -- id numeric(10,0) IDENTITY NOT NULL, -- PRIMARY KEY (id) @@ -332,6 +340,12 @@ go CREATE INDEX activesync_device_user_idx ON horde_activesync_device (device_user); go +CREATE INDEX activesync_device_users_idx ON horde_activesync_device_users (device_user); +go + +CREATE INDEX activesync_map_user_idx ON horde_activesync_map (sync_user); +go + -- CREATE INDEX vfs_path_idx ON horde_vfs (vfs_path) -- go diff --git a/horde/scripts/sql/create.xml b/horde/scripts/sql/create.xml index eb30d2986..06ae2df29 100644 --- a/horde/scripts/sql/create.xml +++ b/horde/scripts/sql/create.xml @@ -1345,6 +1345,13 @@ false + + sync_user + text + 255 + false + + activesync_state_primary true @@ -1409,6 +1416,13 @@ false + + sync_user + text + 255 + false + + activesync_map_message_idx @@ -1423,6 +1437,13 @@ + + activesync_map_user_idx + + sync_user + + + @@ -1452,12 +1473,6 @@ - device_ping - clob - false - - - device_supported clob false @@ -1475,6 +1490,29 @@ false + + activesync_device_primary + true + + device_id + + + + + + + + + + horde_activesync_device_users + + + + device_ping + clob + false + + device_folders clob @@ -1489,15 +1527,7 @@ - activesync_device_primary - true - - device_id - - - - - activesync_device_user_message_idx + activesync_device_user_idx device_user @@ -1506,5 +1536,4 @@
- diff --git a/horde/scripts/sql/horde_activesync.sql b/horde/scripts/sql/horde_activesync.sql index 92546b59a..ae64a7f73 100644 --- a/horde/scripts/sql/horde_activesync.sql +++ b/horde/scripts/sql/horde_activesync.sql @@ -4,6 +4,7 @@ CREATE TABLE horde_activesync_state ( sync_data TEXT, sync_devid VARCHAR(255), sync_folderid VARCHAR(255), + sync_user VARCHAR(255) NOT NULL, -- PRIMARY KEY (sync_key) ); @@ -16,26 +17,34 @@ CREATE TABLE horde_activesync_map ( sync_modtime INTEGER, sync_key VARCHAR(255) NOT NULL, sync_devid VARCHAR(255) NOT NULL, - sync_folderid VARCHAR(255) NOT NULL + sync_folderid VARCHAR(255) NOT NULL, + sync_user VARCHAR(255) NOT NULL ); CREATE INDEX activesync_map_devid_idx ON horde_activesync_map (sync_devid); CREATE INDEX activesync_map_message_idx ON horde_activesync_map (message_uid); +CREATE INDEX activesync_map_user_idx ON horde_activesync_map (sync_user); + CREATE TABLE horde_activesync_device ( device_id VARCHAR(255) NOT NULL, device_type VARCHAR(255) NOT NULL, device_agent VARCHAR(255) NOT NULL, - device_ping TEXT, device_supported TEXT, device_policykey BIGINT DEFAULT 0, device_rwstatus INTEGER, - device_folders TEXT, - device_user VARCHAR(255), - -- PRIMARY KEY (device_id) ); -CREATE INDEX activesync_device_user_idx ON horde_activesync_device (device_user); +CREATE TABLE horde_activesync_device_users ( + device_id VARCHAR(255) NOT NULL, + device_user VARCHAR(255) NOT NULL, + device_ping TEXT, + device_folders TEXT, +-- + PRIMARY KEY (device_id, device_user) +); + +CREATE INDEX activesync_device_user_idx ON horde_activesync_users (device_user); diff --git a/horde/scripts/upgrades/2010-05-11_horde_activesync_adduserkey.sql b/horde/scripts/upgrades/2010-05-11_horde_activesync_adduserkey.sql new file mode 100644 index 000000000..88f0d9f3a --- /dev/null +++ b/horde/scripts/upgrades/2010-05-11_horde_activesync_adduserkey.sql @@ -0,0 +1,21 @@ +ALTER TABLE horde_activesync_state ADD COLUMN sync_user VARCHAR(255); + +ALTER TABLE horde_activesync_device DROP COLUMN device_user; +ALTER TABLE horde_activesync_device DROP COLUMN device_ping; +ALTER TABLE horde_activesync_device DROP COLUMN device_folders; + +DROP INDEX activesync_device_user_idx; + +CREATE TABLE horde_activesync_device_users ( + device_id VARCHAR(255) NOT NULL, + device_user VARCHAR(255) NOT NULL, + device_ping TEXT, + device_folders TEXT, +-- + PRIMARY KEY (device_id, device_user) +); +CREATE INDEX activesync_device_users_idx ON horde_activesync_device_users (device_user); + +ALTER TABLE horde_activesync_map ADD COLUMN sync_user VARCHAR(255); +CREATE INDEX activesync_map_user_idx ON horde_activesync_map (sync_user); + diff --git a/horde/templates/prefs/activesync.html b/horde/templates/prefs/activesync.html index 3d5f4a46f..9f11dcc06 100644 --- a/horde/templates/prefs/activesync.html +++ b/horde/templates/prefs/activesync.html @@ -9,6 +9,7 @@ + @@ -25,7 +26,7 @@ - + -- 2.11.0