Overview

Packages

  • Auth
  • Core
  • Horde
    • Imsp
  • None
  • Notification

Classes

  • Horde
  • Horde_Config
  • Horde_Config_Form
  • Horde_Core_ActiveSync_Connector
  • Horde_Core_ActiveSync_Driver
  • Horde_Core_Ajax_Application
  • Horde_Core_Ajax_Imple
  • Horde_Core_Ajax_Imple_AutoCompleter
  • Horde_Core_Ajax_Imple_Geocoder_Geonames
  • Horde_Core_Ajax_Imple_SpellChecker
  • Horde_Core_Alarm_Handler_Notify
  • Horde_Core_Auth_Application
  • Horde_Core_Auth_Composite
  • Horde_Core_Auth_Ldap
  • Horde_Core_Auth_Msad
  • Horde_Core_Auth_Shibboleth
  • Horde_Core_Auth_Signup_Base
  • Horde_Core_Auth_Signup_Form
  • Horde_Core_Auth_Signup_Null
  • Horde_Core_Auth_Signup_Sql
  • Horde_Core_Auth_Signup_SqlObject
  • Horde_Core_Autoloader_Callback_Mime
  • Horde_Core_Autoloader_Callback_Nls
  • Horde_Core_Block
  • Horde_Core_Block_Collection
  • Horde_Core_Block_Layout
  • Horde_Core_Block_Layout_Manager
  • Horde_Core_Block_Layout_View
  • Horde_Core_Block_Upgrade
  • Horde_Core_Browser
  • Horde_Core_Bundle
  • Horde_Core_Cli
  • Horde_Core_Controller_NotFound
  • Horde_Core_Controller_RequestConfiguration
  • Horde_Core_Controller_RequestMapper
  • Horde_Core_Controller_SettingsFinder
  • Horde_Core_Db_Migration
  • Horde_Core_Factory_ActiveSyncBackend
  • Horde_Core_Factory_ActiveSyncServer
  • Horde_Core_Factory_ActiveSyncState
  • Horde_Core_Factory_Ajax
  • Horde_Core_Factory_Alarm
  • Horde_Core_Factory_Auth
  • Horde_Core_Factory_AuthSignup
  • Horde_Core_Factory_Base
  • Horde_Core_Factory_BlockCollection
  • Horde_Core_Factory_Browser
  • Horde_Core_Factory_Cache
  • Horde_Core_Factory_Crypt
  • Horde_Core_Factory_Data
  • Horde_Core_Factory_Db
  • Horde_Core_Factory_DbBase
  • Horde_Core_Factory_DbPear
  • Horde_Core_Factory_Dns
  • Horde_Core_Factory_Editor
  • Horde_Core_Factory_Facebook
  • Horde_Core_Factory_Group
  • Horde_Core_Factory_History
  • Horde_Core_Factory_HttpClient
  • Horde_Core_Factory_Identity
  • Horde_Core_Factory_Image
  • Horde_Core_Factory_Imple
  • Horde_Core_Factory_Imsp
  • Horde_Core_Factory_ImspAuth
  • Horde_Core_Factory_Injector
  • Horde_Core_Factory_KolabServer
  • Horde_Core_Factory_KolabSession
  • Horde_Core_Factory_KolabStorage
  • Horde_Core_Factory_Ldap
  • Horde_Core_Factory_Lock
  • Horde_Core_Factory_Logger
  • Horde_Core_Factory_LoginTasks
  • Horde_Core_Factory_Mail
  • Horde_Core_Factory_Mapper
  • Horde_Core_Factory_Matcher
  • Horde_Core_Factory_Memcache
  • Horde_Core_Factory_MimeViewer
  • Horde_Core_Factory_Notification
  • Horde_Core_Factory_Perms
  • Horde_Core_Factory_PermsCore
  • Horde_Core_Factory_Prefs
  • Horde_Core_Factory_Request
  • Horde_Core_Factory_Secret
  • Horde_Core_Factory_SessionHandler
  • Horde_Core_Factory_Share
  • Horde_Core_Factory_ShareBase
  • Horde_Core_Factory_Template
  • Horde_Core_Factory_TextFilter
  • Horde_Core_Factory_ThemesCache
  • Horde_Core_Factory_Token
  • Horde_Core_Factory_Tree
  • Horde_Core_Factory_Twitter
  • Horde_Core_Factory_UrlShortener
  • Horde_Core_Factory_Vfs
  • Horde_Core_Factory_View
  • Horde_Core_Factory_Weather
  • Horde_Core_Group_Ldap
  • Horde_Core_Log_Logger
  • Horde_Core_LoginTasks
  • Horde_Core_LoginTasks_Backend_Horde
  • Horde_Core_LoginTasks_SystemTask_Upgrade
  • Horde_Core_Mime_Viewer_Syntaxhighlighter
  • Horde_Core_Mime_Viewer_Vcard
  • Horde_Core_Notification_Event_Status
  • Horde_Core_Notification_Handler_Decorator_Hordelog
  • Horde_Core_Notification_Storage_Session
  • Horde_Core_Perms
  • Horde_Core_Perms_Ui
  • Horde_Core_Prefs_Cache_Session
  • Horde_Core_Prefs_Identity
  • Horde_Core_Prefs_Storage_Configuration
  • Horde_Core_Prefs_Storage_Hooks
  • Horde_Core_Prefs_Storage_Upgrade
  • Horde_Core_Prefs_Ui
  • Horde_Core_Prefs_Ui_Widgets
  • Horde_Core_Share_Driver
  • Horde_Core_Share_FactoryCallback
  • Horde_Core_Sidebar
  • Horde_Core_Text_Filter_Bbcode
  • Horde_Core_Text_Filter_Emails
  • Horde_Core_Text_Filter_Emoticons
  • Horde_Core_Text_Filter_Highlightquotes
  • Horde_Core_Translation
  • Horde_Core_Tree_Html
  • Horde_Core_Tree_Javascript
  • Horde_Core_Tree_Simplehtml
  • Horde_Core_Ui_FlagImage
  • Horde_Core_Ui_JsCalendar
  • Horde_Core_Ui_Language
  • Horde_Core_Ui_Layout
  • Horde_Core_Ui_ModalFormRenderer
  • Horde_Core_Ui_Pager
  • Horde_Core_Ui_Tabs
  • Horde_Core_Ui_TagCloud
  • Horde_Core_Ui_VarRenderer
  • Horde_Core_Ui_VarRenderer_Html
  • Horde_Core_Ui_VarRenderer_TablesetHtml
  • Horde_Core_Ui_Widget
  • Horde_ErrorHandler
  • Horde_Help
  • Horde_Menu
  • Horde_Registry
  • Horde_Registry_Api
  • Horde_Registry_Application
  • Horde_Registry_Caller
  • Horde_Registry_Nlsconfig
  • Horde_Script_Files
  • Horde_Session
  • Horde_Session_Null
  • Horde_Themes
  • Horde_Themes_Cache
  • Horde_Themes_Css
  • Horde_Themes_Element
  • Horde_Themes_Image
  • Horde_Themes_Sound

Exceptions

  • Horde_Exception_HookNotSet
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Horde backend. Provides the communication between horde data and
  4:  * ActiveSync server.
  5:  *
  6:  * Copyright 2010-2012 Horde LLC (http://www.horde.org/)
  7:  *
  8:  * @author  Michael J. Rubinsky <mrubinsk@horde.org>
  9:  * @package Core
 10:  */
 11: class Horde_Core_ActiveSync_Driver extends Horde_ActiveSync_Driver_Base
 12: {
 13:     /** Constants **/
 14:     const APPOINTMENTS_FOLDER = 'Calendar';
 15:     const CONTACTS_FOLDER     = 'Contacts';
 16:     const TASKS_FOLDER        = 'Tasks';
 17:     const FOLDER_INBOX        = 'Inbox';
 18: 
 19:     /**
 20:      * Cache message stats
 21:      *
 22:      * @var Array of stat hashes
 23:      */
 24:     private $_modCache;
 25: 
 26:     /**
 27:      * Horde connector instance
 28:      *
 29:      * @var Horde_ActiveSync_Driver_Horde_Connector_Registry
 30:      */
 31:     private $_connector;
 32: 
 33:     /**
 34:      * Const'r
 35:      * <pre>
 36:      * Required params (in addition to the base class' requirements):
 37:      *   connector => Horde_ActiveSync_Driver_Horde_Connector_Registry object
 38:      *   auth      => Horde_Auth object
 39:      * </pre>
 40:      *
 41:      * @param array $params  Configuration parameters.
 42:      *
 43:      * @return Horde_ActiveSync_Driver_Horde
 44:      */
 45:     public function __construct($params = array())
 46:     {
 47:         parent::__construct($params);
 48:         if (empty($this->_params['connector']) || !($this->_params['connector'] instanceof Horde_Core_ActiveSync_Connector)) {
 49:             throw new InvalidArgumentException('Missing required connector object.');
 50:         }
 51: 
 52:         if (empty($this->_params['auth']) || !($this->_params['auth'] instanceof Horde_Auth_Base)) {
 53:             throw new InvalidArgumentException('Missing required Auth object');
 54:         }
 55: 
 56:         $this->_connector = $params['connector'];
 57:         $this->_auth = $params['auth'];
 58:     }
 59: 
 60:     /**
 61:      * Authenticate to Horde
 62:      *
 63:      * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#Logon($username, $domain, $password)
 64:      */
 65:     public function logon($username, $password, $domain = null)
 66:     {
 67:         $this->_logger->info('Horde_ActiveSync_Driver_Horde::logon attempt for: ' . $username);
 68:         parent::logon($username, $password, $domain);
 69: 
 70:         return $this->_auth->authenticate($username, array('password' => $password));
 71:     }
 72: 
 73:     /**
 74:      * Clean up
 75:      *
 76:      * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#Logoff()
 77:      */
 78:     public function logOff()
 79:     {
 80:         $this->_connector->clearAuth();
 81:         $this->_logger->info('User ' . $this->_user . ' logged off');
 82:         return true;
 83:     }
 84: 
 85:     /**
 86:      * Setup sync parameters. The user provided here is the user the backend
 87:      * will sync with. This allows you to authenticate as one user, and sync as
 88:      * another, if the backend supports this.
 89:      *
 90:      * @param string $user      The username to sync as on the backend.
 91:      *
 92:      * @return boolean
 93:      */
 94:     public function setup($user)
 95:     {
 96:         parent::setup($user);
 97:         $this->_modCache = array();
 98:         return true;
 99:     }
100: 
101:     /**
102:      * Get the wastebasket folder
103:      *
104:      * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#getWasteBasket()
105:      */
106:     public function getWasteBasket()
107:     {
108:         $this->_logger->debug('Horde::getWasteBasket()');
109: 
110:         return false;
111:     }
112: 
113:     /**
114:      * Return a list of available folders
115:      *
116:      * @return array  An array of folder stats
117:      */
118:     public function getFolderList()
119:     {
120:         ob_start();
121: 
122:         $this->_logger->debug('Horde::getFolderList()');
123:         /* Make sure we have the APIs needed for each folder class */
124:         try {
125:             $supported = $this->_connector->horde_listApis();
126:         } catch (Exception $e) {
127:             $this->_logger->err($e->getMessage());
128:             $this->_endBuffer();
129:             return array();
130:         }
131:         $folders = array();
132: 
133:         if (array_search('calendar', $supported)) {
134:             $folders[] = $this->statFolder(self::APPOINTMENTS_FOLDER);
135:         }
136: 
137:         if (array_search('contacts', $supported)) {
138:             $folders[] = $this->statFolder(self::CONTACTS_FOLDER);
139:         }
140: 
141:         if (array_search('tasks', $supported)) {
142:             $folders[] = $this->statFolder(self::TASKS_FOLDER);
143:         }
144: 
145:         // HACK to allow email setup to complete enough to allow invitation
146:         // emails.
147:         $folders[] = $this->statFolder(self::FOLDER_INBOX);
148: 
149:         if ($errors = Horde::endBuffer()) {
150:             $this->_logger->err('Unexpected output: ' . $errors);
151:         }
152:         $this->_endBuffer();
153: 
154:         return $folders;
155:     }
156: 
157:     /**
158:      * Retrieve folder
159:      *
160:      * @param string $id  The folder id
161:      *
162:      * @return Horde_ActiveSync_Message_Folder
163:      */
164:     public function getFolder($id)
165:     {
166:         $this->_logger->debug('Horde::getFolder(' . $id . ')');
167: 
168:         $folder = new Horde_ActiveSync_Message_Folder();
169:         $folder->serverid = $id;
170:         $folder->parentid = "0";
171:         $folder->displayname = $id;
172: 
173:         switch ($id) {
174:         case self::APPOINTMENTS_FOLDER:
175:             $folder->type = Horde_ActiveSync::FOLDER_TYPE_APPOINTMENT;
176:             break;
177:         case self::CONTACTS_FOLDER:
178:             $folder->type = Horde_ActiveSync::FOLDER_TYPE_CONTACT;
179:             break;
180:         case self::TASKS_FOLDER:
181:             $folder->type = Horde_ActiveSync::FOLDER_TYPE_TASK;
182:             break;
183:         case self::FOLDER_INBOX:
184:             $folder->type = Horde_ActiveSync::FOLDER_TYPE_INBOX;
185:             break;
186:         default:
187:             return false;
188:         }
189: 
190:         return $folder;
191:     }
192: 
193:     /**
194:      * Stat folder. Note that since the only thing that can ever change for a
195:      * folder is the name, we use that as the 'mod' value.
196:      *
197:      * @param $id
198:      *
199:      * @return a stat hash
200:      */
201:     public function statFolder($id)
202:     {
203:         $this->_logger->debug('Horde::statFolder(' . $id . ')');
204: 
205:         $folder = array();
206:         $folder['id'] = $id;
207:         $folder['mod'] = $id;
208:         $folder['parent'] = 0;
209: 
210:         return $folder;
211:     }
212: 
213:     /**
214:      * Get the message list of specified folder
215:      *
216:      * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#getMessageList($folderId, $cutOffDate)
217:      */
218:     public function getMessageList($folderid, $cutoffdate)
219:     {
220:         $this->_logger->debug('Horde::getMessageList(' . $folderid . ', ' . $cutoffdate . ')');
221: 
222:         ob_start();
223:         $messages = array();
224:         switch ($folderid) {
225:         case self::APPOINTMENTS_FOLDER:
226:             $startstamp = (int)$cutoffdate;
227:             $endstamp = time() + 32140800; //60 * 60 * 24 * 31 * 12 == one year
228: 
229:             try {
230:                 $events = $this->_connector->calendar_listUids($startstamp, $endstamp);
231:             } catch (Horde_Exception $e) {
232:                 $this->_logger->err($e->getMessage());
233:                 $this->_endBuffer();
234:                 return array();
235:             }
236:             foreach ($events as $uid) {
237:                 $messages[] = $this->_smartStatMessage($folderid, $uid, false);
238:             }
239:             break;
240: 
241:         case self::CONTACTS_FOLDER:
242:             try {
243:                 $contacts = $this->_connector->contacts_listUids();
244:             } catch (Horde_Exception $e) {
245:                 $this->_logger->err($e->getMessage());
246:                 $this->_endBuffer();
247:                 return array();
248:             }
249: 
250:             foreach ($contacts as $contact) {
251:                 $messages[] = $this->_smartStatMessage($folderid, $contact, false);
252:             }
253:             break;
254: 
255:         case self::TASKS_FOLDER:
256:             try {
257:                 $tasks = $this->_connector->tasks_listUids();
258:             } catch (Horde_Exception $e) {
259:                 $this->_logger->err($e->getMessage());
260:                 $this->_endBuffer();
261:                 return array();
262:             }
263:             foreach ($tasks as $task) {
264:                 $messages[] = $this->_smartStatMessage($folderid, $task, false);
265:             }
266:             break;
267: 
268:         default:
269:             $this->_endBuffer();
270:             return array();
271:         }
272:         $this->_endBuffer();
273: 
274:         return $messages;
275:     }
276: 
277:     /**
278:      * Get a list of server changes that occured during the specified time
279:      * period.
280:      *
281:      * @param string $folderId     The server id of the collection to check.
282:      * @param integer $from_ts     The starting timestamp
283:      * @param integer $to_ts       The ending timestamp
284:      * @param integer $cutoffdate  The earliest date to retrieve back to
285:      *
286:      * @return array A list of messge uids that have chnaged in the specified
287:      *               time period.
288:      */
289:     public function getServerChanges($folderId, $from_ts, $to_ts, $cutoffdate)
290:     {
291:         $this->_logger->debug("Horde_ActiveSync_Driver_Horde::getServerChanges($folderId, $from_ts, $to_ts, $cutoffdate)");
292: 
293:         $changes = array(
294:             'add' => array(),
295:             'delete' => array(),
296:             'modify' => array()
297:         );
298: 
299:         ob_start();
300:         switch ($folderId) {
301:         case self::APPOINTMENTS_FOLDER:
302:             if ($from_ts == 0) {
303:                 /* Can't use History if it's a first sync */
304:                 $startstamp = (int)$cutoffdate;
305:                 $endstamp = time() + 32140800; //60 * 60 * 24 * 31 * 12 == one year
306:                 try {
307:                     $changes['add'] = $this->_connector->calendar_listUids($startstamp, $endstamp);
308:                 } catch (Horde_Exception $e) {
309:                     $this->_logger->err($e->getMessage());
310:                     $this->_endBuffer();
311:                     return array();
312:                 }
313:             } else {
314:                 try {
315:                     $changes = $this->_connector->getChanges('calendar', $from_ts, $to_ts);
316:                 } catch (Horde_Exception $e) {
317:                     $this->_logger->err($e->getMessage());
318:                     $this->_endBuffer();
319:                     return array();
320:                 }
321:             }
322:             break;
323: 
324:         case self::CONTACTS_FOLDER:
325:             /* Can't use History for first sync */
326:             if ($from_ts == 0) {
327:                 try {
328:                     $changes['add'] = $this->_connector->contacts_listUids();
329:                 } catch (Horde_Exception $e) {
330:                     $this->_logger->err($e->getMessage());
331:                     $this->_endBuffer();
332:                     return array();
333:                 }
334:                 $edits = $deletes = array();
335:             } else {
336:                 try {
337:                     $changes = $this->_connector->getChanges('contacts', $from_ts, $to_ts);
338:                 } catch (Horde_Exception $e) {
339:                     $this->_logger->err($e->getMessage());
340:                     $this->_endBuffer();
341:                     return array();
342:                 }
343:             }
344:             break;
345: 
346:         case self::TASKS_FOLDER:
347:             /* Can't use History for first sync */
348:             if ($from_ts == 0) {
349:                 try {
350:                     $changes['add'] = $this->_connector->tasks_listUids();
351:                 } catch (Horde_Exception $e) {
352:                     $this->_logger->err($e->getMessage());
353:                     $this->_endBuffer();
354:                     return array();
355:                 }
356:             } else {
357:                 try {
358:                     $changes = $this->_connector->getChanges('tasks', $from_ts, $to_ts);
359:                 } catch (Horde_Exception $e) {
360:                     $this->_logger->err($e->getMessage());
361:                     $this->_endBuffer();
362:                     return array();
363:                 }
364:             }
365:             break;
366:         }
367: 
368:         $results = array();
369: 
370:         /* Server additions */
371:         foreach ($changes['add'] as $add) {
372:             $results[] = array(
373:                 'id' => $add,
374:                 'type' => 'change',
375:                 'flags' => Horde_ActiveSync::FLAG_NEWMESSAGE);
376:         }
377: 
378:         /* Server changes */
379:         foreach ($changes['modify'] as $change) {
380:             $results[] = array(
381:                 'id' => $change,
382:                 'type' => 'change');
383:         }
384: 
385:         /* Server Deletions */
386:         foreach ($changes['delete'] as $deleted) {
387:             $results[] = array(
388:                 'id' => $deleted,
389:                 'type' => 'delete');
390:         }
391:         $this->_endBuffer();
392: 
393:         return $results;
394:     }
395: 
396:     /**
397:      * Get a message from the backend
398:      *
399:      * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#getMessage
400:      */
401:     public function getMessage($folderid, $id, $truncsize, $mimesupport = 0)
402:     {
403:         $this->_logger->debug('Horde::getMessage(' . $folderid . ', ' . $id . ')');
404:         ob_start();
405:         $message = false;
406:         switch ($folderid) {
407:         case self::APPOINTMENTS_FOLDER:
408:             try {
409:                 $message = $this->_connector->calendar_export($id);
410:                 // Nokia MfE requires the optional UID element.
411:                 if (!$message->getUid()) {
412:                     $message->setUid($id);
413:                 }
414:             } catch (Horde_Exception $e) {
415:                 $this->_logger->err($e->getMessage());
416:                 $this->_endBuffer();
417:                 return false;
418:             }
419:             break;
420: 
421:         case self::CONTACTS_FOLDER:
422:             try {
423:                 $message = $this->_connector->contacts_export($id);
424:             } catch (Horde_Exception $e) {
425:                 $this->_logger->err($e->getMessage());
426:                 $this->_endBuffer();
427:                 return false;
428:             }
429:             break;
430: 
431:         case self::TASKS_FOLDER:
432:             try {
433:                 $message = $this->_connector->tasks_export($id);
434:             } catch (Horde_Exception $e) {
435:                 $this->_logger->err($e->getMessage());
436:                 $this->_endBuffer();
437:                 return false;
438:             }
439:             break;
440:         default:
441:             $this->_endBuffer();
442:             return false;
443:         }
444:         if (strlen($message->body) > $truncsize) {
445:             $message->body = self::truncate($message->body, $truncsize);
446:             $message->bodytruncated = 1;
447:         } else {
448:             // Be certain this is set.
449:             $message->bodytruncated = 0;
450:         }
451: 
452:         $this->_endBuffer();
453:         return $message;
454:     }
455: 
456:     /**
457:      * Get message stat data
458:      *
459:      * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#statMessage($folderId, $id)
460:      */
461:     public function statMessage($folderid, $id)
462:     {
463:         return $this->_smartStatMessage($folderid, $id, true);
464:     }
465: 
466:     /**
467:      * Delete a message
468:      *
469:      * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#deleteMessage($folderid, $id)
470:      */
471:     public function deleteMessage($folderid, $id)
472:     {
473:         $this->_logger->debug('Horde::deleteMessage(' . $folderid . ', ' . $id . ')');
474:         ob_start();
475:         $status = false;
476:         switch ($folderid) {
477:         case self::APPOINTMENTS_FOLDER:
478:             try {
479:                 $status = $this->_connector->calendar_delete($id);
480:             } catch (Horde_Exception $e) {
481:                 $this->_logger->err($e->getMessage());
482:                 $this->_endBuffer();
483:                 return false;
484:             }
485:             break;
486: 
487:         case self::CONTACTS_FOLDER:
488:             try {
489:                 $status = $this->_connector->contacts_delete($id);
490:             } catch (Horde_Exception $e) {
491:                 $this->_logger->err($e->getMessage());
492:                 $this->_endBuffer();
493:                 return false;
494:             }
495:             break;
496: 
497:         case self::TASKS_FOLDER:
498:             try {
499:                 $status = $this->_connector->tasks_delete($id);
500:             } catch (Horde_Exception $e) {
501:                 $this->_logger->err($e->getMessage());
502:                 $this->_endBuffer();
503:                 return false;
504:             }
505:             break;
506:         default:
507:             $this->_endBuffer();
508:             return false;
509:         }
510: 
511:         $this->_endBuffer();
512:         return $status;
513:     }
514: 
515:     /**
516:      * Add/Edit a message
517:      *
518:      * @param string $folderid  The server id for the folder the message belongs
519:      *                          to.
520:      * @param string $id        The server's uid for the message if this is a
521:      *                          change to an existing message.
522:      * @param Horde_ActiveSync_Message_Base $message  The activesync message
523:      * @param object $device  The device information
524:      *
525:      * @see framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde_ActiveSync_Driver_Base#changeMessage($folderid, $id, $message)
526:      */
527:     public function changeMessage($folderid, $id, $message, $device)
528:     {
529:         $this->_logger->debug('Horde::changeMessage(' . $folderid . ', ' . $id . ')');
530:         ob_start();
531:         $stat = false;
532:         switch ($folderid) {
533:         case self::APPOINTMENTS_FOLDER:
534:             if (!$id) {
535:                 try {
536:                     $id = $this->_connector->calendar_import($message);
537:                 } catch (Horde_Exception $e) {
538:                     $this->_logger->err($e->getMessage());
539:                     $this->_endBuffer();
540:                     return false;
541:                 }
542:                 // There is no history entry for new messages, so use the
543:                 // current time for purposes of remembering this is from the PIM
544:                 $stat = $this->_smartStatMessage($folderid, $id, false);
545:                 $stat['mod'] = time();
546:             } else {
547:                 // ActiveSync messages do NOT contain the serverUID value, put
548:                 // it in ourselves so we can have it during import/change.
549:                 $message->setServerUID($id);
550:                 if (!empty($device->supported[self::APPOINTMENTS_FOLDER])) {
551:                     $message->setSupported($device->supported[self::APPOINTMENTS_FOLDER]);
552:                 }
553:                 try {
554:                     $this->_connector->calendar_replace($id, $message);
555:                 } catch (Horde_Exception $e) {
556:                     $this->_logger->err($e->getMessage());
557:                     $this->_endBuffer();
558:                     return false;
559:                 }
560:                 $stat = $this->_smartStatMessage($folderid, $id, false);
561:             }
562:             break;
563: 
564:         case self::CONTACTS_FOLDER:
565:             if (!$id) {
566:                 try {
567:                     $id = $this->_connector->contacts_import($message);
568:                 } catch (Horde_Exception $e) {
569:                     $this->_logger->err($e->getMessage());
570:                     $this->_endBuffer();
571:                     return false;
572:                 }
573:                 $stat = $this->_smartStatMessage($folderid, $id, false);
574:                 $stat['mod'] = time();
575:             } else {
576:                 if (!empty($device->supported[self::CONTACTS_FOLDER])) {
577:                     $message->setSupported($device->supported[self::CONTACTS_FOLDER]);
578:                 }
579:                 try {
580:                     $this->_connector->contacts_replace($id, $message);
581:                 } catch (Horde_Exception $e) {
582:                     $this->_logger->err($e->getMessage());
583:                     $this->_endBuffer();
584:                     return false;
585:                 }
586:                 $stat = $this->_smartStatMessage($folderid, $id, false);
587:             }
588:             break;
589: 
590:         case self::TASKS_FOLDER:
591:             if (!$id) {
592:                 try {
593:                     $id = $this->_connector->tasks_import($message);
594:                 } catch (Horde_Exception $e) {
595:                     $this->_logger->err($e->getMessage());
596:                     $this->_endBuffer();
597:                     return false;
598:                 }
599:                 $stat = $this->_smartStatMessage($folderid, $id, false);
600:                 $stat['mod'] = time();
601:             } else {
602:                 if (!empty($device->supported[self::TASKS_FOLDER])) {
603:                     $message->setSupported($device->supported[self::TASKS_FOLDER]);
604:                 }
605:                 try {
606:                     $this->_connector->tasks_replace($id, $message);
607:                 } catch (Horde_Exception $e) {
608:                     $this->_logger->err($e->getMessage());
609:                     $this->_endBuffer();
610:                     return false;
611:                 }
612:                 $stat = $this->_smartStatMessage($folderid, $id, false);
613:             }
614:             break;
615: 
616:         default:
617:             $this->_endBuffer();
618:             return false;
619:         }
620: 
621:         $this->_endBuffer();
622:         return $stat;
623:     }
624: 
625:     /**
626:      * Returns array of items which contain contact information
627:      *
628:      * @param string $query  The text string to match against any textual ANR
629:      *                       (Automatic Name Resolution) properties. Exchange's
630:      *                       searchable ANR properties are currently:
631:      *                       firstname, lastname, alias, displayname, email
632:      * @param string $range  The range to return (for example, 1-50).
633:      *
634:      * @return array with 'rows' and 'range' keys
635:      */
636:     public function getSearchResults($query, $range)
637:     {
638:         $return = array('rows' => array(),
639:                         'range' => $range);
640: 
641:         ob_start();
642:         try {
643:             $results = $this->_connector->contacts_search($query);
644:         } catch (Horde_ActiveSync_Exception $e) {
645:             $this->_logger->err($e->getMessage());
646:             $this->_endBuffer();
647:             return $return;
648:         }
649: 
650:         /* Honor range, and don't bother if no results */
651:         $count = count($results);
652:         if (!$count) {
653:             return $return;
654:         }
655:         $this->_logger->info('Horde::getSearchResults found ' . $count . ' matches.');
656: 
657:         preg_match('/(.*)\-(.*)/', $range, $matches);
658:         $return_count = $matches[2] - $matches[1];
659:         $rows = array_slice($results, $matches[1], $return_count + 1, true);
660:         $rows = array_pop($rows);
661:         foreach ($rows as $row) {
662:             $return['rows'][] = array(
663:                 Horde_ActiveSync::GAL_ALIAS => !empty($row['alias']) ? $row['alias'] : '',
664:                 Horde_ActiveSync::GAL_DISPLAYNAME => $row['name'],
665:                 Horde_ActiveSync::GAL_EMAILADDRESS => !empty($row['email']) ? $row['email'] : '',
666:                 Horde_ActiveSync::GAL_FIRSTNAME => $row['firstname'],
667:                 Horde_ActiveSync::GAL_LASTNAME => $row['lastname'],
668:                 Horde_ActiveSync::GAL_COMPANY => !empty($row['company']) ? $row['company'] : '',
669:                 Horde_ActiveSync::GAL_HOMEPHONE => !empty($row['homePhone']) ? $row['homePhone'] : '',
670:                 Horde_ActiveSync::GAL_PHONE => !empty($row['workPhone']) ? $row['workPhone'] : '',
671:                 Horde_ActiveSync::GAL_MOBILEPHONE => !empty($row['cellPhone']) ? $row['cellPhone'] : '',
672:                 Horde_ActiveSync::GAL_TITLE => !empty($row['title']) ? $row['title'] : '',
673:             );
674:         }
675: 
676:         $this->_endBuffer();
677:         return $return;
678:     }
679: 
680:     /**
681:      * Sends the email represented by the rfc822 string received by the PIM.
682:      * Currently only used when meeting requests are sent from the PIM.
683:      *
684:      * @param string $rfc822    The rfc822 mime message
685:      * @param boolean $forward  Indicates if this is a forwarded message
686:      * @param boolean $reply    Indicates if this is a reply
687:      * @param boolean $parent   Parent message in thread.
688:      *
689:      * @return boolean
690:      */
691:     public function sendMail($rfc822, $forward = false, $reply = false, $parent = false)
692:     {
693:         $headers = Horde_Mime_Headers::parseHeaders($rfc822);
694:         $message = Horde_Mime_Part::parseMessage($rfc822);
695: 
696:         // Message requests do not contain the From, since it is assumed to
697:         // be from the user of the AS account.
698:         $ident = $GLOBALS['injector']
699:             ->getInstance('Horde_Core_Factory_Identity')
700:             ->create($this->_user);
701:         $name = $ident->getValue('fullname');
702:         $from_addr = $ident->getValue('from_addr');
703: 
704:         $mail = new Horde_Mime_Mail();
705:         $mail->addHeaders($headers->toArray());
706:         $mail->addHeader('From', $name . '<' . $from_addr . '>');
707: 
708:         $body_id = $message->findBody();
709:         if ($body_id) {
710:             $part = $message->getPart($body_id);
711:             $body = $part->getContents();
712:             $mail->setBody($body);
713:         } else {
714:             $mail->setBody('No body?');
715:         }
716: 
717:         foreach ($message->contentTypeMap() as $id => $type) {
718:             $mail->addPart($type, $message->getPart($id)->toString());
719:         }
720: 
721:         $mail->send($GLOBALS['injector']->getInstance('Horde_Mail'));
722: 
723:         return true;
724:     }
725: 
726:     /**
727:      *
728:      * @param string  $folderid  The folder id
729:      * @param string  $id        The message id
730:      * @param boolean $hint      Use the cached data, if available?
731:      *
732:      * @return message stat hash
733:      */
734:     private function _smartStatMessage($folderid, $id, $hint)
735:     {
736:         ob_start();
737:         $this->_logger->debug('ActiveSync_Driver_Horde::_smartStatMessage:' . $folderid . ':' . $id);
738:         $statKey = $folderid . $id;
739:         $mod = false;
740: 
741:         if ($hint && isset($this->_modCache[$statKey])) {
742:             $mod = $this->_modCache[$statKey];
743:         } else {
744:             try {
745:                 switch ($folderid) {
746:                 case self::APPOINTMENTS_FOLDER:
747:                     $mod = $this->_connector->calendar_getActionTimestamp($id, 'modify');
748:                     break;
749: 
750:                 case self::CONTACTS_FOLDER:
751:                     $mod = $this->_connector->contacts_getActionTimestamp($id, 'modify');
752:                     break;
753: 
754:                 case self::TASKS_FOLDER:
755:                     $mod = $this->_connector->tasks_getActionTimestamp($id, 'modify');
756:                     break;
757: 
758:                 default:
759:                     $this->_endBuffer();
760:                     return false;
761:                 }
762:             } catch (Horde_Exception $e) {
763:                 $this->_logger->err($e->getMessage());
764:                 $this->_endBuffer();
765:                 return array('id' => '', 'mod' => 0, 'flags' => 1);
766:             }
767:             $this->_modCache[$statKey] = $mod;
768:         }
769: 
770:         $message = array();
771:         $message['id'] = $id;
772:         $message['mod'] = $mod;
773:         $message['flags'] = 1;
774: 
775:         $this->_endBuffer();
776:         return $message;
777:     }
778: 
779:     private function _endBuffer()
780:     {
781:         if ($output = ob_get_clean()) {
782:             $this->_logger->err('Unexpected output: ' . $output);
783:         }
784:     }
785: 
786: }
787: 
API documentation generated by ApiGen