1: <?php
2: 3: 4: 5: 6: 7: 8: 9:
10: 11: 12: 13: 14:
15: class Horde_ActiveSync_Request_FolderSync extends Horde_ActiveSync_Request_Base
16: {
17:
18: const STATUS_SUCCESS = 1;
19: const STATUS_SERVERERROR = 6;
20: const STATUS_TIMEOUT = 8;
21: const STATUS_KEYMISM = 9;
22: const STATUS_PROTOERR = 10;
23:
24: 25: 26: 27: 28:
29: public function handle()
30: {
31: parent::handle();
32:
33:
34: $this->_statusCode = self::STATUS_SUCCESS;
35: $this->_logger->info('[Horde_ActiveSync::handleFolderSync] Beginning FOLDERSYNC');
36:
37:
38: if (!$this->checkPolicyKey($this->_activeSync->getPolicyKey())) {
39: return false;
40: }
41:
42:
43: if (!$this->_decoder->getElementStartTag(Horde_ActiveSync::FOLDERHIERARCHY_FOLDERSYNC)) {
44: $this->_logger->err('[Horde_ActiveSync::handleFolderSync] No input to parse');
45: $this->_statusCode = self::STATUS_PROTOERR;
46: $this->_handleError();
47: exit;
48: }
49:
50:
51: if (!$this->_decoder->getElementStartTag(Horde_ActiveSync::FOLDERHIERARCHY_SYNCKEY)) {
52: $this->_logger->err('[Horde_ActiveSync::handleFolderSync] No input to parse');
53: $this->_statusCode = self::STATUS_PROTOERR;
54: $this->_handleError();
55: exit;
56: }
57: $synckey = $this->_decoder->getElementContent();
58: if (!$this->_decoder->getElementEndTag()) {
59: $this->_logger->err('[Horde_ActiveSync::handleFolderSync] No input to parse');
60: $this->_statusCode = self::STATUS_PROTOERR;
61: $this->_handleError();
62: exit;
63: }
64: $this->_logger->debug('[Horde_ActiveSync::handleFolderSync] syncKey: ' . $synckey);
65:
66: try {
67: $this->_state->loadState($synckey, 'foldersync');
68: } catch (Horde_ActiveSync_Exception $e) {
69: $this->_statusCode = self::STATUS_KEYMISM;
70: $this->_handleError();
71: exit;
72: }
73:
74:
75: $changes = false;
76:
77:
78: if ($this->_decoder->getElementStartTag(Horde_ActiveSync::FOLDERHIERARCHY_CHANGES)) {
79:
80: if ($this->_decoder->getElementStartTag(Horde_ActiveSync::FOLDERHIERARCHY_COUNT)) {
81: $this->_decoder->getElementContent();
82: if (!$this->_decoder->getElementEndTag()) {
83: $this->_statusCode = self::STATUS_PROTOERR;
84: $this->_handleError();
85: exit;
86: }
87: }
88:
89:
90: $element = $this->_decoder->getElement();
91: if ($element[Horde_ActiveSync_Wbxml::EN_TYPE] != Horde_ActiveSync_Wbxml::EN_TYPE_STARTTAG) {
92: $this->_statusCode = self::STATUS_PROTOERR;
93: $this->_handleError();
94: exit;
95: }
96:
97:
98: $importer = $this->_driver->getImporter();
99: $importer->init($this->_state, false);
100:
101: while (1) {
102: $folder = new Horde_ActiveSync_Message_Folder(array('logger' => $this->_logger));
103: if (!$folder->decodeStream($this->_decoder)) {
104: break;
105: }
106:
107: switch ($element[Horde_ActiveSync_Wbxml::EN_TAG]) {
108: case SYNC_ADD:
109: case SYNC_MODIFY:
110: $serverid = $importer->importFolderChange($folder);
111: $changes = true;
112: break;
113: case SYNC_REMOVE:
114: $serverid = $importer->importFolderDeletion($folder);
115: $changes = true;
116: break;
117: }
118: }
119:
120: if (!$this->_decoder->getElementEndTag()) {
121: $this->_statusCode = self::STATUS_PROTOERR;
122: $this->_handleError();
123: exit;
124: }
125: }
126:
127: if (!$this->_decoder->getElementEndTag()) {
128: $this->_statusCode = self::STATUS_PROTOERR;
129: $this->_handleError();
130: exit;
131: }
132:
133:
134: $this->_logger->debug('[Horde_ActiveSync::handleFolderSync] Preparing to send changes to PIM');
135: $newsynckey = $this->_state->getNewSyncKey($synckey);
136: $seenfolders = $this->_state->getKnownFolders();
137: $this->_logger->debug('[Horde_ActiveSync::handleFolderSync] newSyncKey: ' . $newsynckey);
138:
139:
140:
141: $exporter = new Horde_ActiveSync_Connector_Exporter();
142: $sync = $this->_driver->getSyncObject();
143: $sync->init($this->_state, $exporter, array('synckey' => $synckey));
144:
145:
146: while(is_array($sync->syncronize()));
147:
148:
149: $this->_encoder->StartWBXML();
150:
151: $this->_encoder->startTag(Horde_ActiveSync::FOLDERHIERARCHY_FOLDERSYNC);
152:
153: $this->_encoder->startTag(Horde_ActiveSync::FOLDERHIERARCHY_STATUS);
154: $this->_encoder->content($this->_statusCode);
155: $this->_encoder->endTag();
156:
157: $this->_encoder->startTag(Horde_ActiveSync::FOLDERHIERARCHY_SYNCKEY);
158: $this->_encoder->content((($changes || $exporter->count > 0) ? $newsynckey : $synckey));
159: $this->_encoder->endTag();
160:
161: $this->_encoder->startTag(Horde_ActiveSync::FOLDERHIERARCHY_CHANGES);
162:
163: $this->_encoder->startTag(Horde_ActiveSync::FOLDERHIERARCHY_COUNT);
164: $this->_encoder->content($exporter->count);
165: $this->_encoder->endTag();
166:
167: if (count($exporter->changed) > 0) {
168: foreach ($exporter->changed as $folder) {
169: if (isset($folder->serverid) && in_array($folder->serverid, $seenfolders)) {
170: $this->_encoder->startTag(Horde_ActiveSync::FOLDERHIERARCHY_UPDATE);
171: } else {
172: $this->_encoder->startTag(Horde_ActiveSync::FOLDERHIERARCHY_ADD);
173: }
174: $folder->encodeStream($this->_encoder);
175: $this->_encoder->endTag();
176: }
177: }
178:
179: if (count($exporter->deleted) > 0) {
180: foreach ($exporter->deleted as $folder) {
181: $this->_encoder->startTag(Horde_ActiveSync::FOLDERHIERARCHY_REMOVE);
182: $this->_encoder->startTag(Horde_ActiveSync::FOLDERHIERARCHY_SERVERENTRYID);
183: $this->_encoder->content($folder);
184: $this->_encoder->endTag();
185: $this->_encoder->endTag();
186: }
187: }
188:
189: $this->_encoder->endTag();
190: $this->_encoder->endTag();
191:
192:
193:
194: if ($exporter->count || $changed) {
195: $this->_state->setNewSyncKey($newsynckey);
196: $this->_state->save();
197: }
198: $this->_cleanUpAfterPairing();
199:
200: return true;
201: }
202:
203: 204: 205: 206:
207: private function _handleError()
208: {
209: $this->_encoder->startWBXML();
210: $this->_encoder->startTag(Horde_ActiveSync::FOLDERHIERARCHY_FOLDERSYNC);
211: $this->_encoder->startTag(Horde_ActiveSync::FOLDERHIERARCHY_STATUS);
212: $this->_encoder->content($this->_statusCode);
213: $this->_encoder->endTag();
214: $this->_encoder->endTag();
215: }
216:
217: }