Overview

Packages

  • ActiveSync
  • None

Classes

  • Horde_ActiveSync
  • Horde_ActiveSync_Connector_Exporter
  • Horde_ActiveSync_Connector_Importer
  • Horde_ActiveSync_Driver_Base
  • Horde_ActiveSync_Exception
  • Horde_ActiveSync_Exception_InvalidRequest
  • Horde_ActiveSync_Exception_StateGone
  • Horde_ActiveSync_Message_Base
  • Horde_ActiveSync_Request_Base
  • Horde_ActiveSync_Request_FolderCreate
  • Horde_ActiveSync_Request_FolderSync
  • Horde_ActiveSync_Request_GetHierarchy
  • Horde_ActiveSync_Request_GetItemEstimate
  • Horde_ActiveSync_Request_MeetingResponse
  • Horde_ActiveSync_Request_MoveItems
  • Horde_ActiveSync_Request_Notify
  • Horde_ActiveSync_Request_Ping
  • Horde_ActiveSync_Request_Provision
  • Horde_ActiveSync_Request_Search
  • Horde_ActiveSync_Request_SendMail
  • Horde_ActiveSync_Request_SmartForward
  • Horde_ActiveSync_Request_SmartReply
  • Horde_ActiveSync_Request_Sync
  • Horde_ActiveSync_State_File
  • Horde_ActiveSync_Sync
  • Horde_ActiveSync_Wbxml
  • Horde_ActiveSync_Wbxml_Decoder
  • Horde_ActiveSync_Wbxml_Encoder
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Connector class for importing ActiveSync messages from the wbxml input stream
  4:  * Contains code written by the Z-Push project. Original file header preserved
  5:  * below.
  6:  *
  7:  * Copyright 2010-2012 Horde LLC (http://www.horde.org/)
  8:  *
  9:  * @author  Michael J. Rubinsky <mrubinsk@horde.org>
 10:  * @package ActiveSync
 11:  */
 12: 
 13: /**
 14:  * File      :   streamimporter.php
 15:  * Project   :   Z-Push
 16:  * Descr     :   Stream import classes
 17:  *
 18:  * Created   :   01.10.2007
 19:  *
 20:  * © Zarafa Deutschland GmbH, www.zarafaserver.de
 21:  * This file is distributed under GPL-2.0.
 22:  * Consult COPYING file for details
 23:  */
 24: class Horde_ActiveSync_Connector_Importer
 25: {
 26:     /**
 27:      * State machine
 28:      *
 29:      * @var Horde_ActiveSync_State_Base
 30:      */
 31:     protected $_state;
 32: 
 33:     /**
 34:      * The backend driver for communicating with the server we are syncing with.
 35:      *
 36:      * @var Horde_ActiveSync_Driver_Base
 37:      */
 38:     protected $_backend;
 39: 
 40:     /**
 41:      * Flags
 42:      *
 43:      * @var integer
 44:      */
 45:     protected $_flags;
 46: 
 47:     /**
 48:      * The server specific folder id
 49:      *
 50:      * @var string
 51:      */
 52:     protected $_folderId;
 53: 
 54:     protected $_logger;
 55: 
 56:     /**
 57:      * Const'r
 58:      *
 59:      * @param Horde_ActiveSync_Driver_Base $backend
 60:      */
 61:     public function __construct(Horde_ActiveSync_Driver_Base $backend)
 62:     {
 63:         $this->_backend = $backend;
 64:     }
 65: 
 66:     /**
 67:      * Initialize the exporter for this collection
 68:      *
 69:      * @param Horde_ActiveSync_State_Base $state  The state machine
 70:      * @param string $folderId                    The collection's id
 71:      * @param integer $flags                      Any flags
 72:      */
 73:     public function init(Horde_ActiveSync_State_Base &$state, $folderId, $flags = 0)
 74:     {
 75:         $this->_state = &$state;
 76:         $this->_flags = $flags;
 77:         $this->_folderId = $folderId;
 78:     }
 79: 
 80:     /**
 81:      * Setter for a logger instance
 82:      *
 83:      * @param Horde_Log_Logger $logger  The logger
 84:      */
 85:     public function setLogger($logger)
 86:     {
 87:         $this->_logger = $logger;
 88:     }
 89: 
 90:     /**
 91:      * Import a message change from the wbxml stream
 92:      *
 93:      * @param mixed $id                                A server message id or
 94:      *                                                 false if a new message
 95:      * @param Horde_ActiveSync_Message_Base $message   A message object
 96:      * @param StdClass $device                         A device descriptor
 97:      * @param integer $clientid                        Client id sent from PIM
 98:      *                                                 on message addition.
 99:      *
100:      * @return mixed The server message id or false
101:      */
102:     public function importMessageChange($id, $message, $device, $clientid)
103:     {
104:         /* do nothing if it is in a dummy folder */
105:         if ($this->_folderId == Horde_ActiveSync::FOLDER_TYPE_DUMMY) {
106:             return false;
107:         }
108: 
109:         /* Changing an existing object */
110:         if ($id) {
111:             /* Check for conflicts */
112:             $conflict = $this->_isConflict('change', $this->_folderId, $id);
113: 
114:             /* Update client state before we attempt to save changes, so we
115:              * have a record of the change. This way, if the server change fails
116:              * the server copy will be re-sync'd back to the PIM, maintaining
117:              * at least some sort of consistency. */
118:             $change = array();
119:             $change['id'] = $id;
120:             // mod is 0 to force a re-synch in the case of server failure. This
121:             // is updated after the change succeeds in the next updateState()
122:             $change['mod'] = 0;
123:             $change['parent'] = $this->_folderId;
124:             $change['flags'] = (isset($message->read)) ? $message->read : 0;
125:             $this->_state->updateState('change', $change, Horde_ActiveSync::CHANGE_ORIGIN_NA);
126: 
127:             /* If this is a conflict, see if the server wins */
128:             if ($conflict && $this->_flags == Horde_ActiveSync::CONFLICT_OVERWRITE_PIM) {
129:                 return $id;
130:             }
131:         } else {
132:             if ($uid = $this->_state->isDuplicatePIMAddition($clientid)) {
133:                 // Already saw this addition, but PIM never received UID
134:                 return $uid;
135:             }
136:         }
137: 
138:         /* Tell the backend about the change */
139:         if (!$stat = $this->_backend->changeMessage($this->_folderId, $id, $message, $device)) {
140:             return false;
141:         }
142:         $stat['parent'] = $this->_folderId;
143: 
144:         /* Record the state of the message */
145:         $this->_state->updateState(
146:             'change', $stat, Horde_ActiveSync::CHANGE_ORIGIN_PIM,
147:             $this->_backend->getUser(), $clientid);
148: 
149:         return $stat['id'];
150:     }
151: 
152:     /**
153:      * Import a message deletion. This may conflict if the local object has been
154:      * modified.
155:      *
156:      * @param string $id  Server message uid
157:      *
158:      * @return boolean
159:      */
160:     public function importMessageDeletion($id)
161:     {
162:         /* Do nothing if it is in a dummy folder */
163:         if ($this->_folderId == Horde_ActiveSync::FOLDER_TYPE_DUMMY) {
164:             return true;
165:         }
166: 
167:         /* Check for conflict */
168:         $conflict = $this->_isConflict('delete', $this->_folderId, $id);
169: 
170:         /* Update client state */
171:         $change = array();
172:         $change['id'] = $id;
173:         $change['mod'] = time();
174:         $change['parent'] = $this->_folderId;
175:         $this->_state->updateState('delete', $change, Horde_ActiveSync::CHANGE_ORIGIN_PIM, $this->_backend->getUser());
176: 
177:         /* If server wins the conflict, don't import change - it will be
178:          * detected on next sync and sent back to PIM (since we updated the PIM
179:          * state). */
180:         if ($conflict && $this->_flags == Horde_ActiveSync::CONFLICT_OVERWRITE_PIM) {
181:             return true;
182:         }
183: 
184:         /* Tell backend about the deletion */
185:         $this->_backend->deleteMessage($this->_folderId, $id);
186: 
187:         return true;
188:     }
189: 
190:     /**
191:      * Import a change in 'read' flags .. This can never conflict
192:      *
193:      * @param string $id  Server message id
194:      * @param ??  $flags  The read flags to set
195:      */
196:     public function importMessageReadFlag($id, $flags)
197:     {
198:         /* Do nothing if it is a dummy folder */
199:         if ($this->_folderId == Horde_ActiveSync::FOLDER_TYPE_DUMMY) {
200:             return true;
201:         }
202: 
203:         /* Update client state */
204:         $change = array();
205:         $change['id'] = $id;
206:         $change['flags'] = $flags;
207:         $this->_state->updateState('flags', $change, Horde_ActiveSync::CHANGE_ORIGIN_NA);
208: 
209:         /* Tell backend */
210:         $this->_backend->setReadFlag($this->_folderId, $id, $flags);
211: 
212:         return true;
213:     }
214: 
215:     /**
216:      * Perform a message move initiated on the PIM.
217:      *
218:      * @TODO
219:      *
220:      * @param string $id  The message id
221:      * @param  $newfolder
222:      *
223:      * @return boolean
224:      */
225:     public function importMessageMove($id, $newfolder)
226:     {
227:         return true;
228:     }
229: 
230:     /**
231:      * Import a folder change from the wbxml stream
232:      *
233:      * @param string $id            The folder id
234:      * @param string $parent        The parent folder id?
235:      * @param string $displayname   The folder display name
236:      * @param <unknown_type> $type  The collection type?
237:      *
238:      * @return boolean
239:      */
240:     public function importFolderChange($id, $parent, $displayname, $type)
241:     {
242:         /* do nothing if it is a dummy folder */
243:         if ($parent == Horde_ActiveSync::FOLDER_TYPE_DUMMY) {
244:             return false;
245:         }
246: 
247:         if ($id) {
248:             $change = array();
249:             $change['id'] = $id;
250:             $change['mod'] = $displayname;
251:             $change['parent'] = $parent;
252:             $change['flags'] = 0;
253:             $this->_state->updateState('change', $change, Horde_ActiveSync::CHANGE_ORIGIN_NA);
254:         }
255: 
256:         /* Tell the backend */
257:         $stat = $this->_backend->ChangeFolder($parent, $id, $displayname, $type);
258:         if ($stat) {
259:             $this->_state->updateState('change', $stat, Horde_ActiveSync::CHANGE_ORIGIN_NA);
260:         }
261: 
262:         return $stat['id'];
263:     }
264: 
265:     /**
266:      * Imports a folder deletion from the PIM
267:      *
268:      * @param string $id      The folder id
269:      * @param string $parent  The folder id of the parent folder
270:      *
271:      * @return boolean
272:      */
273:     public function importFolderDeletion($id, $parent)
274:     {
275:         /* Do nothing if it is a dummy folder */
276:         if ($parent == Horde_ActiveSync::FOLDER_TYPE_DUMMY) {
277:             return false;
278:         }
279: 
280:         $change = array();
281:         $change['id'] = $id;
282: 
283:         $this->_state->updateState('delete', $change, Horde_ActiveSync::CHANGE_ORIGIN_NA);
284:         $this->_backend->deleteFolder($parent, $id);
285: 
286:         return true;
287:     }
288: 
289:     /**
290:      *  Check if this change conflicts with server changes
291:      *  This is only true in the following situations:
292:      *
293:      *    Changed here and changed there
294:      *    Changed here and deleted there
295:      *    Deleted here and changed there
296:      *
297:      * Any other combination of operations can be done
298:      * (e.g. change flags & move or move & delete)
299:      *
300:      * @param string $type  The type of change('change', 'delete' etc...)
301:      * @param string $folderid  The id of the folder this change is from.
302:      * @param string $id        The uid for the changed message.
303:      *
304:      * @return boolean
305:      */
306:     protected function _isConflict($type, $folderid, $id)
307:     {
308:         $stat = $this->_backend->statMessage($folderid, $id);
309:         if (!$stat) {
310:             /* Message is gone, if type is change, this is a conflict */
311:             if ($type == 'change') {
312:                 return true;
313:             } else {
314:                 return false;
315:             }
316:         }
317: 
318:         return $this->_state->isConflict($stat, $type);
319:     }
320: 
321: }
322: 
API documentation generated by ApiGen