+++ /dev/null
-<?php
-/**
- * Horde backend. Provides the communication between horde data and
- * ActiveSync server. Some code based on an implementation found on Z-Push's
- * fourm. Original header appears below. All other changes are:
- *
- * Copyright 2010 The Horde Project (http://www.horde.org)
- *
- * @author Michael J. Rubinsky <mrubinsk@horde.org>
- * @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
- * <pre>
- * Required params (in addition to the base class' requirements):
- * connector => Horde_ActiveSync_Driver_Horde_Connector_Registry object
- * auth => Horde_Auth object
- * </pre>
- *
- * @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);
- }
- }
-
-}
+++ /dev/null
-<?php
-/**
- * Registry connector for Horde backend. Provides the communication between
- * the Horde Registry on the local machine and the ActiveSync Horde driver.
- *
- * See the enclosed file COPYING for license information (GPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
- *
- * Copyright 2010 The Horde Project (http://www.horde.org)
- *
- * @author Michael J. Rubinsky <mrubinsk@horde.org>
- * @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:
- * <pre>
- * 'registry' - An instance of Horde_Registry
- * </pre>
- *
- * @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
<email>mrubinsk@horde.org</email>
<active>yes</active>
</lead>
- <date>2010-10-22</date>
- <time>13:14:23</time>
+ <date>2010-10-25</date>
+ <time>14:01:04</time>
<version>
<release>0.1.0</release>
<api>0.1.0</api>
<file name="Importer.php" role="php" />
</dir> <!-- /lib/Horde/ActiveSync/Connector -->
<dir name="Driver">
- <dir name="Horde">
- <dir name="Connector">
- <file name="Registry.php" role="php" />
- </dir> <!-- /lib/Horde/ActiveSync/Driver/Horde/Connector -->
- </dir> <!-- /lib/Horde/ActiveSync/Driver/Horde -->
<file name="Base.php" role="php" />
- <file name="Horde.php" role="php" />
</dir> <!-- /lib/Horde/ActiveSync/Driver -->
<dir name="Message">
<file name="Appointment.php" role="php" />
<install as="Horde/ActiveSync/Connector/Exporter.php" name="lib/Horde/ActiveSync/Connector/Exporter.php" />
<install as="Horde/ActiveSync/Connector/Importer.php" name="lib/Horde/ActiveSync/Connector/Importer.php" />
<install as="Horde/ActiveSync/Driver/Base.php" name="lib/Horde/ActiveSync/Driver/Base.php" />
- <install as="Horde/ActiveSync/Driver/Horde.php" name="lib/Horde/ActiveSync/Driver/Horde.php" />
- <install as="Horde/ActiveSync/Driver/Horde/Connector/Registry.php" name="lib/Horde/ActiveSync/Driver/Horde/Connector/Registry.php" />
<install as="Horde/ActiveSync/Message/Appointment.php" name="lib/Horde/ActiveSync/Message/Appointment.php" />
<install as="Horde/ActiveSync/Message/Attendee.php" name="lib/Horde/ActiveSync/Message/Attendee.php" />
<install as="Horde/ActiveSync/Message/Base.php" name="lib/Horde/ActiveSync/Message/Base.php" />
<release>alpha</release>
<api>alpha</api>
</stability>
- <date>2010-10-22</date>
+ <date>2010-10-25</date>
<license uri="http://www.gnu.org/licenses/gpl-2.0.html">GPLv2</license>
<notes>
* Initial release
--- /dev/null
+<?php
+/**
+ * Registry connector for Horde backend. Provides the communication between
+ * the Horde Registry on the local machine and the ActiveSync Horde driver.
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org)
+ *
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Horde_ActiveSync
+ */
+class Horde_Core_ActiveSync_Connector
+{
+ /**
+ * Horde registry
+ *
+ * @var Horde_Registry
+ */
+ private $_registry;
+
+ /**
+ * Const'r
+ *
+ * @param array $params Configuration parameters. Requires:
+ * <pre>
+ * 'registry' - An instance of Horde_Registry
+ * </pre>
+ *
+ * @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
--- /dev/null
+<?php
+/**
+ * Horde backend. Provides the communication between horde data and
+ * ActiveSync server. Some code based on an implementation found on Z-Push's
+ * fourm. Original header appears below. All other changes are:
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org)
+ *
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @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
+ * <pre>
+ * Required params (in addition to the base class' requirements):
+ * connector => Horde_ActiveSync_Driver_Horde_Connector_Registry object
+ * auth => Horde_Auth object
+ * </pre>
+ *
+ * @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);
+ }
+ }
+
+}
// 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());
$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
<active>yes</active>
</developer>
<date>2010-10-25</date>
- <time>09:15:23</time>
+ <time>14:04:39</time>
<version>
<release>0.1.0</release>
<api>0.1.0</api>
<file name="Form.php" role="php" />
</dir> <!-- /lib/Horde/Config -->
<dir name="Core">
+ <dir name="ActiveSync">
+ <file name="Connector.php" role="php" />
+ <file name="Driver.php" role="php" />
+ </dir> <!-- /lib/Horde/Core/ActiveSync -->
<dir name="Ajax">
<dir name="Imple">
<dir name="Geocoder">
<install as="Horde/Core/Prefs.php" name="lib/Horde/Core/Prefs.php" />
<install as="Horde/Core/Sidebar.php" name="lib/Horde/Core/Sidebar.php" />
<install as="Horde/Core/Translation.php" name="lib/Horde/Core/Translation.php" />
+ <install as="Horde/Core/ActiveSync/Connector.php" name="lib/Horde/Core/ActiveSync/Connector.php" />
+ <install as="Horde/Core/ActiveSync/Driver.php" name="lib/Horde/Core/ActiveSync/Driver.php" />
<install as="Horde/Core/Ajax/Application.php" name="lib/Horde/Core/Ajax/Application.php" />
<install as="Horde/Core/Ajax/Imple.php" name="lib/Horde/Core/Ajax/Imple.php" />
<install as="Horde/Core/Ajax/Imple/AutoCompleter.php" name="lib/Horde/Core/Ajax/Imple/AutoCompleter.php" />