1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
22: class Horde_SyncMl_Command_Alert extends Horde_SyncMl_Command
23: {
24: 25: 26: 27: 28:
29: protected $_cmdName = 'Alert';
30:
31: 32: 33: 34: 35:
36: protected $_alert;
37:
38: 39: 40: 41: 42:
43: protected $_sourceLocURI;
44:
45: 46: 47: 48: 49:
50: protected $_targetLocURI;
51:
52: 53: 54: 55: 56: 57:
58: protected $_metaAnchorNext;
59:
60: 61: 62: 63: 64: 65:
66: protected $_metaAnchorLast;
67:
68: 69: 70: 71: 72: 73: 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: 114:
115: public function handleCommand($debug = false)
116: {
117: $state = $GLOBALS['backend']->state;
118:
119:
120: if (!$state->authenticated) {
121: $this->_outputHandler->outputStatus($this->_cmdID, $this->_cmdName,
122: Horde_SyncMl::RESPONSE_INVALID_CREDENTIALS);
123: return;
124: }
125:
126:
127:
128:
129: if ($this->_alert == Horde_SyncMl::ALERT_NEXT_MESSAGE) {
130: $this->_outputHandler->outputStatus($this->_cmdID, $this->_cmdName,
131: Horde_SyncMl::RESPONSE_OK);
132:
133:
134: if (is_a($state->getDevice(), 'Horde_SyncMl_Device_sync4j')) {
135:
136:
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:
163: $r = $GLOBALS['backend']->readSyncAnchors($this->_targetLocURI);
164: if (is_array($r)) {
165:
166: list($clientlast, $serverAnchorLast) = $r;
167: $GLOBALS['backend']->logMessage(
168: 'Previous sync found for database ' . $database
169: . '; client timestamp: ' . $clientlast, 'DEBUG');
170:
171:
172:
173: if ($clientlast == $this->_metaAnchorLast) {
174:
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:
181:
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:
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:
201: $anchormatch = true;
202: }
203:
204:
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:
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:
264:
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:
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:
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: