Overview

Packages

  • None
  • SyncMl

Classes

  • Horde_SyncMl
  • Horde_SyncMl_Backend
  • Horde_SyncMl_Backend_Horde
  • Horde_SyncMl_Command
  • Horde_SyncMl_Command_Alert
  • Horde_SyncMl_Command_Final
  • Horde_SyncMl_Command_Get
  • Horde_SyncMl_Command_Map
  • Horde_SyncMl_Command_Put
  • Horde_SyncMl_Command_Replace
  • Horde_SyncMl_Command_Results
  • Horde_SyncMl_Command_Status
  • Horde_SyncMl_Command_Sync
  • Horde_SyncMl_Command_SyncHdr
  • Horde_SyncMl_ContentHandler
  • Horde_SyncMl_DataStore
  • Horde_SyncMl_Device
  • Horde_SyncMl_Device_Nokia
  • Horde_SyncMl_Device_P800
  • Horde_SyncMl_Device_sync4j
  • Horde_SyncMl_Device_Sync4JMozilla
  • Horde_SyncMl_Device_Synthesis
  • Horde_SyncMl_DeviceInfo
  • Horde_SyncMl_Property
  • Horde_SyncMl_PropertyParameter
  • Horde_SyncMl_State
  • Horde_SyncMl_Sync
  • Horde_SyncMl_SyncElement
  • Horde_SyncMl_Translation
  • Horde_SyncMl_XmlOutput
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * The Horde_SyncMl_Command_Alert class provides a SyncML implementation of the
  4:  * Alert command as defined in SyncML Representation Protocol, version 1.1,
  5:  * section 5.5.2.
  6:  *
  7:  * The Alert command is used for sending custom content information to the
  8:  * recipient. The command provides a mechanism for communicating content
  9:  * information, such as state information or notifications to an application on
 10:  * the recipient device.
 11:  *
 12:  * Copyright 2003-2012 Horde LLC (http://www.horde.org/)
 13:  *
 14:  * See the enclosed file COPYING for license information (LGPL). If you
 15:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
 16:  *
 17:  * @author  Anthony Mills <amills@pyramid6.com>
 18:  * @author  Karsten Fourmont <karsten@horde.org>
 19:  * @author  Jan Schneider <jan@horde.org>
 20:  * @package SyncMl
 21:  */
 22: class Horde_SyncMl_Command_Alert extends Horde_SyncMl_Command
 23: {
 24:     /**
 25:      * Name of the command.
 26:      *
 27:      * @var string
 28:      */
 29:     protected $_cmdName = 'Alert';
 30: 
 31:     /**
 32:      * The alert type. Should be one of the Horde_SyncMl::ALERT_* constants.
 33:      *
 34:      * @var integer
 35:      */
 36:     protected $_alert;
 37: 
 38:     /**
 39:      * Source database of the Alert command.
 40:      *
 41:      * @var string
 42:      */
 43:     protected $_sourceLocURI;
 44: 
 45:     /**
 46:      * Target database of the Alert command.
 47:      *
 48:      * @var string
 49:      */
 50:     protected $_targetLocURI;
 51: 
 52:     /**
 53:      * The current time this synchronization happens, from the <Meta><Next>
 54:      * element.
 55:      *
 56:      * @var string
 57:      */
 58:     protected $_metaAnchorNext;
 59: 
 60:     /**
 61:      * The last time when synchronization happened, from the <Meta><Last>
 62:      * element.
 63:      *
 64:      * @var integer
 65:      */
 66:     protected $_metaAnchorLast;
 67: 
 68:     /**
 69:      * End element handler for the XML parser, delegated from
 70:      * Horde_SyncMl_ContentHandler::endElement().
 71:      *
 72:      * @param string $uri      The namespace URI of the element.
 73:      * @param string $element  The element tag name.
 74:      */
 75:     public function endElement($uri, $element)
 76:     {
 77:         switch (count($this->_stack)) {
 78:         case 2:
 79:             if ($element == 'Data') {
 80:                 $this->_alert = intval(trim($this->_chars));
 81:             }
 82:             break;
 83: 
 84:         case 4:
 85:             if ($element == 'LocURI') {
 86:                 switch ($this->_stack[2]) {
 87:                 case 'Source':
 88:                     $this->_sourceLocURI = trim($this->_chars);
 89:                     break;
 90:                 case 'Target':
 91:                     $this->_targetLocURI = trim($this->_chars);
 92:                     break;
 93:                 }
 94:             }
 95:             break;
 96: 
 97:         case 5:
 98:             switch ($element) {
 99:             case 'Next':
100:                 $this->_metaAnchorNext = trim($this->_chars);
101:                 break;
102:             case 'Last':
103:                 $this->_metaAnchorLast = trim($this->_chars);
104:                 break;
105:             }
106:             break;
107:         }
108: 
109:         parent::endElement($uri, $element);
110:     }
111: 
112:     /**
113:      * Implements the actual business logic of the Alert command.
114:      */
115:     public function handleCommand($debug = false)
116:     {
117:         $state = $GLOBALS['backend']->state;
118: 
119:         // Handle unauthenticated first.
120:         if (!$state->authenticated) {
121:             $this->_outputHandler->outputStatus($this->_cmdID, $this->_cmdName,
122:                                                 Horde_SyncMl::RESPONSE_INVALID_CREDENTIALS);
123:             return;
124:         }
125: 
126:         // Handle NEXT_MESSAGE Alert by doing nothing, except OK status
127:         // response.  Exception for Funambol: here we produce the output only
128:         // after an explicit Horde_SyncMl::ALERT_NEXT_MESSAGE.
129:         if ($this->_alert == Horde_SyncMl::ALERT_NEXT_MESSAGE) {
130:             $this->_outputHandler->outputStatus($this->_cmdID, $this->_cmdName,
131:                                                 Horde_SyncMl::RESPONSE_OK);
132:             // @TODO: create a getDevice()->sentyncDataLate() method instead
133:             // of this:
134:             if (is_a($state->getDevice(), 'Horde_SyncMl_Device_sync4j')) {
135:                 // Now send client changes to server. This will produce the
136:                 // <Sync> response.
137:                 $sync = &$state->getSync($this->_targetLocURI);
138:                 if ($sync) {
139:                     $sync->createSyncOutput($this->_outputHandler);
140:                 }
141:             }
142:             return;
143:         }
144: 
145:         $database = $this->_targetLocURI;
146:         if (!$GLOBALS['backend']->isValidDatabaseURI($database)) {
147:             $this->_outputHandler->outputStatus($this->_cmdID, $this->_cmdName,
148:                                                 Horde_SyncMl::RESPONSE_NOT_FOUND);
149:             return;
150:         }
151:         if ($database == 'configuration') {
152:             $this->_outputHandler->outputStatus($this->_cmdID, $this->_cmdName,
153:                                                 Horde_SyncMl::RESPONSE_OK);
154:         }
155: 
156:         $clientAnchorNext = $this->_metaAnchorNext;
157: 
158:         if (!$debug &&
159:             ($this->_alert == Horde_SyncMl::ALERT_TWO_WAY ||
160:              $this->_alert == Horde_SyncMl::ALERT_ONE_WAY_FROM_CLIENT ||
161:              $this->_alert == Horde_SyncMl::ALERT_ONE_WAY_FROM_SERVER)) {
162:             // Check if we have information about previous sync.
163:             $r = $GLOBALS['backend']->readSyncAnchors($this->_targetLocURI);
164:             if (is_array($r)) {
165:                 // Info about previous successful sync sessions found.
166:                 list($clientlast, $serverAnchorLast) = $r;
167:                 $GLOBALS['backend']->logMessage(
168:                     'Previous sync found for database ' . $database
169:                     . '; client timestamp: ' . $clientlast, 'DEBUG');
170: 
171:                 // Check if anchor sent from client matches our own stored
172:                 // data.
173:                 if ($clientlast == $this->_metaAnchorLast) {
174:                     // Last sync anchors matche, TwoWaySync will do.
175:                     $anchormatch = true;
176:                     $GLOBALS['backend']->logMessage(
177:                         'Anchor timestamps match, TwoWaySync possible. Syncing data since '
178:                         . date('Y-m-d H:i:s', $serverAnchorLast), 'DEBUG');
179:                 } else {
180:                     // Server and client have different anchors, enforce
181:                     // SlowSync/RefreshSync
182:                     $GLOBALS['backend']->logMessage(
183:                         'Client requested sync with anchor timestamp '
184:                         . $this->_metaAnchorLast
185:                         . ' but server has recorded timestamp '
186:                         . $clientlast . '. Enforcing SlowSync', 'INFO');
187:                     $anchormatch = false;
188:                     $clientlast = 0;
189:                 }
190:             } else {
191:                 // No info about previous sync, use SlowSync or RefreshSync.
192:                 $GLOBALS['backend']->logMessage(
193:                     'No info about previous syncs found for device ' .
194:                     $state->sourceURI . ' and database ' . $database, 'DEBUG');
195:                 $clientlast = 0;
196:                 $serverAnchorLast = 0;
197:                 $anchormatch = false;
198:             }
199:         } else {
200:             // SlowSync requested, no anchor check required.
201:             $anchormatch = true;
202:         }
203: 
204:         // Determine sync type and status response code.
205:         switch ($this->_alert) {
206:         case Horde_SyncMl::ALERT_TWO_WAY:
207:             if ($anchormatch) {
208:                 $synctype = Horde_SyncMl::ALERT_TWO_WAY;
209:                 $response = Horde_SyncMl::RESPONSE_OK;
210:             } else {
211:                 $synctype = Horde_SyncMl::ALERT_SLOW_SYNC;
212:                 $response = Horde_SyncMl::RESPONSE_REFRESH_REQUIRED;
213:             }
214:             break;
215: 
216:         case Horde_SyncMl::ALERT_SLOW_SYNC:
217:             $synctype = Horde_SyncMl::ALERT_SLOW_SYNC;
218:             $response = $anchormatch ? Horde_SyncMl::RESPONSE_OK : Horde_SyncMl::RESPONSE_REFRESH_REQUIRED;
219:             break;
220: 
221:         case Horde_SyncMl::ALERT_ONE_WAY_FROM_CLIENT:
222:             if ($anchormatch) {
223:                 $synctype = Horde_SyncMl::ALERT_ONE_WAY_FROM_CLIENT;
224:                 $response = Horde_SyncMl::RESPONSE_OK;
225:             } else {
226:                 $synctype = Horde_SyncMl::ALERT_REFRESH_FROM_CLIENT;
227:                 $response = Horde_SyncMl::RESPONSE_REFRESH_REQUIRED;
228:             }
229:             break;
230: 
231:         case Horde_SyncMl::ALERT_REFRESH_FROM_CLIENT:
232:             $synctype = Horde_SyncMl::ALERT_REFRESH_FROM_CLIENT;
233:             $response = $anchormatch ? Horde_SyncMl::RESPONSE_OK : Horde_SyncMl::RESPONSE_REFRESH_REQUIRED;
234:             break;
235: 
236:         case Horde_SyncMl::ALERT_ONE_WAY_FROM_SERVER:
237:             if ($anchormatch) {
238:                 $synctype = Horde_SyncMl::ALERT_ONE_WAY_FROM_SERVER;
239:                 $response = Horde_SyncMl::RESPONSE_OK;
240:             } else {
241:                 $synctype = Horde_SyncMl::ALERT_REFRESH_FROM_SERVER;
242:                 $response = Horde_SyncMl::RESPONSE_REFRESH_REQUIRED;
243:             }
244:             break;
245: 
246:         case Horde_SyncMl::ALERT_REFRESH_FROM_SERVER:
247:             $synctype = Horde_SyncMl::ALERT_REFRESH_FROM_SERVER;
248:             $response = $anchormatch ? Horde_SyncMl::RESPONSE_OK : Horde_SyncMl::RESPONSE_REFRESH_REQUIRED;
249:             break;
250: 
251:         case Horde_SyncMl::ALERT_RESUME:
252:             // @TODO: Suspend and Resume is not supported yet
253:             $synctype = Horde_SyncMl::ALERT_SLOW_SYNC;
254:             $response = Horde_SyncMl::RESPONSE_REFRESH_REQUIRED;
255:             break;
256: 
257:         default:
258:             $GLOBALS['backend']->logMessage(
259:                 'Unknown sync type ' . $this->_alert, 'ERR');
260:             break;
261:         }
262: 
263:         // Now set interval to retrieve server changes from, defined by
264:         // ServerAnchor [Last,Next]
265:         if ($synctype != Horde_SyncMl::ALERT_TWO_WAY &&
266:             $synctype != Horde_SyncMl::ALERT_ONE_WAY_FROM_CLIENT &&
267:             $synctype != Horde_SyncMl::ALERT_ONE_WAY_FROM_SERVER) {
268:             $serverAnchorLast = 0;
269:             // Erase existing map:
270:             if (!$debug &&
271:                 (($anchormatch &&
272:                   Horde_SyncMl::CONFIG_DELETE_MAP_ON_REQUESTED_SLOWSYNC) ||
273:                  (!$anchormatch &&
274:                   Horde_SyncMl::CONFIG_DELETE_MAP_ON_ANCHOR_MISMATCH_SLOWSYNC))) {
275:                 $GLOBALS['backend']->eraseMap($this->_targetLocURI);
276:             }
277:         }
278:         $serverAnchorNext = $debug ? time() : $GLOBALS['backend']->getCurrentTimeStamp();
279: 
280:         // Now create the actual Horde_SyncMl_Sync object, if it doesn't exist yet.
281:         $sync = &$state->getSync($this->_targetLocURI);
282:         if (!$sync) {
283:             $GLOBALS['backend']->logMessage(
284:                 'Creating Horde_SyncMl_Sync object for database '
285:                 . $this->_targetLocURI .  '; sync type ' . $synctype, 'DEBUG');
286:             $sync = new Horde_SyncMl_Sync($synctype,
287:                                     $this->_targetLocURI,
288:                                     $this->_sourceLocURI,
289:                                     (int)$serverAnchorLast, (int)$serverAnchorNext,
290:                                     $clientAnchorNext);
291:             $state->setSync($this->_targetLocURI, $sync);
292:         }
293: 
294:         $this->_outputHandler->outputStatus($this->_cmdID, $this->_cmdName,
295:                                             $response,
296:                                             $this->_targetLocURI,
297:                                             $this->_sourceLocURI,
298:                                             $this->_metaAnchorNext,
299:                                             $this->_metaAnchorLast);
300: 
301:         $this->_outputHandler->outputAlert($synctype,
302:                                            $sync->getClientLocURI(),
303:                                            $sync->getServerLocURI(),
304:                                            $sync->getServerAnchorLast(),
305:                                            $sync->getServerAnchorNext());
306:     }
307: }
308: 
API documentation generated by ApiGen