From: Michael J. Rubinsky Date: Mon, 25 Oct 2010 18:13:16 +0000 (-0400) Subject: Move Horde specific ActiveSync driver classes to Horde/Core X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=f403a97ccc47cc7a58b28dbe455b04166df96d6e;p=horde.git Move Horde specific ActiveSync driver classes to Horde/Core --- diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde.php b/framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde.php deleted file mode 100644 index a63efda10..000000000 --- a/framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde.php +++ /dev/null @@ -1,782 +0,0 @@ - - * @package Horde_ActiveSync - */ -/*********************************************** -* File : horde.php -* Project : Z-Push -* Descr : Horde backend -* Created : 09.03.2009 -* -* � Holger de Carne holger@carne.de -* This file is distributed under GPL v2. -* Consult LICENSE file for details -************************************************/ -class Horde_ActiveSync_Driver_Horde extends Horde_ActiveSync_Driver_Base -{ - /** Constants **/ - const APPOINTMENTS_FOLDER = 'Calendar'; - const CONTACTS_FOLDER = 'Contacts'; - const TASKS_FOLDER = 'Tasks'; - - /** - * Cache message stats - * - * @var Array of stat hashes - */ - private $_modCache; - - /** - * Horde connector instance - * - * @var Horde_ActiveSync_Driver_Horde_Connector_Registry - */ - private $_connector; - - /** - * Const'r - *
-     * Required params (in addition to the base class' requirements):
-     *   connector => Horde_ActiveSync_Driver_Horde_Connector_Registry object
-     *   auth      => Horde_Auth object
-     * 
- * - * @param array $params Configuration parameters. - * - * @return Horde_ActiveSync_Driver_Horde - */ - public function __construct($params = array()) - { - parent::__construct($params); - if (empty($this->_params['connector'])) { - throw new InvalidArgumentException('Missing required connector object.'); - } - - if (empty($this->_params['auth'])) { - throw new InvalidArgumentException('Missing required Auth object'); - } - - $this->_connector = $params['connector']; - $this->_auth = $params['auth']; - } - - /** - * Authenticate to Horde - * - * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#Logon($username, $domain, $password) - */ - public function logon($username, $password, $domain = null) - { - $this->_logger->info('Horde_ActiveSync_Driver_Horde::logon attempt for: ' . $username); - parent::logon($username, $password, $domain); - - return $this->_auth->authenticate($username, array('password' => $password)); - } - - /** - * Clean up - * - * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#Logoff() - */ - public function logOff() - { - $this->_logger->info('User ' . $this->_user . ' logged off'); - return true; - } - - /** - * Setup sync parameters. The user provided here is the user the backend - * will sync with. This allows you to authenticate as one user, and sync as - * another, if the backend supports this. - * - * @param string $user The username to sync as on the backend. - * - * @return boolean - */ - public function setup($user) - { - parent::setup($user); - $this->_modCache = array(); - return true; - } - - /** - * @TODO - * - * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#getWasteBasket() - */ - public function getWasteBasket() - { - $this->_logger->debug('Horde::getWasteBasket()'); - - return false; - } - - /** - * Return a list of available folders - * - * @return array An array of folder stats - */ - public function getFolderList() - { - ob_start(); - - $this->_logger->debug('Horde::getFolderList()'); - /* Make sure we have the APIs needed for each folder class */ - try { - $supported = $this->_connector->horde_listApis(); - } catch (Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return array(); - } - $folders = array(); - - if (array_search('calendar', $supported)){ - $folders[] = $this->statFolder(self::APPOINTMENTS_FOLDER); - } - - if (array_search('contacts', $supported)){ - $folders[] = $this->statFolder(self::CONTACTS_FOLDER); - } - - if (array_search('tasks', $supported)){ - $folders[] = $this->statFolder(self::TASKS_FOLDER); - } - - if ($errors = Horde::endBuffer()) { - $this->_logger->err('Unexpected output: ' . $errors); - } - $this->_endBuffer(); - - return $folders; - } - - /** - * Retrieve folder - * - * @param string $id The folder id - * - * @return Horde_ActiveSync_Message_Folder - */ - public function getFolder($id) - { - $this->_logger->debug('Horde::getFolder(' . $id . ')'); - - $folder = new Horde_ActiveSync_Message_Folder(); - $folder->serverid = $id; - $folder->parentid = "0"; - $folder->displayname = $id; - - switch ($id) { - case self::APPOINTMENTS_FOLDER: - $folder->type = Horde_ActiveSync::FOLDER_TYPE_APPOINTMENT; - break; - case self::CONTACTS_FOLDER: - $folder->type = Horde_ActiveSync::FOLDER_TYPE_CONTACT; - break; - case self::TASKS_FOLDER: - $folder->type = Horde_ActiveSync::FOLDER_TYPE_TASK; - break; - default: - return false; - } - - return $folder; - } - - /** - * Stat folder - * - * @param $id - * - * @return a stat hash - */ - public function statFolder($id) - { - $this->_logger->debug('Horde::statFolder(' . $id . ')'); - - $folder = array(); - $folder['id'] = $id; - $folder['mod'] = $id; - $folder['parent'] = 0; - - return $folder; - } - - /** - * Get the message list of specified folder - * - * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#getMessageList($folderId, $cutOffDate) - */ - public function getMessageList($folderid, $cutoffdate) - { - $this->_logger->debug('Horde::getMessageList(' . $folderid . ', ' . $cutoffdate . ')'); - ob_start(); - $messages = array(); - - switch ($folderid) { - case self::APPOINTMENTS_FOLDER: - $startstamp = (int)$cutoffdate; - $endstamp = time() + 32140800; //60 * 60 * 24 * 31 * 12 == one year - - try { - $events = $this->_connector->calendar_listUids($startstamp, $endstamp); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return array(); - } - foreach ($events as $uid) { - $messages[] = $this->_smartStatMessage($folderid, $uid, false); - } - break; - - case self::CONTACTS_FOLDER: - try { - $contacts = $this->_connector->contacts_listUids(); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return array(); - } - - foreach ($contacts as $contact) { - $messages[] = $this->_smartStatMessage($folderid, $contact, false); - } - break; - - case self::TASKS_FOLDER: - try { - $tasks = $this->_connector->tasks_listUids(); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return array(); - } - foreach ($tasks as $task) - { - $messages[] = $this->_smartStatMessage($folderid, $task, false); - } - break; - - default: - $this->_endBuffer(); - return array(); - } - - $this->_endBuffer(); - return $messages; - } - - /** - * Get a list of server changes that occured during the specified time - * period. - * - * @param string $folderId The server id of the collection to check. - * @param integer $from_ts The starting timestamp - * @param integer $to_ts The ending timestamp - * - * @return array A list of messge uids that have chnaged in the specified - * time period. - */ - public function getServerChanges($folderId, $from_ts, $to_ts, $cutoffdate) - { - $this->_logger->debug("Horde_ActiveSync_Driver_Horde::getServerChanges($folderId, $from_ts, $to_ts, $cutoffdate)"); - $adds = array(); - - ob_start(); - switch ($folderId) { - case self::APPOINTMENTS_FOLDER: - if ($from_ts == 0) { - /* Can't use History if it's a first sync */ - $startstamp = (int)$cutoffdate; - $endstamp = time() + 32140800; //60 * 60 * 24 * 31 * 12 == one year - try { - $adds = $this->_connector->calendar_listUids($startstamp, $endstamp); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return array(); - } - $edits = $deletes = array(); - } else { - try { - $changes = $this->_connector->calendar_getChanges($from_ts, $to_ts); - // @TODO: these assignments are just until all collections are refactored. - $adds = $changes['add']; - $edits = $changes['modify']; - $deletes = $changes['delete']; - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return array(); - } - } - break; - case self::CONTACTS_FOLDER: - /* Can't use History for first sync */ - if ($from_ts == 0) { - try { - $adds = $this->_connector->contacts_listUids(); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return array(); - } - $edits = $deletes = array(); - } else { - try { - $adds = $this->_connector->contacts_listBy('add', $from_ts, $to_ts); - $edits = $this->_connector->contacts_listBy('modify', $from_ts, $to_ts); - $deletes = $this->_connector->contacts_listBy('delete', $from_ts, $to_ts); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return array(); - } - } - break; - case self::TASKS_FOLDER: - /* Can't use History for first sync */ - if ($from_ts == 0) { - try { - $adds = $this->_connector->tasks_listUids(); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return array(); - } - $edits = $deletes = array(); - } else { - try { - $adds = $this->_connector->tasks_listBy('add', $from_ts, $to_ts); - $edits = $this->_connector->tasks_listBy('modify', $from_ts, $to_ts); - $deletes = $this->_connector->tasks_listBy('delete', $from_ts, $to_ts); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return array(); - } - } - break; - } - - /* Build the changes array */ - $changes = array(); - - /* Server additions */ - foreach ($adds as $add) { - $changes[] = array( - 'id' => $add, - 'type' => 'change', - 'flags' => Horde_ActiveSync::FLAG_NEWMESSAGE); - } - - /* Server changes */ - foreach ($edits as $change) { - $changes[] = array( - 'id' => $change, - 'type' => 'change'); - } - - /* Server Deletions */ - foreach ($deletes as $deleted) { - $changes[] = array( - 'id' => $deleted, - 'type' => 'delete'); - } - - $this->_endBuffer(); - return $changes; - } - - /** - * Get a message from the backend - * - * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#getMessage - */ - public function getMessage($folderid, $id, $truncsize, $mimesupport = 0) - { - $this->_logger->debug('Horde::getMessage(' . $folderid . ', ' . $id . ')'); - ob_start(); - $message = false; - switch ($folderid) { - case self::APPOINTMENTS_FOLDER: - try { - $message = $this->_connector->calendar_export($id); - // Nokia MfE requires the optional UID element. - if (!$message->getUid()) { - $message->setUid(pack("H*" , md5($id))); - } - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return false; - } - break; - - case self::CONTACTS_FOLDER: - try { - $message = $this->_connector->contacts_export($id); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return false; - } - break; - - case self::TASKS_FOLDER: - try { - $message = $this->_connector->tasks_export($id); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return false; - } - break; - default: - $this->_endBuffer(); - return false; - } - if (strlen($message->body) > $truncsize) { - $message->body = self::truncate($message->body, $truncsize); - $message->bodytruncated = 1; - } else { - // Be certain this is set. - $message->bodytruncated = 0; - } - - $this->_endBuffer(); - return $message; - } - - /** - * Get message stat data - * - * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#statMessage($folderId, $id) - */ - public function statMessage($folderid, $id) - { - return $this->_smartStatMessage($folderid, $id, true); - } - - /** - * Delete a message - * - * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#deleteMessage($folderid, $id) - */ - public function deleteMessage($folderid, $id) - { - $this->_logger->debug('Horde::deleteMessage(' . $folderid . ', ' . $id . ')'); - ob_start(); - $status = false; - switch ($folderid) { - case self::APPOINTMENTS_FOLDER: - try { - $status = $this->_connector->calendar_delete($id); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return false; - } - break; - - case self::CONTACTS_FOLDER: - try { - $status = $this->_connector->contacts_delete($id); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return false; - } - break; - - case self::TASKS_FOLDER: - try { - $status = $this->_connector->tasks_delete($id); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return false; - } - break; - default: - $this->_endBuffer(); - return false; - } - - $this->_endBuffer(); - return $status; - } - - /** - * Add/Edit a message - * - * @param string $folderid The server id for the folder the message belongs - * to. - * @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 object $device The device information - * - * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#changeMessage($folderid, $id, $message) - */ - public function changeMessage($folderid, $id, $message, $device) - { - $this->_logger->debug('Horde::changeMessage(' . $folderid . ', ' . $id . ')'); - ob_start(); - $stat = false; - switch ($folderid) { - case self::APPOINTMENTS_FOLDER: - if (!$id) { - try { - $id = $this->_connector->calendar_import($message); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return false; - } - // There is no history entry for new messages, so use the - // current time for purposes of remembering this is from the PIM - $stat = $this->_smartStatMessage($folderid, $id, false); - $stat['mod'] = time(); - } else { - // ActiveSync messages do NOT contain the serverUID value, put - // it in ourselves so we can have it during import/change. - $message->setServerUID($id); - if (!empty($device->supported[self::APPOINTMENTS_FOLDER])) { - $message->setSupported($device->supported[self::APPOINTMENTS_FOLDER]); - } - try { - $this->_connector->calendar_replace($id, $message); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return false; - } - $stat = $this->_smartStatMessage($folderid, $id, false); - } - break; - - case self::CONTACTS_FOLDER: - if (!$id) { - try { - $id = $this->_connector->contacts_import($message); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return false; - } - $stat = $this->_smartStatMessage($folderid, $id, false); - $stat['mod'] = time(); - } else { - if (!empty($device->supported[self::CONTACTS_FOLDER])) { - $message->setSupported($device->supported[self::CONTACTS_FOLDER]); - } - try { - $this->_connector->contacts_replace($id, $message); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return false; - } - $stat = $this->_smartStatMessage($folderid, $id, false); - } - break; - - case self::TASKS_FOLDER: - if (!$id) { - try { - $id = $this->_connector->tasks_import($message); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return false; - } - $stat = $this->_smartStatMessage($folderid, $id, false); - $stat['mod'] = time(); - } else { - if (!empty($device->supported[self::TASKS_FOLDER])) { - $message->setSupported($device->supported[self::TASKS_FOLDER]); - } - try { - $this->_connector->tasks_replace($id, $message); - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return false; - } - $stat = $this->_smartStatMessage($folderid, $id, false); - } - break; - - default: - $this->_endBuffer(); - return false; - } - - $this->_endBuffer(); - return $stat; - } - - /** - * Returns array of items which contain contact information - * - * @param string $query The text string to match against any textual ANR - * (Automatic Name Resolution) properties. Exchange's - * searchable ANR properties are currently: - * firstname, lastname, alias, displayname, email - * @param string $range The range to return (for example, 1-50). - * - * @return array with 'rows' and 'range' keys - */ - public function getSearchResults($query, $range) - { - $return = array('rows' => array(), - 'range' => $range); - - ob_start(); - try { - $results = $this->_connector->contacts_search($query); - } catch (Horde_ActiveSync_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return $return; - } - - /* Honor range, and don't bother if no results */ - $count = count($results); - if (!$count) { - return $return; - } - $this->_logger->info('Horde::getSearchResults found ' . $count . ' matches.'); - - preg_match('/(.*)\-(.*)/', $range, $matches); - $return_count = $matches[2] - $matches[1]; - $rows = array_slice($results, $matches[1], $return_count + 1, true); - $rows = array_pop($rows); - foreach ($rows as $row) { - $return['rows'][] = array( - Horde_ActiveSync::GAL_ALIAS => $row['alias'], - Horde_ActiveSync::GAL_DISPLAYNAME => $row['name'], - Horde_ActiveSync::GAL_EMAILADDRESS => $row['email'], - Horde_ActiveSync::GAL_FIRSTNAME => $row['firstname'], - Horde_ActiveSync::GAL_LASTNAME => $row['lastname'], - Horde_ActiveSync::GAL_COMPANY => $row['company'], - Horde_ActiveSync::GAL_HOMEPHONE => $row['homePhone'], - Horde_ActiveSync::GAL_PHONE => $row['workPhone'] - ); - } - - $this->_endBuffer(); - return $return; - } - - /** - * Sends the email represented by the rfc822 string received by the PIM. - * Currently only used when meeting requests are sent from the PIM. - * - * @param string $rfc822 The rfc822 mime message - * @param boolean $forward @TODO - * @param boolean $reply @TODO - * @param boolean $parent @TODO - * - * @return boolean - */ - public function sendMail($rfc822, $forward = false, $reply = false, $parent = false) - { - $headers = Horde_Mime_Headers::parseHeaders($rfc822); - $part = Horde_Mime_Part::parseMessage($rfc822); - - $mail = new Horde_Mime_Mail(); - $mail->addHeaders($headers->toArray()); - - $body_id = $part->findBody(); - if ($body_id) { - $body = $part->getPart($body_id); - $body = $body->getContents(); - $mail->setBody($body); - } else { - $mail->setBody('No body?'); - } - foreach ($part->contentTypeMap() as $id => $type) { - $mail->addPart($type, $part->getPart($id)->toString()); - } - - $mail->send($this->_params['mail']); - - return true; - } - - /** - * - * @param string $folderid The folder id - * @param string $id The message id - * @param mixed $hint @TODO: Figure out what, exactly, this does :) - * - * @return message stat hash - */ - private function _smartStatMessage($folderid, $id, $hint) - { - ob_start(); - $this->_logger->debug('ActiveSync_Driver_Horde::_smartStatMessage:' . $folderid . ':' . $id); - $statKey = $folderid . $id; - $mod = false; - - if ($hint !== false && isset($this->_modCache[$statKey])) { - $mod = $this->_modCache[$statKey]; - } elseif (is_int($hint)) { - $mod = $hint; - $this->_modCache[$statKey] = $mod; - } else { - try { - switch ($folderid) { - case self::APPOINTMENTS_FOLDER: - $mod = $this->_connector->calendar_getActionTimestamp($id, 'modify'); - break; - - case self::CONTACTS_FOLDER: - $mod = $this->_connector->contacts_getActionTimestamp($id, 'modify'); - break; - - case self::TASKS_FOLDER: - $mod = $this->_connector->tasks_getActionTimestamp($id, 'modify'); - break; - - default: - $this->_endBuffer(); - return false; - } - } catch (Horde_Exception $e) { - $this->_logger->err($e->getMessage()); - $this->_endBuffer(); - return array('id' => '', 'mod' => 0, 'flags' => 1); - } - $this->_modCache[$statKey] = $mod; - } - - $message = array(); - $message['id'] = $id; - $message['mod'] = $mod; - $message['flags'] = 1; - - $this->_endBuffer(); - return $message; - } - - private function _endBuffer() - { - if ($output = ob_get_clean()) { - $this->_logger->err('Unexpected output: ' . $output); - } - } - -} diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde/Connector/Registry.php b/framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde/Connector/Registry.php deleted file mode 100644 index cb1d2f239..000000000 --- a/framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde/Connector/Registry.php +++ /dev/null @@ -1,395 +0,0 @@ - - * @package Horde_ActiveSync - */ -class Horde_ActiveSync_Driver_Horde_Connector_Registry -{ - /** - * Horde registry - * - * @var Horde_Registry - */ - private $_registry; - - /** - * Const'r - * - * @param array $params Configuration parameters. Requires: - *
-     *   'registry' - An instance of Horde_Registry
-     * 
- * - * @return Horde_ActiveSync_Driver_Horde_Connector_Registry - */ - public function __construct($params = array()) - { - if (empty($params['registry'])) { - throw new InvalidArgumentException('Missing required Horde_Registry object.'); - } - - $this->_registry = $params['registry']; - } - - /** - * Get a list of events from horde's calendar api - * - * @param integer $startstamp The start of time period. - * @param integer $endstamp The end of time period - * - * @return array - */ - public function calendar_listUids($startstamp, $endstamp) - { - try { - return $this->_registry->calendar->listUids(null, $startstamp, $endstamp); - } catch (Exception $e) { - return array(); - } - } - - /** - * Get a list of event uids that have had $action happen since $from_ts. - * - * @param string $action The action to check for (add, modify, delete) - * @param integer $from_ts The timestamp to start checking from - * @param integer $to_ts The ending timestamp - * - * @return array An array of event uids - */ - public function calendar_listBy($action, $from_ts, $to_ts) - { - try { - $uids = $this->_registry->calendar->listBy($action, $from_ts, null, $to_ts); - } catch (Exception $e) { - return array(); - } - } - - /** - * Obtain all calendar server chages that occured in the specified time - * interval. - * - * @param integer $from_ts Starting timestamp - * @param integer $to_ts Ending timestamp - * - * @return array Hash of add, modify, and delete arrays - */ - public function calendar_getChanges($from_ts, $to_ts) - { - try { - return $this->_registry->calendar->getChanges($from_ts, $to_ts); - } catch (Exception $e) { - return array('add' => array(), - 'modify' => array(), - 'delete' => array()); - } - } - - /** - * Export the specified event as an ActiveSync message - * - * @param string $uid The calendar id - * - * @return Horde_ActiveSync_Message_Appointment - */ - public function calendar_export($uid) - { - return $this->_registry->calendar->export($uid, 'activesync'); - } - - /** - * Import an event into Horde's calendar store. - * - * @param Horde_ActiveSync_Message_Appointment $content The event content - * @param string $calendar The calendar to import event into - * - * @return string The event's UID - */ - public function calendar_import($content) - { - return $this->_registry->calendar->import($content, 'activesync'); - } - - /** - * Replace the event with new data - * - * @param string $uid The UID of the event to replace - * @param Horde_ActiveSync_Message_Appointment $content The new event content - * - * @return boolean - */ - public function calendar_replace($uid, $content) - { - return $this->_registry->calendar->replace($uid, $content, 'activesync'); - } - - /** - * Delete an event from Horde's calendar storage - * - * @param string $uid The UID of the event to delete - * - * @return boolean - */ - public function calendar_delete($uid) - { - return $this->_registry->calendar->delete($uid); - } - - /** - * Return the timestamp for the last time $action was performed. - * - * @param string $uid The UID of the event we are interested in. - * @param string $action The action we are interested in (add, modify...) - * - * @return integer - */ - public function calendar_getActionTimestamp($uid, $action) - { - return $this->_registry->calendar->getActionTimestamp($uid, $action); - } - - /** - * Get a list of all contacts a user can see - * - * @return array of contact UIDs - */ - public function contacts_listUids() - { - return $this->_registry->contacts->listUids(); - } - - /** - * Export the specified contact from Horde's contacts storage - * - * @param string $uid The contact's UID - * - * @return array The contact hash - */ - public function contacts_export($uid) - { - return $this->_registry->contacts->export($uid, 'activesync'); - } - - /** - * Import the provided contact data into Horde's contacts storage - * - * @param string $content The contact data - * @param string $source The contact source to import to - * - * @return boolean - */ - public function contacts_import($content, $import_source = null) - { - return $this->_registry->contacts->import($content, 'activesync', $import_source); - } - - /** - * Replace the specified contact with the data provided. - * - * @param string $uid The UID of the contact to replace - * @param string $content The contact data - * @param string $sources The sources where UID will be replaced - * - * @return boolean - */ - public function contacts_replace($uid, $content, $sources = null) - { - return $this->_registry->contacts->replace($uid, $content, 'activesync', $sources); - } - - /** - * Delete the specified contact - * - * @param string $uid The UID of the contact to remove - * - * @return bolean - */ - public function contacts_delete($uid) - { - return $this->_registry->contacts->delete($uid); - } - - /** - * Get the timestamp of the most recent occurance of $action for the - * specifed contact - * - * @param string $uid The UID of the contact to search - * @param string $action The action to lookup - * - * @return integer - */ - public function contacts_getActionTimestamp($uid, $action) - { - return $this->_registry->contacts->getActionTimestamp($uid, $action); - } - - /** - * Get a list of contact uids that have had $action happen since $from_ts. - * - * @param string $action The action to check for (add, modify, delete) - * @param integer $from_ts The timestamp to start checking from - * @param integer $to_ts The ending timestamp - * - * @return array An array of event uids - */ - public function contacts_listBy($action, $from_ts, $to_ts) - { - return $this->_registry->contacts->listBy($action, $from_ts, null, $to_ts); - } - - public function contacts_search($query) - { - $gal = $this->contacts_getGal(); - $fields = array($gal => array('firstname', 'lastname', 'alias', 'name', 'email')); - return $this->_registry->contacts->search(array($query), array($gal), $fields, true, true); - } - - /** - * Get the GAL source uid. - * - * @return string | boolean - */ - public function contacts_getGal() - { - return $this->_registry->contacts->getGalUid(); - } - - /** - * List all tasks in the user's default tasklist. - * - * @return array An array of task uids. - */ - public function tasks_listUids() - { - $app = $this->horde_hasInterface('tasks'); - $tasklist = $this->horde_getPref($app, 'default_tasklist'); - return $this->_registry->tasks->listUids($tasklist); - } - - public function tasks_listTaskLists() - { - return $this->_registry->tasks->listTaskLists(); - } - - /** - * Export a single task from the backend. - * - * @param string $uid The task uid - * - * @return Horde_ActiveSync_Message_Task The task message object - */ - public function tasks_export($uid) - { - return $this->_registry->tasks->export($uid, 'activesync'); - } - - /** - * Importa a single task into the backend. - * - * @param Horde_ActiveSync_Message_Task $message The task message object - * - * @return string The newly added task's uid. - */ - public function tasks_import($message) - { - return $this->_registry->tasks->import($message, 'activesync'); - } - - /** - * Replace an existing task with the provided task. - * - * @param string $uid The existing tasks's uid - * @param Horde_ActiveSync_Message_Task $message The task object - * - * @return boolean - */ - public function tasks_replace($uid, $message) - { - return $this->_registry->tasks->replace($uid, $message, 'activesync'); - } - - /** - * Delete a task from the backend. - * - * @param string $id The task's uid - * - * @return boolean - */ - public function tasks_delete($id) - { - return $this->_registry->tasks->delete($id); - } - - /** - * Return the timestamp for the last time $action was performed. - * - * @param string $uid The UID of the task we are interested in. - * @param string $action The action we are interested in (add, modify...) - * - * @return integer - */ - public function tasks_getActionTimestamp($uid, $action) - { - return $this->_registry->tasks->getActionTimestamp($uid, $action); - } - - /** - * Get a list of task uids that have had $action happen since $from_ts. - * - * @param string $action The action to check for (add, modify, delete) - * @param integer $from_ts The timestamp to start checking from - * @param integer $to_ts The ending timestamp - * - * @return array An array of event uids - */ - public function tasks_listBy($action, $from_ts) - { - return $this->_registry->tasks->listBy($action, $from_ts, null, $to_ts); - } - - /** - * Return all active api interfaces. - * - * @return array An array of interface names. - */ - public function horde_listApis() - { - return $this->_registry->horde->listAPIs(); - } - - /** - * Obtain a user's preference setting. - * - * @param string $app The Horde application providing the setting. - * @param string $pref The name of the preference setting. - * - * @return mixed The preference value - */ - public function horde_getPref($app, $pref) - { - return $this->_registry->horde->getPreference($app, $pref); - } - - /** - * Obtain the name of the Horde application that provides the specified api - * interface. - * - * @param string $api The interface name - * - * @return string The application name. - */ - public function horde_hasInterface($api) - { - return $this->_registry->hasInterface($api); - } - -} \ No newline at end of file diff --git a/framework/ActiveSync/package.xml b/framework/ActiveSync/package.xml index b583d6583..9f0b30208 100644 --- a/framework/ActiveSync/package.xml +++ b/framework/ActiveSync/package.xml @@ -10,8 +10,8 @@ mrubinsk@horde.org yes - 2010-10-22 - + 2010-10-25 + 0.1.0 0.1.0 @@ -37,13 +37,7 @@ - - - - - - @@ -133,8 +127,6 @@ - - @@ -184,7 +176,7 @@ alpha alpha - 2010-10-22 + 2010-10-25 GPLv2 * Initial release diff --git a/framework/Core/lib/Horde/Core/ActiveSync/Connector.php b/framework/Core/lib/Horde/Core/ActiveSync/Connector.php new file mode 100644 index 000000000..c91fe2e90 --- /dev/null +++ b/framework/Core/lib/Horde/Core/ActiveSync/Connector.php @@ -0,0 +1,395 @@ + + * @package Horde_ActiveSync + */ +class Horde_Core_ActiveSync_Connector +{ + /** + * Horde registry + * + * @var Horde_Registry + */ + private $_registry; + + /** + * Const'r + * + * @param array $params Configuration parameters. Requires: + *
+     *   'registry' - An instance of Horde_Registry
+     * 
+ * + * @return Horde_ActiveSync_Driver_Horde_Connector_Registry + */ + public function __construct($params = array()) + { + if (empty($params['registry'])) { + throw new InvalidArgumentException('Missing required Horde_Registry object.'); + } + + $this->_registry = $params['registry']; + } + + /** + * Get a list of events from horde's calendar api + * + * @param integer $startstamp The start of time period. + * @param integer $endstamp The end of time period + * + * @return array + */ + public function calendar_listUids($startstamp, $endstamp) + { + try { + return $this->_registry->calendar->listUids(null, $startstamp, $endstamp); + } catch (Exception $e) { + return array(); + } + } + + /** + * Get a list of event uids that have had $action happen since $from_ts. + * + * @param string $action The action to check for (add, modify, delete) + * @param integer $from_ts The timestamp to start checking from + * @param integer $to_ts The ending timestamp + * + * @return array An array of event uids + */ + public function calendar_listBy($action, $from_ts, $to_ts) + { + try { + $uids = $this->_registry->calendar->listBy($action, $from_ts, null, $to_ts); + } catch (Exception $e) { + return array(); + } + } + + /** + * Obtain all calendar server chages that occured in the specified time + * interval. + * + * @param integer $from_ts Starting timestamp + * @param integer $to_ts Ending timestamp + * + * @return array Hash of add, modify, and delete arrays + */ + public function calendar_getChanges($from_ts, $to_ts) + { + try { + return $this->_registry->calendar->getChanges($from_ts, $to_ts); + } catch (Exception $e) { + return array('add' => array(), + 'modify' => array(), + 'delete' => array()); + } + } + + /** + * Export the specified event as an ActiveSync message + * + * @param string $uid The calendar id + * + * @return Horde_ActiveSync_Message_Appointment + */ + public function calendar_export($uid) + { + return $this->_registry->calendar->export($uid, 'activesync'); + } + + /** + * Import an event into Horde's calendar store. + * + * @param Horde_ActiveSync_Message_Appointment $content The event content + * @param string $calendar The calendar to import event into + * + * @return string The event's UID + */ + public function calendar_import($content) + { + return $this->_registry->calendar->import($content, 'activesync'); + } + + /** + * Replace the event with new data + * + * @param string $uid The UID of the event to replace + * @param Horde_ActiveSync_Message_Appointment $content The new event content + * + * @return boolean + */ + public function calendar_replace($uid, $content) + { + return $this->_registry->calendar->replace($uid, $content, 'activesync'); + } + + /** + * Delete an event from Horde's calendar storage + * + * @param string $uid The UID of the event to delete + * + * @return boolean + */ + public function calendar_delete($uid) + { + return $this->_registry->calendar->delete($uid); + } + + /** + * Return the timestamp for the last time $action was performed. + * + * @param string $uid The UID of the event we are interested in. + * @param string $action The action we are interested in (add, modify...) + * + * @return integer + */ + public function calendar_getActionTimestamp($uid, $action) + { + return $this->_registry->calendar->getActionTimestamp($uid, $action); + } + + /** + * Get a list of all contacts a user can see + * + * @return array of contact UIDs + */ + public function contacts_listUids() + { + return $this->_registry->contacts->listUids(); + } + + /** + * Export the specified contact from Horde's contacts storage + * + * @param string $uid The contact's UID + * + * @return array The contact hash + */ + public function contacts_export($uid) + { + return $this->_registry->contacts->export($uid, 'activesync'); + } + + /** + * Import the provided contact data into Horde's contacts storage + * + * @param string $content The contact data + * @param string $source The contact source to import to + * + * @return boolean + */ + public function contacts_import($content, $import_source = null) + { + return $this->_registry->contacts->import($content, 'activesync', $import_source); + } + + /** + * Replace the specified contact with the data provided. + * + * @param string $uid The UID of the contact to replace + * @param string $content The contact data + * @param string $sources The sources where UID will be replaced + * + * @return boolean + */ + public function contacts_replace($uid, $content, $sources = null) + { + return $this->_registry->contacts->replace($uid, $content, 'activesync', $sources); + } + + /** + * Delete the specified contact + * + * @param string $uid The UID of the contact to remove + * + * @return bolean + */ + public function contacts_delete($uid) + { + return $this->_registry->contacts->delete($uid); + } + + /** + * Get the timestamp of the most recent occurance of $action for the + * specifed contact + * + * @param string $uid The UID of the contact to search + * @param string $action The action to lookup + * + * @return integer + */ + public function contacts_getActionTimestamp($uid, $action) + { + return $this->_registry->contacts->getActionTimestamp($uid, $action); + } + + /** + * Get a list of contact uids that have had $action happen since $from_ts. + * + * @param string $action The action to check for (add, modify, delete) + * @param integer $from_ts The timestamp to start checking from + * @param integer $to_ts The ending timestamp + * + * @return array An array of event uids + */ + public function contacts_listBy($action, $from_ts, $to_ts) + { + return $this->_registry->contacts->listBy($action, $from_ts, null, $to_ts); + } + + public function contacts_search($query) + { + $gal = $this->contacts_getGal(); + $fields = array($gal => array('firstname', 'lastname', 'alias', 'name', 'email')); + return $this->_registry->contacts->search(array($query), array($gal), $fields, true, true); + } + + /** + * Get the GAL source uid. + * + * @return string | boolean + */ + public function contacts_getGal() + { + return $this->_registry->contacts->getGalUid(); + } + + /** + * List all tasks in the user's default tasklist. + * + * @return array An array of task uids. + */ + public function tasks_listUids() + { + $app = $this->horde_hasInterface('tasks'); + $tasklist = $this->horde_getPref($app, 'default_tasklist'); + return $this->_registry->tasks->listUids($tasklist); + } + + public function tasks_listTaskLists() + { + return $this->_registry->tasks->listTaskLists(); + } + + /** + * Export a single task from the backend. + * + * @param string $uid The task uid + * + * @return Horde_ActiveSync_Message_Task The task message object + */ + public function tasks_export($uid) + { + return $this->_registry->tasks->export($uid, 'activesync'); + } + + /** + * Importa a single task into the backend. + * + * @param Horde_ActiveSync_Message_Task $message The task message object + * + * @return string The newly added task's uid. + */ + public function tasks_import($message) + { + return $this->_registry->tasks->import($message, 'activesync'); + } + + /** + * Replace an existing task with the provided task. + * + * @param string $uid The existing tasks's uid + * @param Horde_ActiveSync_Message_Task $message The task object + * + * @return boolean + */ + public function tasks_replace($uid, $message) + { + return $this->_registry->tasks->replace($uid, $message, 'activesync'); + } + + /** + * Delete a task from the backend. + * + * @param string $id The task's uid + * + * @return boolean + */ + public function tasks_delete($id) + { + return $this->_registry->tasks->delete($id); + } + + /** + * Return the timestamp for the last time $action was performed. + * + * @param string $uid The UID of the task we are interested in. + * @param string $action The action we are interested in (add, modify...) + * + * @return integer + */ + public function tasks_getActionTimestamp($uid, $action) + { + return $this->_registry->tasks->getActionTimestamp($uid, $action); + } + + /** + * Get a list of task uids that have had $action happen since $from_ts. + * + * @param string $action The action to check for (add, modify, delete) + * @param integer $from_ts The timestamp to start checking from + * @param integer $to_ts The ending timestamp + * + * @return array An array of event uids + */ + public function tasks_listBy($action, $from_ts) + { + return $this->_registry->tasks->listBy($action, $from_ts, null, $to_ts); + } + + /** + * Return all active api interfaces. + * + * @return array An array of interface names. + */ + public function horde_listApis() + { + return $this->_registry->horde->listAPIs(); + } + + /** + * Obtain a user's preference setting. + * + * @param string $app The Horde application providing the setting. + * @param string $pref The name of the preference setting. + * + * @return mixed The preference value + */ + public function horde_getPref($app, $pref) + { + return $this->_registry->horde->getPreference($app, $pref); + } + + /** + * Obtain the name of the Horde application that provides the specified api + * interface. + * + * @param string $api The interface name + * + * @return string The application name. + */ + public function horde_hasInterface($api) + { + return $this->_registry->hasInterface($api); + } + +} \ No newline at end of file diff --git a/framework/Core/lib/Horde/Core/ActiveSync/Driver.php b/framework/Core/lib/Horde/Core/ActiveSync/Driver.php new file mode 100644 index 000000000..07b18f91f --- /dev/null +++ b/framework/Core/lib/Horde/Core/ActiveSync/Driver.php @@ -0,0 +1,782 @@ + + * @package Horde_ActiveSync + */ +/*********************************************** +* File : horde.php +* Project : Z-Push +* Descr : Horde backend +* Created : 09.03.2009 +* +* � Holger de Carne holger@carne.de +* This file is distributed under GPL v2. +* Consult LICENSE file for details +************************************************/ +class Horde_Core_ActiveSync_Driver extends Horde_ActiveSync_Driver_Base +{ + /** Constants **/ + const APPOINTMENTS_FOLDER = 'Calendar'; + const CONTACTS_FOLDER = 'Contacts'; + const TASKS_FOLDER = 'Tasks'; + + /** + * Cache message stats + * + * @var Array of stat hashes + */ + private $_modCache; + + /** + * Horde connector instance + * + * @var Horde_ActiveSync_Driver_Horde_Connector_Registry + */ + private $_connector; + + /** + * Const'r + *
+     * Required params (in addition to the base class' requirements):
+     *   connector => Horde_ActiveSync_Driver_Horde_Connector_Registry object
+     *   auth      => Horde_Auth object
+     * 
+ * + * @param array $params Configuration parameters. + * + * @return Horde_ActiveSync_Driver_Horde + */ + public function __construct($params = array()) + { + parent::__construct($params); + if (empty($this->_params['connector']) || !($this->_params['connector'] instanceof Horde_Core_ActiveSync_Connector)) { + throw new InvalidArgumentException('Missing required connector object.'); + } + + if (empty($this->_params['auth']) || !($this->_params['auth'] instanceof Horde_Auth_Base)) { + throw new InvalidArgumentException('Missing required Auth object'); + } + + $this->_connector = $params['connector']; + $this->_auth = $params['auth']; + } + + /** + * Authenticate to Horde + * + * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#Logon($username, $domain, $password) + */ + public function logon($username, $password, $domain = null) + { + $this->_logger->info('Horde_ActiveSync_Driver_Horde::logon attempt for: ' . $username); + parent::logon($username, $password, $domain); + + return $this->_auth->authenticate($username, array('password' => $password)); + } + + /** + * Clean up + * + * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#Logoff() + */ + public function logOff() + { + $this->_logger->info('User ' . $this->_user . ' logged off'); + return true; + } + + /** + * Setup sync parameters. The user provided here is the user the backend + * will sync with. This allows you to authenticate as one user, and sync as + * another, if the backend supports this. + * + * @param string $user The username to sync as on the backend. + * + * @return boolean + */ + public function setup($user) + { + parent::setup($user); + $this->_modCache = array(); + return true; + } + + /** + * @TODO + * + * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#getWasteBasket() + */ + public function getWasteBasket() + { + $this->_logger->debug('Horde::getWasteBasket()'); + + return false; + } + + /** + * Return a list of available folders + * + * @return array An array of folder stats + */ + public function getFolderList() + { + ob_start(); + + $this->_logger->debug('Horde::getFolderList()'); + /* Make sure we have the APIs needed for each folder class */ + try { + $supported = $this->_connector->horde_listApis(); + } catch (Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return array(); + } + $folders = array(); + + if (array_search('calendar', $supported)){ + $folders[] = $this->statFolder(self::APPOINTMENTS_FOLDER); + } + + if (array_search('contacts', $supported)){ + $folders[] = $this->statFolder(self::CONTACTS_FOLDER); + } + + if (array_search('tasks', $supported)){ + $folders[] = $this->statFolder(self::TASKS_FOLDER); + } + + if ($errors = Horde::endBuffer()) { + $this->_logger->err('Unexpected output: ' . $errors); + } + $this->_endBuffer(); + + return $folders; + } + + /** + * Retrieve folder + * + * @param string $id The folder id + * + * @return Horde_ActiveSync_Message_Folder + */ + public function getFolder($id) + { + $this->_logger->debug('Horde::getFolder(' . $id . ')'); + + $folder = new Horde_ActiveSync_Message_Folder(); + $folder->serverid = $id; + $folder->parentid = "0"; + $folder->displayname = $id; + + switch ($id) { + case self::APPOINTMENTS_FOLDER: + $folder->type = Horde_ActiveSync::FOLDER_TYPE_APPOINTMENT; + break; + case self::CONTACTS_FOLDER: + $folder->type = Horde_ActiveSync::FOLDER_TYPE_CONTACT; + break; + case self::TASKS_FOLDER: + $folder->type = Horde_ActiveSync::FOLDER_TYPE_TASK; + break; + default: + return false; + } + + return $folder; + } + + /** + * Stat folder + * + * @param $id + * + * @return a stat hash + */ + public function statFolder($id) + { + $this->_logger->debug('Horde::statFolder(' . $id . ')'); + + $folder = array(); + $folder['id'] = $id; + $folder['mod'] = $id; + $folder['parent'] = 0; + + return $folder; + } + + /** + * Get the message list of specified folder + * + * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#getMessageList($folderId, $cutOffDate) + */ + public function getMessageList($folderid, $cutoffdate) + { + $this->_logger->debug('Horde::getMessageList(' . $folderid . ', ' . $cutoffdate . ')'); + ob_start(); + $messages = array(); + + switch ($folderid) { + case self::APPOINTMENTS_FOLDER: + $startstamp = (int)$cutoffdate; + $endstamp = time() + 32140800; //60 * 60 * 24 * 31 * 12 == one year + + try { + $events = $this->_connector->calendar_listUids($startstamp, $endstamp); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return array(); + } + foreach ($events as $uid) { + $messages[] = $this->_smartStatMessage($folderid, $uid, false); + } + break; + + case self::CONTACTS_FOLDER: + try { + $contacts = $this->_connector->contacts_listUids(); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return array(); + } + + foreach ($contacts as $contact) { + $messages[] = $this->_smartStatMessage($folderid, $contact, false); + } + break; + + case self::TASKS_FOLDER: + try { + $tasks = $this->_connector->tasks_listUids(); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return array(); + } + foreach ($tasks as $task) + { + $messages[] = $this->_smartStatMessage($folderid, $task, false); + } + break; + + default: + $this->_endBuffer(); + return array(); + } + + $this->_endBuffer(); + return $messages; + } + + /** + * Get a list of server changes that occured during the specified time + * period. + * + * @param string $folderId The server id of the collection to check. + * @param integer $from_ts The starting timestamp + * @param integer $to_ts The ending timestamp + * + * @return array A list of messge uids that have chnaged in the specified + * time period. + */ + public function getServerChanges($folderId, $from_ts, $to_ts, $cutoffdate) + { + $this->_logger->debug("Horde_ActiveSync_Driver_Horde::getServerChanges($folderId, $from_ts, $to_ts, $cutoffdate)"); + $adds = array(); + + ob_start(); + switch ($folderId) { + case self::APPOINTMENTS_FOLDER: + if ($from_ts == 0) { + /* Can't use History if it's a first sync */ + $startstamp = (int)$cutoffdate; + $endstamp = time() + 32140800; //60 * 60 * 24 * 31 * 12 == one year + try { + $adds = $this->_connector->calendar_listUids($startstamp, $endstamp); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return array(); + } + $edits = $deletes = array(); + } else { + try { + $changes = $this->_connector->calendar_getChanges($from_ts, $to_ts); + // @TODO: these assignments are just until all collections are refactored. + $adds = $changes['add']; + $edits = $changes['modify']; + $deletes = $changes['delete']; + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return array(); + } + } + break; + case self::CONTACTS_FOLDER: + /* Can't use History for first sync */ + if ($from_ts == 0) { + try { + $adds = $this->_connector->contacts_listUids(); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return array(); + } + $edits = $deletes = array(); + } else { + try { + $adds = $this->_connector->contacts_listBy('add', $from_ts, $to_ts); + $edits = $this->_connector->contacts_listBy('modify', $from_ts, $to_ts); + $deletes = $this->_connector->contacts_listBy('delete', $from_ts, $to_ts); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return array(); + } + } + break; + case self::TASKS_FOLDER: + /* Can't use History for first sync */ + if ($from_ts == 0) { + try { + $adds = $this->_connector->tasks_listUids(); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return array(); + } + $edits = $deletes = array(); + } else { + try { + $adds = $this->_connector->tasks_listBy('add', $from_ts, $to_ts); + $edits = $this->_connector->tasks_listBy('modify', $from_ts, $to_ts); + $deletes = $this->_connector->tasks_listBy('delete', $from_ts, $to_ts); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return array(); + } + } + break; + } + + /* Build the changes array */ + $changes = array(); + + /* Server additions */ + foreach ($adds as $add) { + $changes[] = array( + 'id' => $add, + 'type' => 'change', + 'flags' => Horde_ActiveSync::FLAG_NEWMESSAGE); + } + + /* Server changes */ + foreach ($edits as $change) { + $changes[] = array( + 'id' => $change, + 'type' => 'change'); + } + + /* Server Deletions */ + foreach ($deletes as $deleted) { + $changes[] = array( + 'id' => $deleted, + 'type' => 'delete'); + } + + $this->_endBuffer(); + return $changes; + } + + /** + * Get a message from the backend + * + * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#getMessage + */ + public function getMessage($folderid, $id, $truncsize, $mimesupport = 0) + { + $this->_logger->debug('Horde::getMessage(' . $folderid . ', ' . $id . ')'); + ob_start(); + $message = false; + switch ($folderid) { + case self::APPOINTMENTS_FOLDER: + try { + $message = $this->_connector->calendar_export($id); + // Nokia MfE requires the optional UID element. + if (!$message->getUid()) { + $message->setUid(pack("H*" , md5($id))); + } + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return false; + } + break; + + case self::CONTACTS_FOLDER: + try { + $message = $this->_connector->contacts_export($id); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return false; + } + break; + + case self::TASKS_FOLDER: + try { + $message = $this->_connector->tasks_export($id); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return false; + } + break; + default: + $this->_endBuffer(); + return false; + } + if (strlen($message->body) > $truncsize) { + $message->body = self::truncate($message->body, $truncsize); + $message->bodytruncated = 1; + } else { + // Be certain this is set. + $message->bodytruncated = 0; + } + + $this->_endBuffer(); + return $message; + } + + /** + * Get message stat data + * + * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#statMessage($folderId, $id) + */ + public function statMessage($folderid, $id) + { + return $this->_smartStatMessage($folderid, $id, true); + } + + /** + * Delete a message + * + * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#deleteMessage($folderid, $id) + */ + public function deleteMessage($folderid, $id) + { + $this->_logger->debug('Horde::deleteMessage(' . $folderid . ', ' . $id . ')'); + ob_start(); + $status = false; + switch ($folderid) { + case self::APPOINTMENTS_FOLDER: + try { + $status = $this->_connector->calendar_delete($id); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return false; + } + break; + + case self::CONTACTS_FOLDER: + try { + $status = $this->_connector->contacts_delete($id); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return false; + } + break; + + case self::TASKS_FOLDER: + try { + $status = $this->_connector->tasks_delete($id); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return false; + } + break; + default: + $this->_endBuffer(); + return false; + } + + $this->_endBuffer(); + return $status; + } + + /** + * Add/Edit a message + * + * @param string $folderid The server id for the folder the message belongs + * to. + * @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 object $device The device information + * + * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#changeMessage($folderid, $id, $message) + */ + public function changeMessage($folderid, $id, $message, $device) + { + $this->_logger->debug('Horde::changeMessage(' . $folderid . ', ' . $id . ')'); + ob_start(); + $stat = false; + switch ($folderid) { + case self::APPOINTMENTS_FOLDER: + if (!$id) { + try { + $id = $this->_connector->calendar_import($message); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return false; + } + // There is no history entry for new messages, so use the + // current time for purposes of remembering this is from the PIM + $stat = $this->_smartStatMessage($folderid, $id, false); + $stat['mod'] = time(); + } else { + // ActiveSync messages do NOT contain the serverUID value, put + // it in ourselves so we can have it during import/change. + $message->setServerUID($id); + if (!empty($device->supported[self::APPOINTMENTS_FOLDER])) { + $message->setSupported($device->supported[self::APPOINTMENTS_FOLDER]); + } + try { + $this->_connector->calendar_replace($id, $message); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return false; + } + $stat = $this->_smartStatMessage($folderid, $id, false); + } + break; + + case self::CONTACTS_FOLDER: + if (!$id) { + try { + $id = $this->_connector->contacts_import($message); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return false; + } + $stat = $this->_smartStatMessage($folderid, $id, false); + $stat['mod'] = time(); + } else { + if (!empty($device->supported[self::CONTACTS_FOLDER])) { + $message->setSupported($device->supported[self::CONTACTS_FOLDER]); + } + try { + $this->_connector->contacts_replace($id, $message); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return false; + } + $stat = $this->_smartStatMessage($folderid, $id, false); + } + break; + + case self::TASKS_FOLDER: + if (!$id) { + try { + $id = $this->_connector->tasks_import($message); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return false; + } + $stat = $this->_smartStatMessage($folderid, $id, false); + $stat['mod'] = time(); + } else { + if (!empty($device->supported[self::TASKS_FOLDER])) { + $message->setSupported($device->supported[self::TASKS_FOLDER]); + } + try { + $this->_connector->tasks_replace($id, $message); + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return false; + } + $stat = $this->_smartStatMessage($folderid, $id, false); + } + break; + + default: + $this->_endBuffer(); + return false; + } + + $this->_endBuffer(); + return $stat; + } + + /** + * Returns array of items which contain contact information + * + * @param string $query The text string to match against any textual ANR + * (Automatic Name Resolution) properties. Exchange's + * searchable ANR properties are currently: + * firstname, lastname, alias, displayname, email + * @param string $range The range to return (for example, 1-50). + * + * @return array with 'rows' and 'range' keys + */ + public function getSearchResults($query, $range) + { + $return = array('rows' => array(), + 'range' => $range); + + ob_start(); + try { + $results = $this->_connector->contacts_search($query); + } catch (Horde_ActiveSync_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return $return; + } + + /* Honor range, and don't bother if no results */ + $count = count($results); + if (!$count) { + return $return; + } + $this->_logger->info('Horde::getSearchResults found ' . $count . ' matches.'); + + preg_match('/(.*)\-(.*)/', $range, $matches); + $return_count = $matches[2] - $matches[1]; + $rows = array_slice($results, $matches[1], $return_count + 1, true); + $rows = array_pop($rows); + foreach ($rows as $row) { + $return['rows'][] = array( + Horde_ActiveSync::GAL_ALIAS => $row['alias'], + Horde_ActiveSync::GAL_DISPLAYNAME => $row['name'], + Horde_ActiveSync::GAL_EMAILADDRESS => $row['email'], + Horde_ActiveSync::GAL_FIRSTNAME => $row['firstname'], + Horde_ActiveSync::GAL_LASTNAME => $row['lastname'], + Horde_ActiveSync::GAL_COMPANY => $row['company'], + Horde_ActiveSync::GAL_HOMEPHONE => $row['homePhone'], + Horde_ActiveSync::GAL_PHONE => $row['workPhone'] + ); + } + + $this->_endBuffer(); + return $return; + } + + /** + * Sends the email represented by the rfc822 string received by the PIM. + * Currently only used when meeting requests are sent from the PIM. + * + * @param string $rfc822 The rfc822 mime message + * @param boolean $forward @TODO + * @param boolean $reply @TODO + * @param boolean $parent @TODO + * + * @return boolean + */ + public function sendMail($rfc822, $forward = false, $reply = false, $parent = false) + { + $headers = Horde_Mime_Headers::parseHeaders($rfc822); + $part = Horde_Mime_Part::parseMessage($rfc822); + + $mail = new Horde_Mime_Mail(); + $mail->addHeaders($headers->toArray()); + + $body_id = $part->findBody(); + if ($body_id) { + $body = $part->getPart($body_id); + $body = $body->getContents(); + $mail->setBody($body); + } else { + $mail->setBody('No body?'); + } + foreach ($part->contentTypeMap() as $id => $type) { + $mail->addPart($type, $part->getPart($id)->toString()); + } + + $mail->send($this->_params['mail']); + + return true; + } + + /** + * + * @param string $folderid The folder id + * @param string $id The message id + * @param mixed $hint @TODO: Figure out what, exactly, this does :) + * + * @return message stat hash + */ + private function _smartStatMessage($folderid, $id, $hint) + { + ob_start(); + $this->_logger->debug('ActiveSync_Driver_Horde::_smartStatMessage:' . $folderid . ':' . $id); + $statKey = $folderid . $id; + $mod = false; + + if ($hint !== false && isset($this->_modCache[$statKey])) { + $mod = $this->_modCache[$statKey]; + } elseif (is_int($hint)) { + $mod = $hint; + $this->_modCache[$statKey] = $mod; + } else { + try { + switch ($folderid) { + case self::APPOINTMENTS_FOLDER: + $mod = $this->_connector->calendar_getActionTimestamp($id, 'modify'); + break; + + case self::CONTACTS_FOLDER: + $mod = $this->_connector->contacts_getActionTimestamp($id, 'modify'); + break; + + case self::TASKS_FOLDER: + $mod = $this->_connector->tasks_getActionTimestamp($id, 'modify'); + break; + + default: + $this->_endBuffer(); + return false; + } + } catch (Horde_Exception $e) { + $this->_logger->err($e->getMessage()); + $this->_endBuffer(); + return array('id' => '', 'mod' => 0, 'flags' => 1); + } + $this->_modCache[$statKey] = $mod; + } + + $message = array(); + $message['id'] = $id; + $message['mod'] = $mod; + $message['flags'] = 1; + + $this->_endBuffer(); + return $message; + } + + private function _endBuffer() + { + if ($output = ob_get_clean()) { + $this->_logger->err('Unexpected output: ' . $output); + } + } + +} diff --git a/framework/Core/lib/Horde/Core/Factory/ActiveSyncBackend.php b/framework/Core/lib/Horde/Core/Factory/ActiveSyncBackend.php index 1b03ac111..8b6b1a28a 100644 --- a/framework/Core/lib/Horde/Core/Factory/ActiveSyncBackend.php +++ b/framework/Core/lib/Horde/Core/Factory/ActiveSyncBackend.php @@ -21,7 +21,7 @@ class Horde_Core_Factory_ActiveSyncBackend // Backend driver and dependencies $params['registry'] = $GLOBALS['registry']; $driver_params = array( - 'connector' => new Horde_ActiveSync_Driver_Horde_Connector_Registry($params), + 'connector' => new Horde_Core_ActiveSync_Connector($params), 'ping' => $conf['activesync']['ping'], 'state_basic' => $injector->getInstance('Horde_ActiveSyncState'), 'auth' => $injector->getInstance('Horde_Core_Factory_Auth')->create()); @@ -29,7 +29,7 @@ class Horde_Core_Factory_ActiveSyncBackend $driver_params['policies'] = $conf['activesync']['securitypolicies']; } - return new Horde_ActiveSync_Driver_Horde($driver_params); + return new Horde_Core_ActiveSync_Driver($driver_params); } } \ No newline at end of file diff --git a/framework/Core/package.xml b/framework/Core/package.xml index 761282035..61fdd825f 100644 --- a/framework/Core/package.xml +++ b/framework/Core/package.xml @@ -24,7 +24,7 @@ Application Framework. yes 2010-10-25 - + 0.1.0 0.1.0 @@ -79,6 +79,10 @@ Application Framework.
+ + + + @@ -674,6 +678,8 @@ Application Framework. + +