@@ -8,269 +8,269 @@ |
||
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | 10 | class Ping extends RequestProcessor { |
| 11 | - /** |
|
| 12 | - * Handles the Ping command. |
|
| 13 | - * |
|
| 14 | - * @param int $commandCode |
|
| 15 | - * |
|
| 16 | - * @return bool |
|
| 17 | - */ |
|
| 18 | - public function Handle($commandCode) { |
|
| 19 | - $interval = (defined('PING_INTERVAL') && PING_INTERVAL > 0) ? PING_INTERVAL : 30; |
|
| 20 | - $pingstatus = false; |
|
| 21 | - $fakechanges = []; |
|
| 22 | - $foundchanges = false; |
|
| 11 | + /** |
|
| 12 | + * Handles the Ping command. |
|
| 13 | + * |
|
| 14 | + * @param int $commandCode |
|
| 15 | + * |
|
| 16 | + * @return bool |
|
| 17 | + */ |
|
| 18 | + public function Handle($commandCode) { |
|
| 19 | + $interval = (defined('PING_INTERVAL') && PING_INTERVAL > 0) ? PING_INTERVAL : 30; |
|
| 20 | + $pingstatus = false; |
|
| 21 | + $fakechanges = []; |
|
| 22 | + $foundchanges = false; |
|
| 23 | 23 | |
| 24 | - // Contains all requested folders (containers) |
|
| 25 | - $sc = new SyncCollections(); |
|
| 24 | + // Contains all requested folders (containers) |
|
| 25 | + $sc = new SyncCollections(); |
|
| 26 | 26 | |
| 27 | - // read from stream to see if the symc params are being sent |
|
| 28 | - $params_present = self::$decoder->getElementStartTag(SYNC_PING_PING); |
|
| 27 | + // read from stream to see if the symc params are being sent |
|
| 28 | + $params_present = self::$decoder->getElementStartTag(SYNC_PING_PING); |
|
| 29 | 29 | |
| 30 | - // Load all collections - do load states, check permissions and allow unconfirmed states |
|
| 31 | - try { |
|
| 32 | - $sc->LoadAllCollections(true, true, true, true, false); |
|
| 33 | - } |
|
| 34 | - catch (StateInvalidException $siex) { |
|
| 35 | - // if no params are present, indicate to send params, else do hierarchy sync |
|
| 36 | - if (!$params_present) { |
|
| 37 | - $pingstatus = SYNC_PINGSTATUS_FAILINGPARAMS; |
|
| 38 | - self::$topCollector->AnnounceInformation("StateInvalidException: require PingParameters", true); |
|
| 39 | - } |
|
| 40 | - elseif (self::$deviceManager->IsHierarchySyncRequired()) { |
|
| 41 | - // we could be in a looping - see LoopDetection->ProcessLoopDetectionIsHierarchySyncAdvised() |
|
| 42 | - $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED; |
|
| 43 | - self::$topCollector->AnnounceInformation("Potential loop detection: require HierarchySync", true); |
|
| 44 | - } |
|
| 45 | - else { |
|
| 46 | - // we do not have a ping status for this, but SyncCollections should have generated fake changes for the folders which are broken |
|
| 47 | - $fakechanges = $sc->GetChangedFolderIds(); |
|
| 48 | - $foundchanges = true; |
|
| 30 | + // Load all collections - do load states, check permissions and allow unconfirmed states |
|
| 31 | + try { |
|
| 32 | + $sc->LoadAllCollections(true, true, true, true, false); |
|
| 33 | + } |
|
| 34 | + catch (StateInvalidException $siex) { |
|
| 35 | + // if no params are present, indicate to send params, else do hierarchy sync |
|
| 36 | + if (!$params_present) { |
|
| 37 | + $pingstatus = SYNC_PINGSTATUS_FAILINGPARAMS; |
|
| 38 | + self::$topCollector->AnnounceInformation("StateInvalidException: require PingParameters", true); |
|
| 39 | + } |
|
| 40 | + elseif (self::$deviceManager->IsHierarchySyncRequired()) { |
|
| 41 | + // we could be in a looping - see LoopDetection->ProcessLoopDetectionIsHierarchySyncAdvised() |
|
| 42 | + $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED; |
|
| 43 | + self::$topCollector->AnnounceInformation("Potential loop detection: require HierarchySync", true); |
|
| 44 | + } |
|
| 45 | + else { |
|
| 46 | + // we do not have a ping status for this, but SyncCollections should have generated fake changes for the folders which are broken |
|
| 47 | + $fakechanges = $sc->GetChangedFolderIds(); |
|
| 48 | + $foundchanges = true; |
|
| 49 | 49 | |
| 50 | - self::$topCollector->AnnounceInformation("StateInvalidException: force sync", true); |
|
| 51 | - } |
|
| 52 | - } |
|
| 53 | - catch (StatusException $stex) { |
|
| 54 | - $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED; |
|
| 55 | - self::$topCollector->AnnounceInformation("StatusException: require HierarchySync", true); |
|
| 56 | - } |
|
| 50 | + self::$topCollector->AnnounceInformation("StateInvalidException: force sync", true); |
|
| 51 | + } |
|
| 52 | + } |
|
| 53 | + catch (StatusException $stex) { |
|
| 54 | + $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED; |
|
| 55 | + self::$topCollector->AnnounceInformation("StatusException: require HierarchySync", true); |
|
| 56 | + } |
|
| 57 | 57 | |
| 58 | - SLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): reference PolicyKey for PING: %s", $sc->GetReferencePolicyKey())); |
|
| 58 | + SLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): reference PolicyKey for PING: %s", $sc->GetReferencePolicyKey())); |
|
| 59 | 59 | |
| 60 | - // receive PING initialization data |
|
| 61 | - if ($params_present) { |
|
| 62 | - self::$topCollector->AnnounceInformation("Processing PING data"); |
|
| 63 | - SLog::Write(LOGLEVEL_DEBUG, "HandlePing(): initialization data received"); |
|
| 60 | + // receive PING initialization data |
|
| 61 | + if ($params_present) { |
|
| 62 | + self::$topCollector->AnnounceInformation("Processing PING data"); |
|
| 63 | + SLog::Write(LOGLEVEL_DEBUG, "HandlePing(): initialization data received"); |
|
| 64 | 64 | |
| 65 | - if (self::$decoder->getElementStartTag(SYNC_PING_LIFETIME)) { |
|
| 66 | - $sc->SetLifetime(self::$decoder->getElementContent()); |
|
| 67 | - self::$decoder->getElementEndTag(); |
|
| 68 | - } |
|
| 65 | + if (self::$decoder->getElementStartTag(SYNC_PING_LIFETIME)) { |
|
| 66 | + $sc->SetLifetime(self::$decoder->getElementContent()); |
|
| 67 | + self::$decoder->getElementEndTag(); |
|
| 68 | + } |
|
| 69 | 69 | |
| 70 | - if (($el = self::$decoder->getElementStartTag(SYNC_PING_FOLDERS)) && $el[EN_FLAGS] & EN_FLAGS_CONTENT) { |
|
| 71 | - // cache requested (pingable) folderids |
|
| 72 | - $pingable = []; |
|
| 70 | + if (($el = self::$decoder->getElementStartTag(SYNC_PING_FOLDERS)) && $el[EN_FLAGS] & EN_FLAGS_CONTENT) { |
|
| 71 | + // cache requested (pingable) folderids |
|
| 72 | + $pingable = []; |
|
| 73 | 73 | |
| 74 | - while (self::$decoder->getElementStartTag(SYNC_PING_FOLDER)) { |
|
| 75 | - WBXMLDecoder::ResetInWhile("pingFolder"); |
|
| 76 | - while (WBXMLDecoder::InWhile("pingFolder")) { |
|
| 77 | - if (self::$decoder->getElementStartTag(SYNC_PING_SERVERENTRYID)) { |
|
| 78 | - $folderid = self::$decoder->getElementContent(); |
|
| 79 | - self::$decoder->getElementEndTag(); |
|
| 80 | - } |
|
| 81 | - if (self::$decoder->getElementStartTag(SYNC_PING_FOLDERTYPE)) { |
|
| 82 | - $class = self::$decoder->getElementContent(); |
|
| 83 | - self::$decoder->getElementEndTag(); |
|
| 84 | - } |
|
| 74 | + while (self::$decoder->getElementStartTag(SYNC_PING_FOLDER)) { |
|
| 75 | + WBXMLDecoder::ResetInWhile("pingFolder"); |
|
| 76 | + while (WBXMLDecoder::InWhile("pingFolder")) { |
|
| 77 | + if (self::$decoder->getElementStartTag(SYNC_PING_SERVERENTRYID)) { |
|
| 78 | + $folderid = self::$decoder->getElementContent(); |
|
| 79 | + self::$decoder->getElementEndTag(); |
|
| 80 | + } |
|
| 81 | + if (self::$decoder->getElementStartTag(SYNC_PING_FOLDERTYPE)) { |
|
| 82 | + $class = self::$decoder->getElementContent(); |
|
| 83 | + self::$decoder->getElementEndTag(); |
|
| 84 | + } |
|
| 85 | 85 | |
| 86 | - $e = self::$decoder->peek(); |
|
| 87 | - if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { |
|
| 88 | - self::$decoder->getElementEndTag(); |
|
| 86 | + $e = self::$decoder->peek(); |
|
| 87 | + if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { |
|
| 88 | + self::$decoder->getElementEndTag(); |
|
| 89 | 89 | |
| 90 | - break; |
|
| 91 | - } |
|
| 92 | - } |
|
| 90 | + break; |
|
| 91 | + } |
|
| 92 | + } |
|
| 93 | 93 | |
| 94 | - $spa = $sc->GetCollection($folderid); |
|
| 95 | - if (!$spa) { |
|
| 96 | - // The requested collection is not synchronized. |
|
| 97 | - // check if the HierarchyCache is available, if not, trigger a HierarchySync |
|
| 98 | - try { |
|
| 99 | - self::$deviceManager->GetFolderClassFromCacheByID($folderid); |
|
| 100 | - // ZP-907: ignore all folders with SYNC_FOLDER_TYPE_UNKNOWN |
|
| 101 | - if (self::$deviceManager->GetFolderTypeFromCacheById($folderid) == SYNC_FOLDER_TYPE_UNKNOWN) { |
|
| 102 | - SLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): ignoring folder id '%s' as it's of type UNKNOWN ", $folderid)); |
|
| 94 | + $spa = $sc->GetCollection($folderid); |
|
| 95 | + if (!$spa) { |
|
| 96 | + // The requested collection is not synchronized. |
|
| 97 | + // check if the HierarchyCache is available, if not, trigger a HierarchySync |
|
| 98 | + try { |
|
| 99 | + self::$deviceManager->GetFolderClassFromCacheByID($folderid); |
|
| 100 | + // ZP-907: ignore all folders with SYNC_FOLDER_TYPE_UNKNOWN |
|
| 101 | + if (self::$deviceManager->GetFolderTypeFromCacheById($folderid) == SYNC_FOLDER_TYPE_UNKNOWN) { |
|
| 102 | + SLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): ignoring folder id '%s' as it's of type UNKNOWN ", $folderid)); |
|
| 103 | 103 | |
| 104 | - continue; |
|
| 105 | - } |
|
| 106 | - } |
|
| 107 | - catch (NoHierarchyCacheAvailableException $nhca) { |
|
| 108 | - SLog::Write(LOGLEVEL_INFO, sprintf("HandlePing(): unknown collection '%s', triggering HierarchySync", $folderid)); |
|
| 109 | - $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED; |
|
| 110 | - } |
|
| 104 | + continue; |
|
| 105 | + } |
|
| 106 | + } |
|
| 107 | + catch (NoHierarchyCacheAvailableException $nhca) { |
|
| 108 | + SLog::Write(LOGLEVEL_INFO, sprintf("HandlePing(): unknown collection '%s', triggering HierarchySync", $folderid)); |
|
| 109 | + $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED; |
|
| 110 | + } |
|
| 111 | 111 | |
| 112 | - // Trigger a Sync request because then the device will be forced to resync this folder. |
|
| 113 | - $fakechanges[$folderid] = 1; |
|
| 114 | - $foundchanges = true; |
|
| 115 | - } |
|
| 116 | - elseif ($class == $spa->GetContentClass()) { |
|
| 117 | - $pingable[] = $folderid; |
|
| 118 | - SLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): using saved sync state for '%s' id '%s'", $spa->GetContentClass(), $folderid)); |
|
| 119 | - } |
|
| 120 | - } |
|
| 121 | - if (!self::$decoder->getElementEndTag()) { |
|
| 122 | - return false; |
|
| 123 | - } |
|
| 112 | + // Trigger a Sync request because then the device will be forced to resync this folder. |
|
| 113 | + $fakechanges[$folderid] = 1; |
|
| 114 | + $foundchanges = true; |
|
| 115 | + } |
|
| 116 | + elseif ($class == $spa->GetContentClass()) { |
|
| 117 | + $pingable[] = $folderid; |
|
| 118 | + SLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): using saved sync state for '%s' id '%s'", $spa->GetContentClass(), $folderid)); |
|
| 119 | + } |
|
| 120 | + } |
|
| 121 | + if (!self::$decoder->getElementEndTag()) { |
|
| 122 | + return false; |
|
| 123 | + } |
|
| 124 | 124 | |
| 125 | - // update pingable flags |
|
| 126 | - foreach ($sc as $folderid => $spa) { |
|
| 127 | - // if the folderid is in $pingable, we should ping it, else remove the flag |
|
| 128 | - if (in_array($folderid, $pingable)) { |
|
| 129 | - $spa->SetPingableFlag(true); |
|
| 130 | - } |
|
| 131 | - else { |
|
| 132 | - $spa->DelPingableFlag(); |
|
| 133 | - } |
|
| 134 | - } |
|
| 135 | - } |
|
| 136 | - if (!self::$decoder->getElementEndTag()) { |
|
| 137 | - return false; |
|
| 138 | - } |
|
| 125 | + // update pingable flags |
|
| 126 | + foreach ($sc as $folderid => $spa) { |
|
| 127 | + // if the folderid is in $pingable, we should ping it, else remove the flag |
|
| 128 | + if (in_array($folderid, $pingable)) { |
|
| 129 | + $spa->SetPingableFlag(true); |
|
| 130 | + } |
|
| 131 | + else { |
|
| 132 | + $spa->DelPingableFlag(); |
|
| 133 | + } |
|
| 134 | + } |
|
| 135 | + } |
|
| 136 | + if (!self::$decoder->getElementEndTag()) { |
|
| 137 | + return false; |
|
| 138 | + } |
|
| 139 | 139 | |
| 140 | - if (!$this->lifetimeBetweenBound($sc->GetLifetime())) { |
|
| 141 | - $pingstatus = SYNC_PINGSTATUS_HBOUTOFRANGE; |
|
| 142 | - SLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): ping lifetime not between bound (higher bound:'%d' lower bound:'%d' current lifetime:'%d'. Returning SYNC_PINGSTATUS_HBOUTOFRANGE.", PING_HIGHER_BOUND_LIFETIME, PING_LOWER_BOUND_LIFETIME, $sc->GetLifetime())); |
|
| 143 | - } |
|
| 144 | - // save changed data |
|
| 145 | - foreach ($sc as $folderid => $spa) { |
|
| 146 | - $sc->SaveCollection($spa); |
|
| 147 | - } |
|
| 148 | - } // END SYNC_PING_PING |
|
| 149 | - else { |
|
| 150 | - // if no ping initialization data was sent, we check if we have pingable folders |
|
| 151 | - // if not, we indicate that there is nothing to do. |
|
| 152 | - if (!$sc->PingableFolders()) { |
|
| 153 | - $pingstatus = SYNC_PINGSTATUS_FAILINGPARAMS; |
|
| 154 | - SLog::Write(LOGLEVEL_DEBUG, "HandlePing(): no pingable folders found and no initialization data sent. Returning SYNC_PINGSTATUS_FAILINGPARAMS."); |
|
| 155 | - } |
|
| 156 | - elseif (!$this->lifetimeBetweenBound($sc->GetLifetime())) { |
|
| 157 | - $pingstatus = SYNC_PINGSTATUS_FAILINGPARAMS; |
|
| 158 | - SLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): ping lifetime not between bound (higher bound:'%d' lower bound:'%d' current lifetime:'%d'. Returning SYNC_PINGSTATUS_FAILINGPARAMS.", PING_HIGHER_BOUND_LIFETIME, PING_LOWER_BOUND_LIFETIME, $sc->GetLifetime())); |
|
| 159 | - } |
|
| 160 | - } |
|
| 140 | + if (!$this->lifetimeBetweenBound($sc->GetLifetime())) { |
|
| 141 | + $pingstatus = SYNC_PINGSTATUS_HBOUTOFRANGE; |
|
| 142 | + SLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): ping lifetime not between bound (higher bound:'%d' lower bound:'%d' current lifetime:'%d'. Returning SYNC_PINGSTATUS_HBOUTOFRANGE.", PING_HIGHER_BOUND_LIFETIME, PING_LOWER_BOUND_LIFETIME, $sc->GetLifetime())); |
|
| 143 | + } |
|
| 144 | + // save changed data |
|
| 145 | + foreach ($sc as $folderid => $spa) { |
|
| 146 | + $sc->SaveCollection($spa); |
|
| 147 | + } |
|
| 148 | + } // END SYNC_PING_PING |
|
| 149 | + else { |
|
| 150 | + // if no ping initialization data was sent, we check if we have pingable folders |
|
| 151 | + // if not, we indicate that there is nothing to do. |
|
| 152 | + if (!$sc->PingableFolders()) { |
|
| 153 | + $pingstatus = SYNC_PINGSTATUS_FAILINGPARAMS; |
|
| 154 | + SLog::Write(LOGLEVEL_DEBUG, "HandlePing(): no pingable folders found and no initialization data sent. Returning SYNC_PINGSTATUS_FAILINGPARAMS."); |
|
| 155 | + } |
|
| 156 | + elseif (!$this->lifetimeBetweenBound($sc->GetLifetime())) { |
|
| 157 | + $pingstatus = SYNC_PINGSTATUS_FAILINGPARAMS; |
|
| 158 | + SLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): ping lifetime not between bound (higher bound:'%d' lower bound:'%d' current lifetime:'%d'. Returning SYNC_PINGSTATUS_FAILINGPARAMS.", PING_HIGHER_BOUND_LIFETIME, PING_LOWER_BOUND_LIFETIME, $sc->GetLifetime())); |
|
| 159 | + } |
|
| 160 | + } |
|
| 161 | 161 | |
| 162 | - // Check for changes on the default LifeTime, set interval and ONLY on pingable collections |
|
| 163 | - try { |
|
| 164 | - if (!$pingstatus && empty($fakechanges)) { |
|
| 165 | - self::$deviceManager->DoAutomaticASDeviceSaving(false); |
|
| 166 | - $foundchanges = $sc->CheckForChanges($sc->GetLifetime(), $interval, true); |
|
| 167 | - } |
|
| 168 | - } |
|
| 169 | - catch (StatusException $ste) { |
|
| 170 | - switch ($ste->getCode()) { |
|
| 171 | - case SyncCollections::ERROR_NO_COLLECTIONS: |
|
| 172 | - $pingstatus = SYNC_PINGSTATUS_FAILINGPARAMS; |
|
| 173 | - break; |
|
| 162 | + // Check for changes on the default LifeTime, set interval and ONLY on pingable collections |
|
| 163 | + try { |
|
| 164 | + if (!$pingstatus && empty($fakechanges)) { |
|
| 165 | + self::$deviceManager->DoAutomaticASDeviceSaving(false); |
|
| 166 | + $foundchanges = $sc->CheckForChanges($sc->GetLifetime(), $interval, true); |
|
| 167 | + } |
|
| 168 | + } |
|
| 169 | + catch (StatusException $ste) { |
|
| 170 | + switch ($ste->getCode()) { |
|
| 171 | + case SyncCollections::ERROR_NO_COLLECTIONS: |
|
| 172 | + $pingstatus = SYNC_PINGSTATUS_FAILINGPARAMS; |
|
| 173 | + break; |
|
| 174 | 174 | |
| 175 | - case SyncCollections::ERROR_WRONG_HIERARCHY: |
|
| 176 | - $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED; |
|
| 177 | - self::$deviceManager->AnnounceProcessStatus(false, $pingstatus); |
|
| 178 | - break; |
|
| 175 | + case SyncCollections::ERROR_WRONG_HIERARCHY: |
|
| 176 | + $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED; |
|
| 177 | + self::$deviceManager->AnnounceProcessStatus(false, $pingstatus); |
|
| 178 | + break; |
|
| 179 | 179 | |
| 180 | - case SyncCollections::OBSOLETE_CONNECTION: |
|
| 181 | - $foundchanges = false; |
|
| 182 | - break; |
|
| 180 | + case SyncCollections::OBSOLETE_CONNECTION: |
|
| 181 | + $foundchanges = false; |
|
| 182 | + break; |
|
| 183 | 183 | |
| 184 | - case SyncCollections::HIERARCHY_CHANGED: |
|
| 185 | - $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED; |
|
| 186 | - break; |
|
| 187 | - } |
|
| 188 | - } |
|
| 184 | + case SyncCollections::HIERARCHY_CHANGED: |
|
| 185 | + $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED; |
|
| 186 | + break; |
|
| 187 | + } |
|
| 188 | + } |
|
| 189 | 189 | |
| 190 | - self::$encoder->StartWBXML(); |
|
| 191 | - self::$encoder->startTag(SYNC_PING_PING); |
|
| 190 | + self::$encoder->StartWBXML(); |
|
| 191 | + self::$encoder->startTag(SYNC_PING_PING); |
|
| 192 | 192 | |
| 193 | - self::$encoder->startTag(SYNC_PING_STATUS); |
|
| 194 | - if (isset($pingstatus) && $pingstatus) { |
|
| 195 | - self::$encoder->content($pingstatus); |
|
| 196 | - } |
|
| 197 | - else { |
|
| 198 | - self::$encoder->content($foundchanges ? SYNC_PINGSTATUS_CHANGES : SYNC_PINGSTATUS_HBEXPIRED); |
|
| 199 | - } |
|
| 200 | - self::$encoder->endTag(); |
|
| 193 | + self::$encoder->startTag(SYNC_PING_STATUS); |
|
| 194 | + if (isset($pingstatus) && $pingstatus) { |
|
| 195 | + self::$encoder->content($pingstatus); |
|
| 196 | + } |
|
| 197 | + else { |
|
| 198 | + self::$encoder->content($foundchanges ? SYNC_PINGSTATUS_CHANGES : SYNC_PINGSTATUS_HBEXPIRED); |
|
| 199 | + } |
|
| 200 | + self::$encoder->endTag(); |
|
| 201 | 201 | |
| 202 | - if (!$pingstatus) { |
|
| 203 | - self::$encoder->startTag(SYNC_PING_FOLDERS); |
|
| 202 | + if (!$pingstatus) { |
|
| 203 | + self::$encoder->startTag(SYNC_PING_FOLDERS); |
|
| 204 | 204 | |
| 205 | - if (empty($fakechanges)) { |
|
| 206 | - $changes = $sc->GetChangedFolderIds(); |
|
| 207 | - } |
|
| 208 | - else { |
|
| 209 | - $changes = $fakechanges; |
|
| 210 | - } |
|
| 205 | + if (empty($fakechanges)) { |
|
| 206 | + $changes = $sc->GetChangedFolderIds(); |
|
| 207 | + } |
|
| 208 | + else { |
|
| 209 | + $changes = $fakechanges; |
|
| 210 | + } |
|
| 211 | 211 | |
| 212 | - $announceAggregated = false; |
|
| 213 | - if (count($changes) > 1) { |
|
| 214 | - $announceAggregated = 0; |
|
| 215 | - } |
|
| 216 | - foreach ($changes as $folderid => $changecount) { |
|
| 217 | - if ($changecount > 0) { |
|
| 218 | - self::$encoder->startTag(SYNC_PING_FOLDER); |
|
| 219 | - self::$encoder->content($folderid); |
|
| 220 | - self::$encoder->endTag(); |
|
| 221 | - if ($announceAggregated === false) { |
|
| 222 | - if (empty($fakechanges)) { |
|
| 223 | - self::$topCollector->AnnounceInformation(sprintf("Found change in %s", $sc->GetCollection($folderid)->GetContentClass()), true); |
|
| 224 | - } |
|
| 225 | - } |
|
| 226 | - else { |
|
| 227 | - $announceAggregated += $changecount; |
|
| 228 | - } |
|
| 229 | - self::$deviceManager->AnnounceProcessStatus($folderid, SYNC_PINGSTATUS_CHANGES); |
|
| 230 | - } |
|
| 231 | - } |
|
| 232 | - if ($announceAggregated !== false) { |
|
| 233 | - self::$topCollector->AnnounceInformation(sprintf("Found %d changes in %d folders", $announceAggregated, count($changes)), true); |
|
| 234 | - } |
|
| 235 | - self::$encoder->endTag(); |
|
| 236 | - } |
|
| 237 | - elseif ($pingstatus == SYNC_PINGSTATUS_HBOUTOFRANGE) { |
|
| 238 | - self::$encoder->startTag(SYNC_PING_LIFETIME); |
|
| 239 | - if ($sc->GetLifetime() > PING_HIGHER_BOUND_LIFETIME) { |
|
| 240 | - self::$encoder->content(PING_HIGHER_BOUND_LIFETIME); |
|
| 241 | - } |
|
| 242 | - else { |
|
| 243 | - self::$encoder->content(PING_LOWER_BOUND_LIFETIME); |
|
| 244 | - } |
|
| 245 | - self::$encoder->endTag(); |
|
| 246 | - } |
|
| 212 | + $announceAggregated = false; |
|
| 213 | + if (count($changes) > 1) { |
|
| 214 | + $announceAggregated = 0; |
|
| 215 | + } |
|
| 216 | + foreach ($changes as $folderid => $changecount) { |
|
| 217 | + if ($changecount > 0) { |
|
| 218 | + self::$encoder->startTag(SYNC_PING_FOLDER); |
|
| 219 | + self::$encoder->content($folderid); |
|
| 220 | + self::$encoder->endTag(); |
|
| 221 | + if ($announceAggregated === false) { |
|
| 222 | + if (empty($fakechanges)) { |
|
| 223 | + self::$topCollector->AnnounceInformation(sprintf("Found change in %s", $sc->GetCollection($folderid)->GetContentClass()), true); |
|
| 224 | + } |
|
| 225 | + } |
|
| 226 | + else { |
|
| 227 | + $announceAggregated += $changecount; |
|
| 228 | + } |
|
| 229 | + self::$deviceManager->AnnounceProcessStatus($folderid, SYNC_PINGSTATUS_CHANGES); |
|
| 230 | + } |
|
| 231 | + } |
|
| 232 | + if ($announceAggregated !== false) { |
|
| 233 | + self::$topCollector->AnnounceInformation(sprintf("Found %d changes in %d folders", $announceAggregated, count($changes)), true); |
|
| 234 | + } |
|
| 235 | + self::$encoder->endTag(); |
|
| 236 | + } |
|
| 237 | + elseif ($pingstatus == SYNC_PINGSTATUS_HBOUTOFRANGE) { |
|
| 238 | + self::$encoder->startTag(SYNC_PING_LIFETIME); |
|
| 239 | + if ($sc->GetLifetime() > PING_HIGHER_BOUND_LIFETIME) { |
|
| 240 | + self::$encoder->content(PING_HIGHER_BOUND_LIFETIME); |
|
| 241 | + } |
|
| 242 | + else { |
|
| 243 | + self::$encoder->content(PING_LOWER_BOUND_LIFETIME); |
|
| 244 | + } |
|
| 245 | + self::$encoder->endTag(); |
|
| 246 | + } |
|
| 247 | 247 | |
| 248 | - self::$encoder->endTag(); |
|
| 248 | + self::$encoder->endTag(); |
|
| 249 | 249 | |
| 250 | - // update the waittime waited |
|
| 251 | - self::$waitTime = $sc->GetWaitedSeconds(); |
|
| 250 | + // update the waittime waited |
|
| 251 | + self::$waitTime = $sc->GetWaitedSeconds(); |
|
| 252 | 252 | |
| 253 | - return true; |
|
| 254 | - } |
|
| 253 | + return true; |
|
| 254 | + } |
|
| 255 | 255 | |
| 256 | - /** |
|
| 257 | - * Return true if the ping lifetime is between the specified bound (PING_HIGHER_BOUND_LIFETIME and PING_LOWER_BOUND_LIFETIME). If no bound are specified, it returns true. |
|
| 258 | - * |
|
| 259 | - * @param int $lifetime |
|
| 260 | - * |
|
| 261 | - * @return bool |
|
| 262 | - */ |
|
| 263 | - private function lifetimeBetweenBound($lifetime) { |
|
| 264 | - if (PING_HIGHER_BOUND_LIFETIME !== false && PING_LOWER_BOUND_LIFETIME !== false) { |
|
| 265 | - return $lifetime <= PING_HIGHER_BOUND_LIFETIME && $lifetime >= PING_LOWER_BOUND_LIFETIME; |
|
| 266 | - } |
|
| 267 | - if (PING_HIGHER_BOUND_LIFETIME !== false) { |
|
| 268 | - return $lifetime <= PING_HIGHER_BOUND_LIFETIME; |
|
| 269 | - } |
|
| 270 | - if (PING_LOWER_BOUND_LIFETIME !== false) { |
|
| 271 | - return $lifetime >= PING_LOWER_BOUND_LIFETIME; |
|
| 272 | - } |
|
| 256 | + /** |
|
| 257 | + * Return true if the ping lifetime is between the specified bound (PING_HIGHER_BOUND_LIFETIME and PING_LOWER_BOUND_LIFETIME). If no bound are specified, it returns true. |
|
| 258 | + * |
|
| 259 | + * @param int $lifetime |
|
| 260 | + * |
|
| 261 | + * @return bool |
|
| 262 | + */ |
|
| 263 | + private function lifetimeBetweenBound($lifetime) { |
|
| 264 | + if (PING_HIGHER_BOUND_LIFETIME !== false && PING_LOWER_BOUND_LIFETIME !== false) { |
|
| 265 | + return $lifetime <= PING_HIGHER_BOUND_LIFETIME && $lifetime >= PING_LOWER_BOUND_LIFETIME; |
|
| 266 | + } |
|
| 267 | + if (PING_HIGHER_BOUND_LIFETIME !== false) { |
|
| 268 | + return $lifetime <= PING_HIGHER_BOUND_LIFETIME; |
|
| 269 | + } |
|
| 270 | + if (PING_LOWER_BOUND_LIFETIME !== false) { |
|
| 271 | + return $lifetime >= PING_LOWER_BOUND_LIFETIME; |
|
| 272 | + } |
|
| 273 | 273 | |
| 274 | - return true; |
|
| 275 | - } |
|
| 274 | + return true; |
|
| 275 | + } |
|
| 276 | 276 | } |
@@ -30,27 +30,23 @@ discard block |
||
| 30 | 30 | // Load all collections - do load states, check permissions and allow unconfirmed states |
| 31 | 31 | try { |
| 32 | 32 | $sc->LoadAllCollections(true, true, true, true, false); |
| 33 | - } |
|
| 34 | - catch (StateInvalidException $siex) { |
|
| 33 | + } catch (StateInvalidException $siex) { |
|
| 35 | 34 | // if no params are present, indicate to send params, else do hierarchy sync |
| 36 | 35 | if (!$params_present) { |
| 37 | 36 | $pingstatus = SYNC_PINGSTATUS_FAILINGPARAMS; |
| 38 | 37 | self::$topCollector->AnnounceInformation("StateInvalidException: require PingParameters", true); |
| 39 | - } |
|
| 40 | - elseif (self::$deviceManager->IsHierarchySyncRequired()) { |
|
| 38 | + } elseif (self::$deviceManager->IsHierarchySyncRequired()) { |
|
| 41 | 39 | // we could be in a looping - see LoopDetection->ProcessLoopDetectionIsHierarchySyncAdvised() |
| 42 | 40 | $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED; |
| 43 | 41 | self::$topCollector->AnnounceInformation("Potential loop detection: require HierarchySync", true); |
| 44 | - } |
|
| 45 | - else { |
|
| 42 | + } else { |
|
| 46 | 43 | // we do not have a ping status for this, but SyncCollections should have generated fake changes for the folders which are broken |
| 47 | 44 | $fakechanges = $sc->GetChangedFolderIds(); |
| 48 | 45 | $foundchanges = true; |
| 49 | 46 | |
| 50 | 47 | self::$topCollector->AnnounceInformation("StateInvalidException: force sync", true); |
| 51 | 48 | } |
| 52 | - } |
|
| 53 | - catch (StatusException $stex) { |
|
| 49 | + } catch (StatusException $stex) { |
|
| 54 | 50 | $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED; |
| 55 | 51 | self::$topCollector->AnnounceInformation("StatusException: require HierarchySync", true); |
| 56 | 52 | } |
@@ -103,8 +99,7 @@ discard block |
||
| 103 | 99 | |
| 104 | 100 | continue; |
| 105 | 101 | } |
| 106 | - } |
|
| 107 | - catch (NoHierarchyCacheAvailableException $nhca) { |
|
| 102 | + } catch (NoHierarchyCacheAvailableException $nhca) { |
|
| 108 | 103 | SLog::Write(LOGLEVEL_INFO, sprintf("HandlePing(): unknown collection '%s', triggering HierarchySync", $folderid)); |
| 109 | 104 | $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED; |
| 110 | 105 | } |
@@ -112,8 +107,7 @@ discard block |
||
| 112 | 107 | // Trigger a Sync request because then the device will be forced to resync this folder. |
| 113 | 108 | $fakechanges[$folderid] = 1; |
| 114 | 109 | $foundchanges = true; |
| 115 | - } |
|
| 116 | - elseif ($class == $spa->GetContentClass()) { |
|
| 110 | + } elseif ($class == $spa->GetContentClass()) { |
|
| 117 | 111 | $pingable[] = $folderid; |
| 118 | 112 | SLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): using saved sync state for '%s' id '%s'", $spa->GetContentClass(), $folderid)); |
| 119 | 113 | } |
@@ -127,8 +121,7 @@ discard block |
||
| 127 | 121 | // if the folderid is in $pingable, we should ping it, else remove the flag |
| 128 | 122 | if (in_array($folderid, $pingable)) { |
| 129 | 123 | $spa->SetPingableFlag(true); |
| 130 | - } |
|
| 131 | - else { |
|
| 124 | + } else { |
|
| 132 | 125 | $spa->DelPingableFlag(); |
| 133 | 126 | } |
| 134 | 127 | } |
@@ -152,8 +145,7 @@ discard block |
||
| 152 | 145 | if (!$sc->PingableFolders()) { |
| 153 | 146 | $pingstatus = SYNC_PINGSTATUS_FAILINGPARAMS; |
| 154 | 147 | SLog::Write(LOGLEVEL_DEBUG, "HandlePing(): no pingable folders found and no initialization data sent. Returning SYNC_PINGSTATUS_FAILINGPARAMS."); |
| 155 | - } |
|
| 156 | - elseif (!$this->lifetimeBetweenBound($sc->GetLifetime())) { |
|
| 148 | + } elseif (!$this->lifetimeBetweenBound($sc->GetLifetime())) { |
|
| 157 | 149 | $pingstatus = SYNC_PINGSTATUS_FAILINGPARAMS; |
| 158 | 150 | SLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): ping lifetime not between bound (higher bound:'%d' lower bound:'%d' current lifetime:'%d'. Returning SYNC_PINGSTATUS_FAILINGPARAMS.", PING_HIGHER_BOUND_LIFETIME, PING_LOWER_BOUND_LIFETIME, $sc->GetLifetime())); |
| 159 | 151 | } |
@@ -165,8 +157,7 @@ discard block |
||
| 165 | 157 | self::$deviceManager->DoAutomaticASDeviceSaving(false); |
| 166 | 158 | $foundchanges = $sc->CheckForChanges($sc->GetLifetime(), $interval, true); |
| 167 | 159 | } |
| 168 | - } |
|
| 169 | - catch (StatusException $ste) { |
|
| 160 | + } catch (StatusException $ste) { |
|
| 170 | 161 | switch ($ste->getCode()) { |
| 171 | 162 | case SyncCollections::ERROR_NO_COLLECTIONS: |
| 172 | 163 | $pingstatus = SYNC_PINGSTATUS_FAILINGPARAMS; |
@@ -193,8 +184,7 @@ discard block |
||
| 193 | 184 | self::$encoder->startTag(SYNC_PING_STATUS); |
| 194 | 185 | if (isset($pingstatus) && $pingstatus) { |
| 195 | 186 | self::$encoder->content($pingstatus); |
| 196 | - } |
|
| 197 | - else { |
|
| 187 | + } else { |
|
| 198 | 188 | self::$encoder->content($foundchanges ? SYNC_PINGSTATUS_CHANGES : SYNC_PINGSTATUS_HBEXPIRED); |
| 199 | 189 | } |
| 200 | 190 | self::$encoder->endTag(); |
@@ -204,8 +194,7 @@ discard block |
||
| 204 | 194 | |
| 205 | 195 | if (empty($fakechanges)) { |
| 206 | 196 | $changes = $sc->GetChangedFolderIds(); |
| 207 | - } |
|
| 208 | - else { |
|
| 197 | + } else { |
|
| 209 | 198 | $changes = $fakechanges; |
| 210 | 199 | } |
| 211 | 200 | |
@@ -222,8 +211,7 @@ discard block |
||
| 222 | 211 | if (empty($fakechanges)) { |
| 223 | 212 | self::$topCollector->AnnounceInformation(sprintf("Found change in %s", $sc->GetCollection($folderid)->GetContentClass()), true); |
| 224 | 213 | } |
| 225 | - } |
|
| 226 | - else { |
|
| 214 | + } else { |
|
| 227 | 215 | $announceAggregated += $changecount; |
| 228 | 216 | } |
| 229 | 217 | self::$deviceManager->AnnounceProcessStatus($folderid, SYNC_PINGSTATUS_CHANGES); |
@@ -233,13 +221,11 @@ discard block |
||
| 233 | 221 | self::$topCollector->AnnounceInformation(sprintf("Found %d changes in %d folders", $announceAggregated, count($changes)), true); |
| 234 | 222 | } |
| 235 | 223 | self::$encoder->endTag(); |
| 236 | - } |
|
| 237 | - elseif ($pingstatus == SYNC_PINGSTATUS_HBOUTOFRANGE) { |
|
| 224 | + } elseif ($pingstatus == SYNC_PINGSTATUS_HBOUTOFRANGE) { |
|
| 238 | 225 | self::$encoder->startTag(SYNC_PING_LIFETIME); |
| 239 | 226 | if ($sc->GetLifetime() > PING_HIGHER_BOUND_LIFETIME) { |
| 240 | 227 | self::$encoder->content(PING_HIGHER_BOUND_LIFETIME); |
| 241 | - } |
|
| 242 | - else { |
|
| 228 | + } else { |
|
| 243 | 229 | self::$encoder->content(PING_LOWER_BOUND_LIFETIME); |
| 244 | 230 | } |
| 245 | 231 | self::$encoder->endTag(); |
@@ -8,428 +8,428 @@ |
||
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | 10 | class ItemOperations extends RequestProcessor { |
| 11 | - /** |
|
| 12 | - * Handles the ItemOperations command |
|
| 13 | - * Provides batched online handling for Fetch, EmptyFolderContents and Move. |
|
| 14 | - * |
|
| 15 | - * @param int $commandCode |
|
| 16 | - * |
|
| 17 | - * @return bool |
|
| 18 | - */ |
|
| 19 | - public function Handle($commandCode) { |
|
| 20 | - // Parse input |
|
| 21 | - if (!self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_ITEMOPERATIONS)) { |
|
| 22 | - return false; |
|
| 23 | - } |
|
| 24 | - |
|
| 25 | - $itemoperations = []; |
|
| 26 | - // ItemOperations can either be Fetch, EmptyFolderContents or Move |
|
| 27 | - WBXMLDecoder::ResetInWhile("itemOperationsActions"); |
|
| 28 | - while (WBXMLDecoder::InWhile("itemOperationsActions")) { |
|
| 29 | - // TODO check if multiple item operations are possible in one request |
|
| 30 | - $el = self::$decoder->getElement(); |
|
| 31 | - |
|
| 32 | - if ($el[EN_TYPE] != EN_TYPE_STARTTAG) { |
|
| 33 | - return false; |
|
| 34 | - } |
|
| 35 | - |
|
| 36 | - $fetch = $efc = $move = false; |
|
| 37 | - $operation = []; |
|
| 38 | - if ($el[EN_TAG] == SYNC_ITEMOPERATIONS_FETCH) { |
|
| 39 | - $fetch = true; |
|
| 40 | - $operation['operation'] = SYNC_ITEMOPERATIONS_FETCH; |
|
| 41 | - self::$topCollector->AnnounceInformation("Fetch", true); |
|
| 42 | - } |
|
| 43 | - elseif ($el[EN_TAG] == SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS) { |
|
| 44 | - $efc = true; |
|
| 45 | - $operation['operation'] = SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS; |
|
| 46 | - self::$topCollector->AnnounceInformation("Empty Folder", true); |
|
| 47 | - } |
|
| 48 | - elseif ($el[EN_TAG] == SYNC_ITEMOPERATIONS_MOVE) { |
|
| 49 | - $move = true; |
|
| 50 | - $operation['operation'] = SYNC_ITEMOPERATIONS_MOVE; |
|
| 51 | - self::$topCollector->AnnounceInformation("Move", true); |
|
| 52 | - } |
|
| 53 | - |
|
| 54 | - if (!$fetch && !$efc && !$move) { |
|
| 55 | - SLog::Write(LOGLEVEL_DEBUG, "Unknown item operation:" . print_r($el, 1)); |
|
| 56 | - self::$topCollector->AnnounceInformation("Unknown operation", true); |
|
| 57 | - |
|
| 58 | - return false; |
|
| 59 | - } |
|
| 60 | - |
|
| 61 | - // process operation |
|
| 62 | - WBXMLDecoder::ResetInWhile("itemOperationsOperation"); |
|
| 63 | - while (WBXMLDecoder::InWhile("itemOperationsOperation")) { |
|
| 64 | - if ($fetch) { |
|
| 65 | - // Save all OPTIONS into a ContentParameters object |
|
| 66 | - $operation["cpo"] = new ContentParameters(); |
|
| 67 | - |
|
| 68 | - if (self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_STORE)) { |
|
| 69 | - $operation['store'] = self::$decoder->getElementContent(); |
|
| 70 | - if (!self::$decoder->getElementEndTag()) { |
|
| 71 | - return false; |
|
| 72 | - }// SYNC_ITEMOPERATIONS_STORE |
|
| 73 | - } |
|
| 74 | - |
|
| 75 | - if (self::$decoder->getElementStartTag(SYNC_SEARCH_LONGID)) { |
|
| 76 | - $operation['longid'] = self::$decoder->getElementContent(); |
|
| 77 | - if (!self::$decoder->getElementEndTag()) { |
|
| 78 | - return false; |
|
| 79 | - }// SYNC_SEARCH_LONGID |
|
| 80 | - } |
|
| 81 | - |
|
| 82 | - if (self::$decoder->getElementStartTag(SYNC_FOLDERID)) { |
|
| 83 | - $operation['folderid'] = self::$decoder->getElementContent(); |
|
| 84 | - if (!self::$decoder->getElementEndTag()) { |
|
| 85 | - return false; |
|
| 86 | - }// SYNC_FOLDERID |
|
| 87 | - } |
|
| 88 | - |
|
| 89 | - if (self::$decoder->getElementStartTag(SYNC_SERVERENTRYID)) { |
|
| 90 | - $operation['serverid'] = self::$decoder->getElementContent(); |
|
| 91 | - if (!self::$decoder->getElementEndTag()) { |
|
| 92 | - return false; |
|
| 93 | - }// SYNC_SERVERENTRYID |
|
| 94 | - } |
|
| 95 | - |
|
| 96 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_FILEREFERENCE)) { |
|
| 97 | - $operation['filereference'] = self::$decoder->getElementContent(); |
|
| 98 | - if (!self::$decoder->getElementEndTag()) { |
|
| 99 | - return false; |
|
| 100 | - }// SYNC_AIRSYNCBASE_FILEREFERENCE |
|
| 101 | - } |
|
| 102 | - |
|
| 103 | - if (($el = self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_OPTIONS)) && ($el[EN_FLAGS] & EN_FLAGS_CONTENT)) { |
|
| 104 | - // TODO other options |
|
| 105 | - // schema |
|
| 106 | - // range |
|
| 107 | - // username |
|
| 108 | - // password |
|
| 109 | - // bodypartpreference |
|
| 110 | - // rm:RightsManagementSupport |
|
| 111 | - |
|
| 112 | - WBXMLDecoder::ResetInWhile("itemOperationsOptions"); |
|
| 113 | - while (WBXMLDecoder::InWhile("itemOperationsOptions")) { |
|
| 114 | - while (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_BODYPREFERENCE)) { |
|
| 115 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TYPE)) { |
|
| 116 | - $bptype = self::$decoder->getElementContent(); |
|
| 117 | - $operation["cpo"]->BodyPreference($bptype); |
|
| 118 | - if (!self::$decoder->getElementEndTag()) { |
|
| 119 | - return false; |
|
| 120 | - } |
|
| 121 | - } |
|
| 122 | - |
|
| 123 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TRUNCATIONSIZE)) { |
|
| 124 | - $operation["cpo"]->BodyPreference($bptype)->SetTruncationSize(self::$decoder->getElementContent()); |
|
| 125 | - if (!self::$decoder->getElementEndTag()) { |
|
| 126 | - return false; |
|
| 127 | - } |
|
| 128 | - } |
|
| 129 | - |
|
| 130 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_ALLORNONE)) { |
|
| 131 | - $operation["cpo"]->BodyPreference($bptype)->SetAllOrNone(self::$decoder->getElementContent()); |
|
| 132 | - if (!self::$decoder->getElementEndTag()) { |
|
| 133 | - return false; |
|
| 134 | - } |
|
| 135 | - } |
|
| 136 | - |
|
| 137 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_PREVIEW)) { |
|
| 138 | - $operation["cpo"]->BodyPreference($bptype)->SetPreview(self::$decoder->getElementContent()); |
|
| 139 | - if (!self::$decoder->getElementEndTag()) { |
|
| 140 | - return false; |
|
| 141 | - } |
|
| 142 | - } |
|
| 143 | - |
|
| 144 | - if (!self::$decoder->getElementEndTag()) { |
|
| 145 | - return false; |
|
| 146 | - }// SYNC_AIRSYNCBASE_BODYPREFERENCE |
|
| 147 | - } |
|
| 148 | - |
|
| 149 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_BODYPARTPREFERENCE)) { |
|
| 150 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TYPE)) { |
|
| 151 | - $bpptype = self::$decoder->getElementContent(); |
|
| 152 | - $operation["cpo"]->BodyPartPreference($bpptype); |
|
| 153 | - if (!self::$decoder->getElementEndTag()) { |
|
| 154 | - return false; |
|
| 155 | - } |
|
| 156 | - } |
|
| 157 | - |
|
| 158 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TRUNCATIONSIZE)) { |
|
| 159 | - $operation["cpo"]->BodyPartPreference($bpptype)->SetTruncationSize(self::$decoder->getElementContent()); |
|
| 160 | - if (!self::$decoder->getElementEndTag()) { |
|
| 161 | - return false; |
|
| 162 | - } |
|
| 163 | - } |
|
| 164 | - |
|
| 165 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_ALLORNONE)) { |
|
| 166 | - $operation["cpo"]->BodyPartPreference($bpptype)->SetAllOrNone(self::$decoder->getElementContent()); |
|
| 167 | - if (!self::$decoder->getElementEndTag()) { |
|
| 168 | - return false; |
|
| 169 | - } |
|
| 170 | - } |
|
| 171 | - |
|
| 172 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_PREVIEW)) { |
|
| 173 | - $operation["cpo"]->BodyPartPreference($bpptype)->SetPreview(self::$decoder->getElementContent()); |
|
| 174 | - if (!self::$decoder->getElementEndTag()) { |
|
| 175 | - return false; |
|
| 176 | - } |
|
| 177 | - } |
|
| 178 | - |
|
| 179 | - if (!self::$decoder->getElementEndTag()) { |
|
| 180 | - return false; |
|
| 181 | - } |
|
| 182 | - } |
|
| 183 | - |
|
| 184 | - if (self::$decoder->getElementStartTag(SYNC_MIMESUPPORT)) { |
|
| 185 | - $operation["cpo"]->SetMimeSupport(self::$decoder->getElementContent()); |
|
| 186 | - if (!self::$decoder->getElementEndTag()) { |
|
| 187 | - return false; |
|
| 188 | - } |
|
| 189 | - } |
|
| 190 | - |
|
| 191 | - if (self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_RANGE)) { |
|
| 192 | - $operation["range"] = self::$decoder->getElementContent(); |
|
| 193 | - if (!self::$decoder->getElementEndTag()) { |
|
| 194 | - return false; |
|
| 195 | - } |
|
| 196 | - } |
|
| 197 | - |
|
| 198 | - if (self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_SCHEMA)) { |
|
| 199 | - // read schema tags |
|
| 200 | - WBXMLDecoder::ResetInWhile("itemOperationsSchema"); |
|
| 201 | - while (WBXMLDecoder::InWhile("itemOperationsSchema")) { |
|
| 202 | - // TODO save elements |
|
| 203 | - $el = self::$decoder->getElement(); |
|
| 204 | - $e = self::$decoder->peek(); |
|
| 205 | - if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { |
|
| 206 | - self::$decoder->getElementEndTag(); |
|
| 207 | - |
|
| 208 | - break; |
|
| 209 | - } |
|
| 210 | - } |
|
| 211 | - } |
|
| 212 | - |
|
| 213 | - if (self::$decoder->getElementStartTag(SYNC_RIGHTSMANAGEMENT_SUPPORT)) { |
|
| 214 | - $operation["cpo"]->SetRmSupport(self::$decoder->getElementContent()); |
|
| 215 | - if (!self::$decoder->getElementEndTag()) { |
|
| 216 | - return false; |
|
| 217 | - } |
|
| 218 | - } |
|
| 219 | - |
|
| 220 | - // break if it reached the endtag |
|
| 221 | - $e = self::$decoder->peek(); |
|
| 222 | - if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { |
|
| 223 | - self::$decoder->getElementEndTag(); |
|
| 224 | - |
|
| 225 | - break; |
|
| 226 | - } |
|
| 227 | - } |
|
| 228 | - } |
|
| 229 | - |
|
| 230 | - if (self::$decoder->getElementStartTag(SYNC_RIGHTSMANAGEMENT_REMOVERIGHTSMGNTPROTECTION)) { |
|
| 231 | - $operation["cpo"]->SetRemoveRmProtection(true); |
|
| 232 | - if (($rrmp = self::$decoder->getElementContent()) !== false) { |
|
| 233 | - $operation["cpo"]->SetRemoveRmProtection($rrmp); |
|
| 234 | - if (!self::$decoder->getElementEndTag()) { |
|
| 235 | - return false; |
|
| 236 | - } |
|
| 237 | - } |
|
| 238 | - } |
|
| 239 | - } // end if fetch |
|
| 240 | - |
|
| 241 | - if ($efc) { |
|
| 242 | - if (self::$decoder->getElementStartTag(SYNC_FOLDERID)) { |
|
| 243 | - $operation['folderid'] = self::$decoder->getElementContent(); |
|
| 244 | - if (!self::$decoder->getElementEndTag()) { |
|
| 245 | - return false; |
|
| 246 | - }// SYNC_FOLDERID |
|
| 247 | - } |
|
| 248 | - if (self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_OPTIONS)) { |
|
| 249 | - if (self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_DELETESUBFOLDERS)) { |
|
| 250 | - $operation['deletesubfolders'] = true; |
|
| 251 | - if (($dsf = self::$decoder->getElementContent()) !== false) { |
|
| 252 | - $operation['deletesubfolders'] = (bool) $dsf; |
|
| 253 | - if (!self::$decoder->getElementEndTag()) { |
|
| 254 | - return false; |
|
| 255 | - } |
|
| 256 | - } |
|
| 257 | - } |
|
| 258 | - self::$decoder->getElementEndTag(); |
|
| 259 | - } |
|
| 260 | - } |
|
| 261 | - |
|
| 262 | - // TODO move |
|
| 263 | - |
|
| 264 | - // break if it reached the endtag SYNC_ITEMOPERATIONS_FETCH or SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS or SYNC_ITEMOPERATIONS_MOVE |
|
| 265 | - $e = self::$decoder->peek(); |
|
| 266 | - if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { |
|
| 267 | - self::$decoder->getElementEndTag(); |
|
| 268 | - |
|
| 269 | - break; |
|
| 270 | - } |
|
| 271 | - } // end while operation |
|
| 272 | - |
|
| 273 | - // rewrite folderid into backendfolderid to be used on backend operations below |
|
| 274 | - if (isset($operation['folderid'])) { |
|
| 275 | - $operation['backendfolderid'] = self::$deviceManager->GetBackendIdForFolderId($operation['folderid']); |
|
| 276 | - } |
|
| 277 | - |
|
| 278 | - $itemoperations[] = $operation; |
|
| 279 | - // break if it reached the endtag |
|
| 280 | - $e = self::$decoder->peek(); |
|
| 281 | - if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { |
|
| 282 | - self::$decoder->getElementEndTag(); // SYNC_ITEMOPERATIONS_ITEMOPERATIONS |
|
| 283 | - |
|
| 284 | - break; |
|
| 285 | - } |
|
| 286 | - } // end operations loop |
|
| 287 | - |
|
| 288 | - $status = SYNC_ITEMOPERATIONSSTATUS_SUCCESS; |
|
| 289 | - |
|
| 290 | - self::$encoder->startWBXML(); |
|
| 291 | - |
|
| 292 | - self::$encoder->startTag(SYNC_ITEMOPERATIONS_ITEMOPERATIONS); |
|
| 293 | - |
|
| 294 | - self::$encoder->startTag(SYNC_ITEMOPERATIONS_STATUS); |
|
| 295 | - self::$encoder->content($status); |
|
| 296 | - self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_STATUS |
|
| 297 | - |
|
| 298 | - // Stop here if something went wrong |
|
| 299 | - if ($status != SYNC_ITEMOPERATIONSSTATUS_SUCCESS) { |
|
| 300 | - self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_ITEMOPERATIONS |
|
| 301 | - |
|
| 302 | - return true; |
|
| 303 | - } |
|
| 304 | - |
|
| 305 | - self::$encoder->startTag(SYNC_ITEMOPERATIONS_RESPONSE); |
|
| 306 | - |
|
| 307 | - foreach ($itemoperations as $operation) { |
|
| 308 | - // fetch response |
|
| 309 | - if ($operation['operation'] == SYNC_ITEMOPERATIONS_FETCH) { |
|
| 310 | - $status = SYNC_ITEMOPERATIONSSTATUS_SUCCESS; |
|
| 311 | - |
|
| 312 | - // retrieve the data |
|
| 313 | - // Fetch throws Sync status codes, - GetAttachmentData ItemOperations codes |
|
| 314 | - if (isset($operation['filereference'])) { |
|
| 315 | - try { |
|
| 316 | - self::$topCollector->AnnounceInformation("Get attachment data from backend with file reference"); |
|
| 317 | - $data = self::$backend->GetAttachmentData($operation['filereference']); |
|
| 318 | - } |
|
| 319 | - catch (StatusException $stex) { |
|
| 320 | - $status = $stex->getCode(); |
|
| 321 | - } |
|
| 322 | - } |
|
| 323 | - else { |
|
| 324 | - try { |
|
| 325 | - if (isset($operation['folderid'], $operation['serverid'])) { |
|
| 326 | - self::$topCollector->AnnounceInformation("Fetching data from backend with item and folder id"); |
|
| 327 | - $data = self::$backend->Fetch($operation['backendfolderid'], $operation['serverid'], $operation["cpo"]); |
|
| 328 | - } |
|
| 329 | - elseif (isset($operation['longid'])) { |
|
| 330 | - self::$topCollector->AnnounceInformation("Fetching data from backend with long id"); |
|
| 331 | - $tmp = explode(":", $operation['longid']); |
|
| 332 | - $data = self::$backend->Fetch(self::$deviceManager->GetBackendIdForFolderId($tmp[0]), $tmp[1], $operation["cpo"]); |
|
| 333 | - } |
|
| 334 | - } |
|
| 335 | - catch (StatusException $stex) { |
|
| 336 | - // the only option to return is that we could not retrieve it |
|
| 337 | - $status = SYNC_ITEMOPERATIONSSTATUS_CONVERSIONFAILED; |
|
| 338 | - } |
|
| 339 | - } |
|
| 340 | - |
|
| 341 | - self::$encoder->startTag(SYNC_ITEMOPERATIONS_FETCH); |
|
| 342 | - |
|
| 343 | - self::$encoder->startTag(SYNC_ITEMOPERATIONS_STATUS); |
|
| 344 | - self::$encoder->content($status); |
|
| 345 | - self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_STATUS |
|
| 346 | - |
|
| 347 | - if (isset($operation['folderid'], $operation['serverid'])) { |
|
| 348 | - self::$encoder->startTag(SYNC_FOLDERID); |
|
| 349 | - self::$encoder->content($operation['folderid']); |
|
| 350 | - self::$encoder->endTag(); // end SYNC_FOLDERID |
|
| 351 | - |
|
| 352 | - self::$encoder->startTag(SYNC_SERVERENTRYID); |
|
| 353 | - self::$encoder->content($operation['serverid']); |
|
| 354 | - self::$encoder->endTag(); // end SYNC_SERVERENTRYID |
|
| 355 | - |
|
| 356 | - self::$encoder->startTag(SYNC_FOLDERTYPE); |
|
| 357 | - self::$encoder->content("Email"); |
|
| 358 | - self::$encoder->endTag(); |
|
| 359 | - } |
|
| 360 | - |
|
| 361 | - if (isset($operation['longid'])) { |
|
| 362 | - self::$encoder->startTag(SYNC_SEARCH_LONGID); |
|
| 363 | - self::$encoder->content($operation['longid']); |
|
| 364 | - self::$encoder->endTag(); // end SYNC_FOLDERID |
|
| 365 | - |
|
| 366 | - self::$encoder->startTag(SYNC_FOLDERTYPE); |
|
| 367 | - self::$encoder->content("Email"); |
|
| 368 | - self::$encoder->endTag(); |
|
| 369 | - } |
|
| 370 | - |
|
| 371 | - if (isset($operation['filereference'])) { |
|
| 372 | - self::$encoder->startTag(SYNC_AIRSYNCBASE_FILEREFERENCE); |
|
| 373 | - self::$encoder->content($operation['filereference']); |
|
| 374 | - self::$encoder->endTag(); // end SYNC_AIRSYNCBASE_FILEREFERENCE |
|
| 375 | - } |
|
| 376 | - |
|
| 377 | - if (isset($data)) { |
|
| 378 | - self::$topCollector->AnnounceInformation("Streaming data"); |
|
| 379 | - |
|
| 380 | - self::$encoder->startTag(SYNC_ITEMOPERATIONS_PROPERTIES); |
|
| 381 | - if (isset($operation['range'])) { |
|
| 382 | - self::$encoder->startTag(SYNC_ITEMOPERATIONS_RANGE); |
|
| 383 | - self::$encoder->content($operation['range']); |
|
| 384 | - self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_RANGE |
|
| 385 | - } |
|
| 386 | - $data->Encode(self::$encoder); |
|
| 387 | - self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_PROPERTIES |
|
| 388 | - } |
|
| 389 | - |
|
| 390 | - self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_FETCH |
|
| 391 | - } |
|
| 392 | - // empty folder contents operation |
|
| 393 | - elseif ($operation['operation'] == SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS) { |
|
| 394 | - try { |
|
| 395 | - self::$topCollector->AnnounceInformation("Emptying folder"); |
|
| 396 | - |
|
| 397 | - // send request to backend |
|
| 398 | - self::$backend->EmptyFolder($operation['backendfolderid'], $operation['deletesubfolders']); |
|
| 399 | - } |
|
| 400 | - catch (StatusException $stex) { |
|
| 401 | - $status = $stex->getCode(); |
|
| 402 | - } |
|
| 403 | - |
|
| 404 | - self::$encoder->startTag(SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS); |
|
| 405 | - |
|
| 406 | - self::$encoder->startTag(SYNC_ITEMOPERATIONS_STATUS); |
|
| 407 | - self::$encoder->content($status); |
|
| 408 | - self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_STATUS |
|
| 409 | - |
|
| 410 | - if (isset($operation['folderid'])) { |
|
| 411 | - self::$encoder->startTag(SYNC_FOLDERID); |
|
| 412 | - self::$encoder->content($operation['folderid']); |
|
| 413 | - self::$encoder->endTag(); // end SYNC_FOLDERID |
|
| 414 | - } |
|
| 415 | - self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS |
|
| 416 | - } |
|
| 417 | - // TODO implement ItemOperations Move |
|
| 418 | - // move operation |
|
| 419 | - else { |
|
| 420 | - self::$topCollector->AnnounceInformation("not implemented", true); |
|
| 421 | - |
|
| 422 | - // reply with "can't do" |
|
| 423 | - self::$encoder->startTag(SYNC_ITEMOPERATIONS_MOVE); |
|
| 424 | - self::$encoder->startTag(SYNC_ITEMOPERATIONS_STATUS); |
|
| 425 | - self::$encoder->content(SYNC_ITEMOPERATIONSSTATUS_SERVERERROR); |
|
| 426 | - self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_STATUS |
|
| 427 | - self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_MOVE |
|
| 428 | - } |
|
| 429 | - } |
|
| 430 | - self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_RESPONSE |
|
| 431 | - self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_ITEMOPERATIONS |
|
| 432 | - |
|
| 433 | - return true; |
|
| 434 | - } |
|
| 11 | + /** |
|
| 12 | + * Handles the ItemOperations command |
|
| 13 | + * Provides batched online handling for Fetch, EmptyFolderContents and Move. |
|
| 14 | + * |
|
| 15 | + * @param int $commandCode |
|
| 16 | + * |
|
| 17 | + * @return bool |
|
| 18 | + */ |
|
| 19 | + public function Handle($commandCode) { |
|
| 20 | + // Parse input |
|
| 21 | + if (!self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_ITEMOPERATIONS)) { |
|
| 22 | + return false; |
|
| 23 | + } |
|
| 24 | + |
|
| 25 | + $itemoperations = []; |
|
| 26 | + // ItemOperations can either be Fetch, EmptyFolderContents or Move |
|
| 27 | + WBXMLDecoder::ResetInWhile("itemOperationsActions"); |
|
| 28 | + while (WBXMLDecoder::InWhile("itemOperationsActions")) { |
|
| 29 | + // TODO check if multiple item operations are possible in one request |
|
| 30 | + $el = self::$decoder->getElement(); |
|
| 31 | + |
|
| 32 | + if ($el[EN_TYPE] != EN_TYPE_STARTTAG) { |
|
| 33 | + return false; |
|
| 34 | + } |
|
| 35 | + |
|
| 36 | + $fetch = $efc = $move = false; |
|
| 37 | + $operation = []; |
|
| 38 | + if ($el[EN_TAG] == SYNC_ITEMOPERATIONS_FETCH) { |
|
| 39 | + $fetch = true; |
|
| 40 | + $operation['operation'] = SYNC_ITEMOPERATIONS_FETCH; |
|
| 41 | + self::$topCollector->AnnounceInformation("Fetch", true); |
|
| 42 | + } |
|
| 43 | + elseif ($el[EN_TAG] == SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS) { |
|
| 44 | + $efc = true; |
|
| 45 | + $operation['operation'] = SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS; |
|
| 46 | + self::$topCollector->AnnounceInformation("Empty Folder", true); |
|
| 47 | + } |
|
| 48 | + elseif ($el[EN_TAG] == SYNC_ITEMOPERATIONS_MOVE) { |
|
| 49 | + $move = true; |
|
| 50 | + $operation['operation'] = SYNC_ITEMOPERATIONS_MOVE; |
|
| 51 | + self::$topCollector->AnnounceInformation("Move", true); |
|
| 52 | + } |
|
| 53 | + |
|
| 54 | + if (!$fetch && !$efc && !$move) { |
|
| 55 | + SLog::Write(LOGLEVEL_DEBUG, "Unknown item operation:" . print_r($el, 1)); |
|
| 56 | + self::$topCollector->AnnounceInformation("Unknown operation", true); |
|
| 57 | + |
|
| 58 | + return false; |
|
| 59 | + } |
|
| 60 | + |
|
| 61 | + // process operation |
|
| 62 | + WBXMLDecoder::ResetInWhile("itemOperationsOperation"); |
|
| 63 | + while (WBXMLDecoder::InWhile("itemOperationsOperation")) { |
|
| 64 | + if ($fetch) { |
|
| 65 | + // Save all OPTIONS into a ContentParameters object |
|
| 66 | + $operation["cpo"] = new ContentParameters(); |
|
| 67 | + |
|
| 68 | + if (self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_STORE)) { |
|
| 69 | + $operation['store'] = self::$decoder->getElementContent(); |
|
| 70 | + if (!self::$decoder->getElementEndTag()) { |
|
| 71 | + return false; |
|
| 72 | + }// SYNC_ITEMOPERATIONS_STORE |
|
| 73 | + } |
|
| 74 | + |
|
| 75 | + if (self::$decoder->getElementStartTag(SYNC_SEARCH_LONGID)) { |
|
| 76 | + $operation['longid'] = self::$decoder->getElementContent(); |
|
| 77 | + if (!self::$decoder->getElementEndTag()) { |
|
| 78 | + return false; |
|
| 79 | + }// SYNC_SEARCH_LONGID |
|
| 80 | + } |
|
| 81 | + |
|
| 82 | + if (self::$decoder->getElementStartTag(SYNC_FOLDERID)) { |
|
| 83 | + $operation['folderid'] = self::$decoder->getElementContent(); |
|
| 84 | + if (!self::$decoder->getElementEndTag()) { |
|
| 85 | + return false; |
|
| 86 | + }// SYNC_FOLDERID |
|
| 87 | + } |
|
| 88 | + |
|
| 89 | + if (self::$decoder->getElementStartTag(SYNC_SERVERENTRYID)) { |
|
| 90 | + $operation['serverid'] = self::$decoder->getElementContent(); |
|
| 91 | + if (!self::$decoder->getElementEndTag()) { |
|
| 92 | + return false; |
|
| 93 | + }// SYNC_SERVERENTRYID |
|
| 94 | + } |
|
| 95 | + |
|
| 96 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_FILEREFERENCE)) { |
|
| 97 | + $operation['filereference'] = self::$decoder->getElementContent(); |
|
| 98 | + if (!self::$decoder->getElementEndTag()) { |
|
| 99 | + return false; |
|
| 100 | + }// SYNC_AIRSYNCBASE_FILEREFERENCE |
|
| 101 | + } |
|
| 102 | + |
|
| 103 | + if (($el = self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_OPTIONS)) && ($el[EN_FLAGS] & EN_FLAGS_CONTENT)) { |
|
| 104 | + // TODO other options |
|
| 105 | + // schema |
|
| 106 | + // range |
|
| 107 | + // username |
|
| 108 | + // password |
|
| 109 | + // bodypartpreference |
|
| 110 | + // rm:RightsManagementSupport |
|
| 111 | + |
|
| 112 | + WBXMLDecoder::ResetInWhile("itemOperationsOptions"); |
|
| 113 | + while (WBXMLDecoder::InWhile("itemOperationsOptions")) { |
|
| 114 | + while (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_BODYPREFERENCE)) { |
|
| 115 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TYPE)) { |
|
| 116 | + $bptype = self::$decoder->getElementContent(); |
|
| 117 | + $operation["cpo"]->BodyPreference($bptype); |
|
| 118 | + if (!self::$decoder->getElementEndTag()) { |
|
| 119 | + return false; |
|
| 120 | + } |
|
| 121 | + } |
|
| 122 | + |
|
| 123 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TRUNCATIONSIZE)) { |
|
| 124 | + $operation["cpo"]->BodyPreference($bptype)->SetTruncationSize(self::$decoder->getElementContent()); |
|
| 125 | + if (!self::$decoder->getElementEndTag()) { |
|
| 126 | + return false; |
|
| 127 | + } |
|
| 128 | + } |
|
| 129 | + |
|
| 130 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_ALLORNONE)) { |
|
| 131 | + $operation["cpo"]->BodyPreference($bptype)->SetAllOrNone(self::$decoder->getElementContent()); |
|
| 132 | + if (!self::$decoder->getElementEndTag()) { |
|
| 133 | + return false; |
|
| 134 | + } |
|
| 135 | + } |
|
| 136 | + |
|
| 137 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_PREVIEW)) { |
|
| 138 | + $operation["cpo"]->BodyPreference($bptype)->SetPreview(self::$decoder->getElementContent()); |
|
| 139 | + if (!self::$decoder->getElementEndTag()) { |
|
| 140 | + return false; |
|
| 141 | + } |
|
| 142 | + } |
|
| 143 | + |
|
| 144 | + if (!self::$decoder->getElementEndTag()) { |
|
| 145 | + return false; |
|
| 146 | + }// SYNC_AIRSYNCBASE_BODYPREFERENCE |
|
| 147 | + } |
|
| 148 | + |
|
| 149 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_BODYPARTPREFERENCE)) { |
|
| 150 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TYPE)) { |
|
| 151 | + $bpptype = self::$decoder->getElementContent(); |
|
| 152 | + $operation["cpo"]->BodyPartPreference($bpptype); |
|
| 153 | + if (!self::$decoder->getElementEndTag()) { |
|
| 154 | + return false; |
|
| 155 | + } |
|
| 156 | + } |
|
| 157 | + |
|
| 158 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TRUNCATIONSIZE)) { |
|
| 159 | + $operation["cpo"]->BodyPartPreference($bpptype)->SetTruncationSize(self::$decoder->getElementContent()); |
|
| 160 | + if (!self::$decoder->getElementEndTag()) { |
|
| 161 | + return false; |
|
| 162 | + } |
|
| 163 | + } |
|
| 164 | + |
|
| 165 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_ALLORNONE)) { |
|
| 166 | + $operation["cpo"]->BodyPartPreference($bpptype)->SetAllOrNone(self::$decoder->getElementContent()); |
|
| 167 | + if (!self::$decoder->getElementEndTag()) { |
|
| 168 | + return false; |
|
| 169 | + } |
|
| 170 | + } |
|
| 171 | + |
|
| 172 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_PREVIEW)) { |
|
| 173 | + $operation["cpo"]->BodyPartPreference($bpptype)->SetPreview(self::$decoder->getElementContent()); |
|
| 174 | + if (!self::$decoder->getElementEndTag()) { |
|
| 175 | + return false; |
|
| 176 | + } |
|
| 177 | + } |
|
| 178 | + |
|
| 179 | + if (!self::$decoder->getElementEndTag()) { |
|
| 180 | + return false; |
|
| 181 | + } |
|
| 182 | + } |
|
| 183 | + |
|
| 184 | + if (self::$decoder->getElementStartTag(SYNC_MIMESUPPORT)) { |
|
| 185 | + $operation["cpo"]->SetMimeSupport(self::$decoder->getElementContent()); |
|
| 186 | + if (!self::$decoder->getElementEndTag()) { |
|
| 187 | + return false; |
|
| 188 | + } |
|
| 189 | + } |
|
| 190 | + |
|
| 191 | + if (self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_RANGE)) { |
|
| 192 | + $operation["range"] = self::$decoder->getElementContent(); |
|
| 193 | + if (!self::$decoder->getElementEndTag()) { |
|
| 194 | + return false; |
|
| 195 | + } |
|
| 196 | + } |
|
| 197 | + |
|
| 198 | + if (self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_SCHEMA)) { |
|
| 199 | + // read schema tags |
|
| 200 | + WBXMLDecoder::ResetInWhile("itemOperationsSchema"); |
|
| 201 | + while (WBXMLDecoder::InWhile("itemOperationsSchema")) { |
|
| 202 | + // TODO save elements |
|
| 203 | + $el = self::$decoder->getElement(); |
|
| 204 | + $e = self::$decoder->peek(); |
|
| 205 | + if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { |
|
| 206 | + self::$decoder->getElementEndTag(); |
|
| 207 | + |
|
| 208 | + break; |
|
| 209 | + } |
|
| 210 | + } |
|
| 211 | + } |
|
| 212 | + |
|
| 213 | + if (self::$decoder->getElementStartTag(SYNC_RIGHTSMANAGEMENT_SUPPORT)) { |
|
| 214 | + $operation["cpo"]->SetRmSupport(self::$decoder->getElementContent()); |
|
| 215 | + if (!self::$decoder->getElementEndTag()) { |
|
| 216 | + return false; |
|
| 217 | + } |
|
| 218 | + } |
|
| 219 | + |
|
| 220 | + // break if it reached the endtag |
|
| 221 | + $e = self::$decoder->peek(); |
|
| 222 | + if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { |
|
| 223 | + self::$decoder->getElementEndTag(); |
|
| 224 | + |
|
| 225 | + break; |
|
| 226 | + } |
|
| 227 | + } |
|
| 228 | + } |
|
| 229 | + |
|
| 230 | + if (self::$decoder->getElementStartTag(SYNC_RIGHTSMANAGEMENT_REMOVERIGHTSMGNTPROTECTION)) { |
|
| 231 | + $operation["cpo"]->SetRemoveRmProtection(true); |
|
| 232 | + if (($rrmp = self::$decoder->getElementContent()) !== false) { |
|
| 233 | + $operation["cpo"]->SetRemoveRmProtection($rrmp); |
|
| 234 | + if (!self::$decoder->getElementEndTag()) { |
|
| 235 | + return false; |
|
| 236 | + } |
|
| 237 | + } |
|
| 238 | + } |
|
| 239 | + } // end if fetch |
|
| 240 | + |
|
| 241 | + if ($efc) { |
|
| 242 | + if (self::$decoder->getElementStartTag(SYNC_FOLDERID)) { |
|
| 243 | + $operation['folderid'] = self::$decoder->getElementContent(); |
|
| 244 | + if (!self::$decoder->getElementEndTag()) { |
|
| 245 | + return false; |
|
| 246 | + }// SYNC_FOLDERID |
|
| 247 | + } |
|
| 248 | + if (self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_OPTIONS)) { |
|
| 249 | + if (self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_DELETESUBFOLDERS)) { |
|
| 250 | + $operation['deletesubfolders'] = true; |
|
| 251 | + if (($dsf = self::$decoder->getElementContent()) !== false) { |
|
| 252 | + $operation['deletesubfolders'] = (bool) $dsf; |
|
| 253 | + if (!self::$decoder->getElementEndTag()) { |
|
| 254 | + return false; |
|
| 255 | + } |
|
| 256 | + } |
|
| 257 | + } |
|
| 258 | + self::$decoder->getElementEndTag(); |
|
| 259 | + } |
|
| 260 | + } |
|
| 261 | + |
|
| 262 | + // TODO move |
|
| 263 | + |
|
| 264 | + // break if it reached the endtag SYNC_ITEMOPERATIONS_FETCH or SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS or SYNC_ITEMOPERATIONS_MOVE |
|
| 265 | + $e = self::$decoder->peek(); |
|
| 266 | + if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { |
|
| 267 | + self::$decoder->getElementEndTag(); |
|
| 268 | + |
|
| 269 | + break; |
|
| 270 | + } |
|
| 271 | + } // end while operation |
|
| 272 | + |
|
| 273 | + // rewrite folderid into backendfolderid to be used on backend operations below |
|
| 274 | + if (isset($operation['folderid'])) { |
|
| 275 | + $operation['backendfolderid'] = self::$deviceManager->GetBackendIdForFolderId($operation['folderid']); |
|
| 276 | + } |
|
| 277 | + |
|
| 278 | + $itemoperations[] = $operation; |
|
| 279 | + // break if it reached the endtag |
|
| 280 | + $e = self::$decoder->peek(); |
|
| 281 | + if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { |
|
| 282 | + self::$decoder->getElementEndTag(); // SYNC_ITEMOPERATIONS_ITEMOPERATIONS |
|
| 283 | + |
|
| 284 | + break; |
|
| 285 | + } |
|
| 286 | + } // end operations loop |
|
| 287 | + |
|
| 288 | + $status = SYNC_ITEMOPERATIONSSTATUS_SUCCESS; |
|
| 289 | + |
|
| 290 | + self::$encoder->startWBXML(); |
|
| 291 | + |
|
| 292 | + self::$encoder->startTag(SYNC_ITEMOPERATIONS_ITEMOPERATIONS); |
|
| 293 | + |
|
| 294 | + self::$encoder->startTag(SYNC_ITEMOPERATIONS_STATUS); |
|
| 295 | + self::$encoder->content($status); |
|
| 296 | + self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_STATUS |
|
| 297 | + |
|
| 298 | + // Stop here if something went wrong |
|
| 299 | + if ($status != SYNC_ITEMOPERATIONSSTATUS_SUCCESS) { |
|
| 300 | + self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_ITEMOPERATIONS |
|
| 301 | + |
|
| 302 | + return true; |
|
| 303 | + } |
|
| 304 | + |
|
| 305 | + self::$encoder->startTag(SYNC_ITEMOPERATIONS_RESPONSE); |
|
| 306 | + |
|
| 307 | + foreach ($itemoperations as $operation) { |
|
| 308 | + // fetch response |
|
| 309 | + if ($operation['operation'] == SYNC_ITEMOPERATIONS_FETCH) { |
|
| 310 | + $status = SYNC_ITEMOPERATIONSSTATUS_SUCCESS; |
|
| 311 | + |
|
| 312 | + // retrieve the data |
|
| 313 | + // Fetch throws Sync status codes, - GetAttachmentData ItemOperations codes |
|
| 314 | + if (isset($operation['filereference'])) { |
|
| 315 | + try { |
|
| 316 | + self::$topCollector->AnnounceInformation("Get attachment data from backend with file reference"); |
|
| 317 | + $data = self::$backend->GetAttachmentData($operation['filereference']); |
|
| 318 | + } |
|
| 319 | + catch (StatusException $stex) { |
|
| 320 | + $status = $stex->getCode(); |
|
| 321 | + } |
|
| 322 | + } |
|
| 323 | + else { |
|
| 324 | + try { |
|
| 325 | + if (isset($operation['folderid'], $operation['serverid'])) { |
|
| 326 | + self::$topCollector->AnnounceInformation("Fetching data from backend with item and folder id"); |
|
| 327 | + $data = self::$backend->Fetch($operation['backendfolderid'], $operation['serverid'], $operation["cpo"]); |
|
| 328 | + } |
|
| 329 | + elseif (isset($operation['longid'])) { |
|
| 330 | + self::$topCollector->AnnounceInformation("Fetching data from backend with long id"); |
|
| 331 | + $tmp = explode(":", $operation['longid']); |
|
| 332 | + $data = self::$backend->Fetch(self::$deviceManager->GetBackendIdForFolderId($tmp[0]), $tmp[1], $operation["cpo"]); |
|
| 333 | + } |
|
| 334 | + } |
|
| 335 | + catch (StatusException $stex) { |
|
| 336 | + // the only option to return is that we could not retrieve it |
|
| 337 | + $status = SYNC_ITEMOPERATIONSSTATUS_CONVERSIONFAILED; |
|
| 338 | + } |
|
| 339 | + } |
|
| 340 | + |
|
| 341 | + self::$encoder->startTag(SYNC_ITEMOPERATIONS_FETCH); |
|
| 342 | + |
|
| 343 | + self::$encoder->startTag(SYNC_ITEMOPERATIONS_STATUS); |
|
| 344 | + self::$encoder->content($status); |
|
| 345 | + self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_STATUS |
|
| 346 | + |
|
| 347 | + if (isset($operation['folderid'], $operation['serverid'])) { |
|
| 348 | + self::$encoder->startTag(SYNC_FOLDERID); |
|
| 349 | + self::$encoder->content($operation['folderid']); |
|
| 350 | + self::$encoder->endTag(); // end SYNC_FOLDERID |
|
| 351 | + |
|
| 352 | + self::$encoder->startTag(SYNC_SERVERENTRYID); |
|
| 353 | + self::$encoder->content($operation['serverid']); |
|
| 354 | + self::$encoder->endTag(); // end SYNC_SERVERENTRYID |
|
| 355 | + |
|
| 356 | + self::$encoder->startTag(SYNC_FOLDERTYPE); |
|
| 357 | + self::$encoder->content("Email"); |
|
| 358 | + self::$encoder->endTag(); |
|
| 359 | + } |
|
| 360 | + |
|
| 361 | + if (isset($operation['longid'])) { |
|
| 362 | + self::$encoder->startTag(SYNC_SEARCH_LONGID); |
|
| 363 | + self::$encoder->content($operation['longid']); |
|
| 364 | + self::$encoder->endTag(); // end SYNC_FOLDERID |
|
| 365 | + |
|
| 366 | + self::$encoder->startTag(SYNC_FOLDERTYPE); |
|
| 367 | + self::$encoder->content("Email"); |
|
| 368 | + self::$encoder->endTag(); |
|
| 369 | + } |
|
| 370 | + |
|
| 371 | + if (isset($operation['filereference'])) { |
|
| 372 | + self::$encoder->startTag(SYNC_AIRSYNCBASE_FILEREFERENCE); |
|
| 373 | + self::$encoder->content($operation['filereference']); |
|
| 374 | + self::$encoder->endTag(); // end SYNC_AIRSYNCBASE_FILEREFERENCE |
|
| 375 | + } |
|
| 376 | + |
|
| 377 | + if (isset($data)) { |
|
| 378 | + self::$topCollector->AnnounceInformation("Streaming data"); |
|
| 379 | + |
|
| 380 | + self::$encoder->startTag(SYNC_ITEMOPERATIONS_PROPERTIES); |
|
| 381 | + if (isset($operation['range'])) { |
|
| 382 | + self::$encoder->startTag(SYNC_ITEMOPERATIONS_RANGE); |
|
| 383 | + self::$encoder->content($operation['range']); |
|
| 384 | + self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_RANGE |
|
| 385 | + } |
|
| 386 | + $data->Encode(self::$encoder); |
|
| 387 | + self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_PROPERTIES |
|
| 388 | + } |
|
| 389 | + |
|
| 390 | + self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_FETCH |
|
| 391 | + } |
|
| 392 | + // empty folder contents operation |
|
| 393 | + elseif ($operation['operation'] == SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS) { |
|
| 394 | + try { |
|
| 395 | + self::$topCollector->AnnounceInformation("Emptying folder"); |
|
| 396 | + |
|
| 397 | + // send request to backend |
|
| 398 | + self::$backend->EmptyFolder($operation['backendfolderid'], $operation['deletesubfolders']); |
|
| 399 | + } |
|
| 400 | + catch (StatusException $stex) { |
|
| 401 | + $status = $stex->getCode(); |
|
| 402 | + } |
|
| 403 | + |
|
| 404 | + self::$encoder->startTag(SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS); |
|
| 405 | + |
|
| 406 | + self::$encoder->startTag(SYNC_ITEMOPERATIONS_STATUS); |
|
| 407 | + self::$encoder->content($status); |
|
| 408 | + self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_STATUS |
|
| 409 | + |
|
| 410 | + if (isset($operation['folderid'])) { |
|
| 411 | + self::$encoder->startTag(SYNC_FOLDERID); |
|
| 412 | + self::$encoder->content($operation['folderid']); |
|
| 413 | + self::$encoder->endTag(); // end SYNC_FOLDERID |
|
| 414 | + } |
|
| 415 | + self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS |
|
| 416 | + } |
|
| 417 | + // TODO implement ItemOperations Move |
|
| 418 | + // move operation |
|
| 419 | + else { |
|
| 420 | + self::$topCollector->AnnounceInformation("not implemented", true); |
|
| 421 | + |
|
| 422 | + // reply with "can't do" |
|
| 423 | + self::$encoder->startTag(SYNC_ITEMOPERATIONS_MOVE); |
|
| 424 | + self::$encoder->startTag(SYNC_ITEMOPERATIONS_STATUS); |
|
| 425 | + self::$encoder->content(SYNC_ITEMOPERATIONSSTATUS_SERVERERROR); |
|
| 426 | + self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_STATUS |
|
| 427 | + self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_MOVE |
|
| 428 | + } |
|
| 429 | + } |
|
| 430 | + self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_RESPONSE |
|
| 431 | + self::$encoder->endTag(); // SYNC_ITEMOPERATIONS_ITEMOPERATIONS |
|
| 432 | + |
|
| 433 | + return true; |
|
| 434 | + } |
|
| 435 | 435 | } |
@@ -52,7 +52,7 @@ discard block |
||
| 52 | 52 | } |
| 53 | 53 | |
| 54 | 54 | if (!$fetch && !$efc && !$move) { |
| 55 | - SLog::Write(LOGLEVEL_DEBUG, "Unknown item operation:" . print_r($el, 1)); |
|
| 55 | + SLog::Write(LOGLEVEL_DEBUG, "Unknown item operation:".print_r($el, 1)); |
|
| 56 | 56 | self::$topCollector->AnnounceInformation("Unknown operation", true); |
| 57 | 57 | |
| 58 | 58 | return false; |
@@ -249,7 +249,7 @@ discard block |
||
| 249 | 249 | if (self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_DELETESUBFOLDERS)) { |
| 250 | 250 | $operation['deletesubfolders'] = true; |
| 251 | 251 | if (($dsf = self::$decoder->getElementContent()) !== false) { |
| 252 | - $operation['deletesubfolders'] = (bool) $dsf; |
|
| 252 | + $operation['deletesubfolders'] = (bool)$dsf; |
|
| 253 | 253 | if (!self::$decoder->getElementEndTag()) { |
| 254 | 254 | return false; |
| 255 | 255 | } |
@@ -39,13 +39,11 @@ discard block |
||
| 39 | 39 | $fetch = true; |
| 40 | 40 | $operation['operation'] = SYNC_ITEMOPERATIONS_FETCH; |
| 41 | 41 | self::$topCollector->AnnounceInformation("Fetch", true); |
| 42 | - } |
|
| 43 | - elseif ($el[EN_TAG] == SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS) { |
|
| 42 | + } elseif ($el[EN_TAG] == SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS) { |
|
| 44 | 43 | $efc = true; |
| 45 | 44 | $operation['operation'] = SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS; |
| 46 | 45 | self::$topCollector->AnnounceInformation("Empty Folder", true); |
| 47 | - } |
|
| 48 | - elseif ($el[EN_TAG] == SYNC_ITEMOPERATIONS_MOVE) { |
|
| 46 | + } elseif ($el[EN_TAG] == SYNC_ITEMOPERATIONS_MOVE) { |
|
| 49 | 47 | $move = true; |
| 50 | 48 | $operation['operation'] = SYNC_ITEMOPERATIONS_MOVE; |
| 51 | 49 | self::$topCollector->AnnounceInformation("Move", true); |
@@ -315,24 +313,20 @@ discard block |
||
| 315 | 313 | try { |
| 316 | 314 | self::$topCollector->AnnounceInformation("Get attachment data from backend with file reference"); |
| 317 | 315 | $data = self::$backend->GetAttachmentData($operation['filereference']); |
| 318 | - } |
|
| 319 | - catch (StatusException $stex) { |
|
| 316 | + } catch (StatusException $stex) { |
|
| 320 | 317 | $status = $stex->getCode(); |
| 321 | 318 | } |
| 322 | - } |
|
| 323 | - else { |
|
| 319 | + } else { |
|
| 324 | 320 | try { |
| 325 | 321 | if (isset($operation['folderid'], $operation['serverid'])) { |
| 326 | 322 | self::$topCollector->AnnounceInformation("Fetching data from backend with item and folder id"); |
| 327 | 323 | $data = self::$backend->Fetch($operation['backendfolderid'], $operation['serverid'], $operation["cpo"]); |
| 328 | - } |
|
| 329 | - elseif (isset($operation['longid'])) { |
|
| 324 | + } elseif (isset($operation['longid'])) { |
|
| 330 | 325 | self::$topCollector->AnnounceInformation("Fetching data from backend with long id"); |
| 331 | 326 | $tmp = explode(":", $operation['longid']); |
| 332 | 327 | $data = self::$backend->Fetch(self::$deviceManager->GetBackendIdForFolderId($tmp[0]), $tmp[1], $operation["cpo"]); |
| 333 | 328 | } |
| 334 | - } |
|
| 335 | - catch (StatusException $stex) { |
|
| 329 | + } catch (StatusException $stex) { |
|
| 336 | 330 | // the only option to return is that we could not retrieve it |
| 337 | 331 | $status = SYNC_ITEMOPERATIONSSTATUS_CONVERSIONFAILED; |
| 338 | 332 | } |
@@ -396,8 +390,7 @@ discard block |
||
| 396 | 390 | |
| 397 | 391 | // send request to backend |
| 398 | 392 | self::$backend->EmptyFolder($operation['backendfolderid'], $operation['deletesubfolders']); |
| 399 | - } |
|
| 400 | - catch (StatusException $stex) { |
|
| 393 | + } catch (StatusException $stex) { |
|
| 401 | 394 | $status = $stex->getCode(); |
| 402 | 395 | } |
| 403 | 396 | |
@@ -8,43 +8,43 @@ |
||
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | 10 | class Notify extends RequestProcessor { |
| 11 | - /** |
|
| 12 | - * Handles the Notify command. |
|
| 13 | - * |
|
| 14 | - * @param int $commandCode |
|
| 15 | - * |
|
| 16 | - * @return bool |
|
| 17 | - */ |
|
| 18 | - public function Handle($commandCode) { |
|
| 19 | - if (!self::$decoder->getElementStartTag(SYNC_AIRNOTIFY_NOTIFY)) { |
|
| 20 | - return false; |
|
| 21 | - } |
|
| 11 | + /** |
|
| 12 | + * Handles the Notify command. |
|
| 13 | + * |
|
| 14 | + * @param int $commandCode |
|
| 15 | + * |
|
| 16 | + * @return bool |
|
| 17 | + */ |
|
| 18 | + public function Handle($commandCode) { |
|
| 19 | + if (!self::$decoder->getElementStartTag(SYNC_AIRNOTIFY_NOTIFY)) { |
|
| 20 | + return false; |
|
| 21 | + } |
|
| 22 | 22 | |
| 23 | - if (!self::$decoder->getElementStartTag(SYNC_AIRNOTIFY_DEVICEINFO)) { |
|
| 24 | - return false; |
|
| 25 | - } |
|
| 23 | + if (!self::$decoder->getElementStartTag(SYNC_AIRNOTIFY_DEVICEINFO)) { |
|
| 24 | + return false; |
|
| 25 | + } |
|
| 26 | 26 | |
| 27 | - if (!self::$decoder->getElementEndTag()) { |
|
| 28 | - return false; |
|
| 29 | - } |
|
| 27 | + if (!self::$decoder->getElementEndTag()) { |
|
| 28 | + return false; |
|
| 29 | + } |
|
| 30 | 30 | |
| 31 | - if (!self::$decoder->getElementEndTag()) { |
|
| 32 | - return false; |
|
| 33 | - } |
|
| 31 | + if (!self::$decoder->getElementEndTag()) { |
|
| 32 | + return false; |
|
| 33 | + } |
|
| 34 | 34 | |
| 35 | - self::$encoder->StartWBXML(); |
|
| 35 | + self::$encoder->StartWBXML(); |
|
| 36 | 36 | |
| 37 | - self::$encoder->startTag(SYNC_AIRNOTIFY_NOTIFY); |
|
| 37 | + self::$encoder->startTag(SYNC_AIRNOTIFY_NOTIFY); |
|
| 38 | 38 | |
| 39 | - self::$encoder->startTag(SYNC_AIRNOTIFY_STATUS); |
|
| 40 | - self::$encoder->content(1); |
|
| 41 | - self::$encoder->endTag(); |
|
| 39 | + self::$encoder->startTag(SYNC_AIRNOTIFY_STATUS); |
|
| 40 | + self::$encoder->content(1); |
|
| 41 | + self::$encoder->endTag(); |
|
| 42 | 42 | |
| 43 | - self::$encoder->startTag(SYNC_AIRNOTIFY_VALIDCARRIERPROFILES); |
|
| 44 | - self::$encoder->endTag(); |
|
| 43 | + self::$encoder->startTag(SYNC_AIRNOTIFY_VALIDCARRIERPROFILES); |
|
| 44 | + self::$encoder->endTag(); |
|
| 45 | 45 | |
| 46 | - self::$encoder->endTag(); |
|
| 46 | + self::$encoder->endTag(); |
|
| 47 | 47 | |
| 48 | - return true; |
|
| 49 | - } |
|
| 48 | + return true; |
|
| 49 | + } |
|
| 50 | 50 | } |
@@ -8,245 +8,245 @@ |
||
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | 10 | class Provisioning extends RequestProcessor { |
| 11 | - /** |
|
| 12 | - * Handles the Provisioning command. |
|
| 13 | - * |
|
| 14 | - * @param int $commandCode |
|
| 15 | - * |
|
| 16 | - * @return bool |
|
| 17 | - */ |
|
| 18 | - public function Handle($commandCode) { |
|
| 19 | - $status = SYNC_PROVISION_STATUS_SUCCESS; |
|
| 20 | - $policystatus = SYNC_PROVISION_POLICYSTATUS_SUCCESS; |
|
| 21 | - |
|
| 22 | - $rwstatus = GSync::GetProvisioningManager()->GetProvisioningWipeStatus(); |
|
| 23 | - $rwstatusWiped = false; |
|
| 24 | - $deviceInfoSet = false; |
|
| 25 | - $wipeRequest = !($rwstatus < SYNC_PROVISION_RWSTATUS_PENDING); |
|
| 26 | - |
|
| 27 | - // if this is a regular provisioning require that an authenticated remote user |
|
| 28 | - if (!$wipeRequest) { |
|
| 29 | - SLog::Write(LOGLEVEL_DEBUG, "RequestProcessor::HandleProvision(): Forcing delayed Authentication"); |
|
| 30 | - self::Authenticate(); |
|
| 31 | - } |
|
| 32 | - |
|
| 33 | - $phase2 = true; |
|
| 34 | - |
|
| 35 | - if (!self::$decoder->getElementStartTag(SYNC_PROVISION_PROVISION)) { |
|
| 36 | - return false; |
|
| 37 | - } |
|
| 38 | - |
|
| 39 | - // Loop through Provision request tags. Possible are: |
|
| 40 | - // - Remote Wipe |
|
| 41 | - // - DeviceInformation |
|
| 42 | - // - Policies |
|
| 43 | - // Each of them should only be once per request. |
|
| 44 | - WBXMLDecoder::ResetInWhile("provisioningMain"); |
|
| 45 | - while (WBXMLDecoder::InWhile("provisioningMain")) { |
|
| 46 | - $requestName = ""; |
|
| 47 | - if (self::$decoder->getElementStartTag(SYNC_PROVISION_REMOTEWIPE)) { |
|
| 48 | - $requestName = SYNC_PROVISION_REMOTEWIPE; |
|
| 49 | - } |
|
| 50 | - if (self::$decoder->getElementStartTag(SYNC_PROVISION_POLICIES)) { |
|
| 51 | - $requestName = SYNC_PROVISION_POLICIES; |
|
| 52 | - } |
|
| 53 | - if (self::$decoder->getElementStartTag(SYNC_SETTINGS_DEVICEINFORMATION)) { |
|
| 54 | - $requestName = SYNC_SETTINGS_DEVICEINFORMATION; |
|
| 55 | - } |
|
| 56 | - |
|
| 57 | - if (!$requestName) { |
|
| 58 | - break; |
|
| 59 | - } |
|
| 60 | - |
|
| 61 | - // set is available for OOF, device password and device information |
|
| 62 | - switch ($requestName) { |
|
| 63 | - case SYNC_PROVISION_REMOTEWIPE: |
|
| 64 | - if (!self::$decoder->getElementStartTag(SYNC_PROVISION_STATUS)) { |
|
| 65 | - return false; |
|
| 66 | - } |
|
| 67 | - |
|
| 68 | - $instatus = self::$decoder->getElementContent(); |
|
| 69 | - |
|
| 70 | - if (!self::$decoder->getElementEndTag()) { |
|
| 71 | - return false; |
|
| 72 | - } |
|
| 73 | - |
|
| 74 | - if (!self::$decoder->getElementEndTag()) { |
|
| 75 | - return false; |
|
| 76 | - } |
|
| 77 | - |
|
| 78 | - $phase2 = false; |
|
| 79 | - $rwstatusWiped = true; |
|
| 80 | - // TODO check - do it after while(1) finished? |
|
| 81 | - break; |
|
| 82 | - |
|
| 83 | - case SYNC_PROVISION_POLICIES: |
|
| 84 | - if (!self::$decoder->getElementStartTag(SYNC_PROVISION_POLICY)) { |
|
| 85 | - return false; |
|
| 86 | - } |
|
| 87 | - |
|
| 88 | - if (!self::$decoder->getElementStartTag(SYNC_PROVISION_POLICYTYPE)) { |
|
| 89 | - return false; |
|
| 90 | - } |
|
| 91 | - |
|
| 92 | - $policytype = self::$decoder->getElementContent(); |
|
| 93 | - if ($policytype != 'MS-WAP-Provisioning-XML' && $policytype != 'MS-EAS-Provisioning-WBXML') { |
|
| 94 | - $status = SYNC_PROVISION_STATUS_SERVERERROR; |
|
| 95 | - } |
|
| 96 | - if (!self::$decoder->getElementEndTag()) { // policytype |
|
| 97 | - return false; |
|
| 98 | - } |
|
| 99 | - |
|
| 100 | - if (self::$decoder->getElementStartTag(SYNC_PROVISION_POLICYKEY)) { |
|
| 101 | - $devpolicykey = self::$decoder->getElementContent(); |
|
| 102 | - |
|
| 103 | - if (!self::$decoder->getElementEndTag()) { |
|
| 104 | - return false; |
|
| 105 | - } |
|
| 106 | - |
|
| 107 | - if (!self::$decoder->getElementStartTag(SYNC_PROVISION_STATUS)) { |
|
| 108 | - return false; |
|
| 109 | - } |
|
| 110 | - |
|
| 111 | - $instatus = self::$decoder->getElementContent(); |
|
| 112 | - |
|
| 113 | - if (!self::$decoder->getElementEndTag()) { |
|
| 114 | - return false; |
|
| 115 | - } |
|
| 116 | - |
|
| 117 | - $phase2 = false; |
|
| 118 | - } |
|
| 119 | - |
|
| 120 | - if (!self::$decoder->getElementEndTag()) { // policy |
|
| 121 | - return false; |
|
| 122 | - } |
|
| 123 | - |
|
| 124 | - if (!self::$decoder->getElementEndTag()) { // policies |
|
| 125 | - return false; |
|
| 126 | - } |
|
| 127 | - break; |
|
| 128 | - |
|
| 129 | - case SYNC_SETTINGS_DEVICEINFORMATION: |
|
| 130 | - // AS14.1 and later clients pass Device Information on the initial Provision request |
|
| 131 | - if (!self::$decoder->getElementStartTag(SYNC_SETTINGS_SET)) { |
|
| 132 | - return false; |
|
| 133 | - } |
|
| 134 | - $deviceInfoSet = true; |
|
| 135 | - $deviceinformation = new SyncDeviceInformation(); |
|
| 136 | - $deviceinformation->Decode(self::$decoder); |
|
| 137 | - $deviceinformation->Status = SYNC_SETTINGSSTATUS_SUCCESS; |
|
| 138 | - if (!$wipeRequest) { |
|
| 139 | - // for this operation the device manager is available |
|
| 140 | - GSync::GetDeviceManager()->SaveDeviceInformation($deviceinformation); |
|
| 141 | - } |
|
| 142 | - else { |
|
| 143 | - SLog::Write(LOGLEVEL_DEBUG, "Ignoring incoming device information as WIPE is due."); |
|
| 144 | - } |
|
| 145 | - if (!self::$decoder->getElementEndTag()) { // SYNC_SETTINGS_SET |
|
| 146 | - return false; |
|
| 147 | - } |
|
| 148 | - if (!self::$decoder->getElementEndTag()) { // SYNC_SETTINGS_DEVICEINFORMATION |
|
| 149 | - return false; |
|
| 150 | - } |
|
| 151 | - break; |
|
| 152 | - |
|
| 153 | - default: |
|
| 154 | - // TODO: a special status code needed? |
|
| 155 | - SLog::Write(LOGLEVEL_WARN, sprintf("This property ('%s') is not allowed to be used in a provision request", $requestName)); |
|
| 156 | - } |
|
| 157 | - } |
|
| 158 | - |
|
| 159 | - if (!self::$decoder->getElementEndTag()) { // provision |
|
| 160 | - return false; |
|
| 161 | - } |
|
| 162 | - |
|
| 163 | - if (PROVISIONING !== true) { |
|
| 164 | - SLog::Write(LOGLEVEL_INFO, "No policies deployed to device"); |
|
| 165 | - $policystatus = SYNC_PROVISION_POLICYSTATUS_NOPOLICY; |
|
| 166 | - } |
|
| 167 | - |
|
| 168 | - self::$encoder->StartWBXML(); |
|
| 169 | - |
|
| 170 | - // just create a temporary key (i.e. iPhone OS4 Beta does not like policykey 0 in response) |
|
| 171 | - $policykey = GSync::GetProvisioningManager()->GenerateProvisioningPolicyKey(); |
|
| 172 | - |
|
| 173 | - self::$encoder->startTag(SYNC_PROVISION_PROVISION); |
|
| 174 | - |
|
| 175 | - self::$encoder->startTag(SYNC_PROVISION_STATUS); |
|
| 176 | - self::$encoder->content($status); |
|
| 177 | - self::$encoder->endTag(); |
|
| 178 | - |
|
| 179 | - if ($deviceInfoSet) { |
|
| 180 | - self::$encoder->startTag(SYNC_SETTINGS_DEVICEINFORMATION); |
|
| 181 | - self::$encoder->startTag(SYNC_SETTINGS_STATUS); |
|
| 182 | - self::$encoder->content($deviceinformation->Status); |
|
| 183 | - self::$encoder->endTag(); // SYNC_SETTINGS_STATUS |
|
| 184 | - self::$encoder->endTag(); // SYNC_SETTINGS_DEVICEINFORMATION |
|
| 185 | - } |
|
| 186 | - |
|
| 187 | - self::$encoder->startTag(SYNC_PROVISION_POLICIES); |
|
| 188 | - self::$encoder->startTag(SYNC_PROVISION_POLICY); |
|
| 189 | - |
|
| 190 | - if (isset($policytype)) { |
|
| 191 | - self::$encoder->startTag(SYNC_PROVISION_POLICYTYPE); |
|
| 192 | - self::$encoder->content($policytype); |
|
| 193 | - self::$encoder->endTag(); |
|
| 194 | - } |
|
| 195 | - |
|
| 196 | - self::$encoder->startTag(SYNC_PROVISION_STATUS); |
|
| 197 | - self::$encoder->content($policystatus); |
|
| 198 | - self::$encoder->endTag(); |
|
| 199 | - |
|
| 200 | - self::$encoder->startTag(SYNC_PROVISION_POLICYKEY); |
|
| 201 | - self::$encoder->content($policykey); |
|
| 202 | - self::$encoder->endTag(); |
|
| 203 | - |
|
| 204 | - if ($phase2 && $policystatus === SYNC_PROVISION_POLICYSTATUS_SUCCESS) { |
|
| 205 | - self::$encoder->startTag(SYNC_PROVISION_DATA); |
|
| 206 | - if ($policytype == 'MS-WAP-Provisioning-XML') { |
|
| 207 | - self::$encoder->content('<wap-provisioningdoc><characteristic type="SecurityPolicy"><parm name="4131" value="1"/><parm name="4133" value="1"/></characteristic></wap-provisioningdoc>'); |
|
| 208 | - } |
|
| 209 | - elseif ($policytype == 'MS-EAS-Provisioning-WBXML') { |
|
| 210 | - self::$encoder->startTag(SYNC_PROVISION_EASPROVISIONDOC); |
|
| 211 | - |
|
| 212 | - // get the provisioning object and log the loaded policy values |
|
| 213 | - $prov = GSync::GetProvisioningManager()->GetProvisioningObject(true); |
|
| 214 | - if (!$prov->Check()) { |
|
| 215 | - throw new FatalException("Invalid policies!"); |
|
| 216 | - } |
|
| 217 | - |
|
| 218 | - GSync::GetProvisioningManager()->SavePolicyHash($prov); |
|
| 219 | - $prov->Encode(self::$encoder); |
|
| 220 | - self::$encoder->endTag(); |
|
| 221 | - } |
|
| 222 | - else { |
|
| 223 | - SLog::Write(LOGLEVEL_WARN, "Wrong policy type"); |
|
| 224 | - self::$topCollector->AnnounceInformation("Policytype not supported", true); |
|
| 225 | - |
|
| 226 | - return false; |
|
| 227 | - } |
|
| 228 | - self::$topCollector->AnnounceInformation("Updated provisioning", true); |
|
| 229 | - |
|
| 230 | - self::$encoder->endTag(); // data |
|
| 231 | - } |
|
| 232 | - self::$encoder->endTag(); // policy |
|
| 233 | - self::$encoder->endTag(); // policies |
|
| 234 | - |
|
| 235 | - // set the new final policy key in the provisioning manager |
|
| 236 | - if (!$phase2 && !$wipeRequest) { |
|
| 237 | - GSync::GetProvisioningManager()->SetProvisioningPolicyKey($policykey); |
|
| 238 | - self::$topCollector->AnnounceInformation("Policies deployed", true); |
|
| 239 | - } |
|
| 240 | - |
|
| 241 | - // wipe data if a higher RWSTATUS is requested |
|
| 242 | - if ($rwstatus > SYNC_PROVISION_RWSTATUS_OK && $policystatus === SYNC_PROVISION_POLICYSTATUS_SUCCESS) { |
|
| 243 | - self::$encoder->startTag(SYNC_PROVISION_REMOTEWIPE, false, true); |
|
| 244 | - GSync::GetProvisioningManager()->SetProvisioningWipeStatus(($rwstatusWiped) ? SYNC_PROVISION_RWSTATUS_WIPED : SYNC_PROVISION_RWSTATUS_REQUESTED); |
|
| 245 | - self::$topCollector->AnnounceInformation(sprintf("Remote wipe %s", ($rwstatusWiped) ? "executed" : "requested"), true); |
|
| 246 | - } |
|
| 247 | - |
|
| 248 | - self::$encoder->endTag(); // provision |
|
| 249 | - |
|
| 250 | - return true; |
|
| 251 | - } |
|
| 11 | + /** |
|
| 12 | + * Handles the Provisioning command. |
|
| 13 | + * |
|
| 14 | + * @param int $commandCode |
|
| 15 | + * |
|
| 16 | + * @return bool |
|
| 17 | + */ |
|
| 18 | + public function Handle($commandCode) { |
|
| 19 | + $status = SYNC_PROVISION_STATUS_SUCCESS; |
|
| 20 | + $policystatus = SYNC_PROVISION_POLICYSTATUS_SUCCESS; |
|
| 21 | + |
|
| 22 | + $rwstatus = GSync::GetProvisioningManager()->GetProvisioningWipeStatus(); |
|
| 23 | + $rwstatusWiped = false; |
|
| 24 | + $deviceInfoSet = false; |
|
| 25 | + $wipeRequest = !($rwstatus < SYNC_PROVISION_RWSTATUS_PENDING); |
|
| 26 | + |
|
| 27 | + // if this is a regular provisioning require that an authenticated remote user |
|
| 28 | + if (!$wipeRequest) { |
|
| 29 | + SLog::Write(LOGLEVEL_DEBUG, "RequestProcessor::HandleProvision(): Forcing delayed Authentication"); |
|
| 30 | + self::Authenticate(); |
|
| 31 | + } |
|
| 32 | + |
|
| 33 | + $phase2 = true; |
|
| 34 | + |
|
| 35 | + if (!self::$decoder->getElementStartTag(SYNC_PROVISION_PROVISION)) { |
|
| 36 | + return false; |
|
| 37 | + } |
|
| 38 | + |
|
| 39 | + // Loop through Provision request tags. Possible are: |
|
| 40 | + // - Remote Wipe |
|
| 41 | + // - DeviceInformation |
|
| 42 | + // - Policies |
|
| 43 | + // Each of them should only be once per request. |
|
| 44 | + WBXMLDecoder::ResetInWhile("provisioningMain"); |
|
| 45 | + while (WBXMLDecoder::InWhile("provisioningMain")) { |
|
| 46 | + $requestName = ""; |
|
| 47 | + if (self::$decoder->getElementStartTag(SYNC_PROVISION_REMOTEWIPE)) { |
|
| 48 | + $requestName = SYNC_PROVISION_REMOTEWIPE; |
|
| 49 | + } |
|
| 50 | + if (self::$decoder->getElementStartTag(SYNC_PROVISION_POLICIES)) { |
|
| 51 | + $requestName = SYNC_PROVISION_POLICIES; |
|
| 52 | + } |
|
| 53 | + if (self::$decoder->getElementStartTag(SYNC_SETTINGS_DEVICEINFORMATION)) { |
|
| 54 | + $requestName = SYNC_SETTINGS_DEVICEINFORMATION; |
|
| 55 | + } |
|
| 56 | + |
|
| 57 | + if (!$requestName) { |
|
| 58 | + break; |
|
| 59 | + } |
|
| 60 | + |
|
| 61 | + // set is available for OOF, device password and device information |
|
| 62 | + switch ($requestName) { |
|
| 63 | + case SYNC_PROVISION_REMOTEWIPE: |
|
| 64 | + if (!self::$decoder->getElementStartTag(SYNC_PROVISION_STATUS)) { |
|
| 65 | + return false; |
|
| 66 | + } |
|
| 67 | + |
|
| 68 | + $instatus = self::$decoder->getElementContent(); |
|
| 69 | + |
|
| 70 | + if (!self::$decoder->getElementEndTag()) { |
|
| 71 | + return false; |
|
| 72 | + } |
|
| 73 | + |
|
| 74 | + if (!self::$decoder->getElementEndTag()) { |
|
| 75 | + return false; |
|
| 76 | + } |
|
| 77 | + |
|
| 78 | + $phase2 = false; |
|
| 79 | + $rwstatusWiped = true; |
|
| 80 | + // TODO check - do it after while(1) finished? |
|
| 81 | + break; |
|
| 82 | + |
|
| 83 | + case SYNC_PROVISION_POLICIES: |
|
| 84 | + if (!self::$decoder->getElementStartTag(SYNC_PROVISION_POLICY)) { |
|
| 85 | + return false; |
|
| 86 | + } |
|
| 87 | + |
|
| 88 | + if (!self::$decoder->getElementStartTag(SYNC_PROVISION_POLICYTYPE)) { |
|
| 89 | + return false; |
|
| 90 | + } |
|
| 91 | + |
|
| 92 | + $policytype = self::$decoder->getElementContent(); |
|
| 93 | + if ($policytype != 'MS-WAP-Provisioning-XML' && $policytype != 'MS-EAS-Provisioning-WBXML') { |
|
| 94 | + $status = SYNC_PROVISION_STATUS_SERVERERROR; |
|
| 95 | + } |
|
| 96 | + if (!self::$decoder->getElementEndTag()) { // policytype |
|
| 97 | + return false; |
|
| 98 | + } |
|
| 99 | + |
|
| 100 | + if (self::$decoder->getElementStartTag(SYNC_PROVISION_POLICYKEY)) { |
|
| 101 | + $devpolicykey = self::$decoder->getElementContent(); |
|
| 102 | + |
|
| 103 | + if (!self::$decoder->getElementEndTag()) { |
|
| 104 | + return false; |
|
| 105 | + } |
|
| 106 | + |
|
| 107 | + if (!self::$decoder->getElementStartTag(SYNC_PROVISION_STATUS)) { |
|
| 108 | + return false; |
|
| 109 | + } |
|
| 110 | + |
|
| 111 | + $instatus = self::$decoder->getElementContent(); |
|
| 112 | + |
|
| 113 | + if (!self::$decoder->getElementEndTag()) { |
|
| 114 | + return false; |
|
| 115 | + } |
|
| 116 | + |
|
| 117 | + $phase2 = false; |
|
| 118 | + } |
|
| 119 | + |
|
| 120 | + if (!self::$decoder->getElementEndTag()) { // policy |
|
| 121 | + return false; |
|
| 122 | + } |
|
| 123 | + |
|
| 124 | + if (!self::$decoder->getElementEndTag()) { // policies |
|
| 125 | + return false; |
|
| 126 | + } |
|
| 127 | + break; |
|
| 128 | + |
|
| 129 | + case SYNC_SETTINGS_DEVICEINFORMATION: |
|
| 130 | + // AS14.1 and later clients pass Device Information on the initial Provision request |
|
| 131 | + if (!self::$decoder->getElementStartTag(SYNC_SETTINGS_SET)) { |
|
| 132 | + return false; |
|
| 133 | + } |
|
| 134 | + $deviceInfoSet = true; |
|
| 135 | + $deviceinformation = new SyncDeviceInformation(); |
|
| 136 | + $deviceinformation->Decode(self::$decoder); |
|
| 137 | + $deviceinformation->Status = SYNC_SETTINGSSTATUS_SUCCESS; |
|
| 138 | + if (!$wipeRequest) { |
|
| 139 | + // for this operation the device manager is available |
|
| 140 | + GSync::GetDeviceManager()->SaveDeviceInformation($deviceinformation); |
|
| 141 | + } |
|
| 142 | + else { |
|
| 143 | + SLog::Write(LOGLEVEL_DEBUG, "Ignoring incoming device information as WIPE is due."); |
|
| 144 | + } |
|
| 145 | + if (!self::$decoder->getElementEndTag()) { // SYNC_SETTINGS_SET |
|
| 146 | + return false; |
|
| 147 | + } |
|
| 148 | + if (!self::$decoder->getElementEndTag()) { // SYNC_SETTINGS_DEVICEINFORMATION |
|
| 149 | + return false; |
|
| 150 | + } |
|
| 151 | + break; |
|
| 152 | + |
|
| 153 | + default: |
|
| 154 | + // TODO: a special status code needed? |
|
| 155 | + SLog::Write(LOGLEVEL_WARN, sprintf("This property ('%s') is not allowed to be used in a provision request", $requestName)); |
|
| 156 | + } |
|
| 157 | + } |
|
| 158 | + |
|
| 159 | + if (!self::$decoder->getElementEndTag()) { // provision |
|
| 160 | + return false; |
|
| 161 | + } |
|
| 162 | + |
|
| 163 | + if (PROVISIONING !== true) { |
|
| 164 | + SLog::Write(LOGLEVEL_INFO, "No policies deployed to device"); |
|
| 165 | + $policystatus = SYNC_PROVISION_POLICYSTATUS_NOPOLICY; |
|
| 166 | + } |
|
| 167 | + |
|
| 168 | + self::$encoder->StartWBXML(); |
|
| 169 | + |
|
| 170 | + // just create a temporary key (i.e. iPhone OS4 Beta does not like policykey 0 in response) |
|
| 171 | + $policykey = GSync::GetProvisioningManager()->GenerateProvisioningPolicyKey(); |
|
| 172 | + |
|
| 173 | + self::$encoder->startTag(SYNC_PROVISION_PROVISION); |
|
| 174 | + |
|
| 175 | + self::$encoder->startTag(SYNC_PROVISION_STATUS); |
|
| 176 | + self::$encoder->content($status); |
|
| 177 | + self::$encoder->endTag(); |
|
| 178 | + |
|
| 179 | + if ($deviceInfoSet) { |
|
| 180 | + self::$encoder->startTag(SYNC_SETTINGS_DEVICEINFORMATION); |
|
| 181 | + self::$encoder->startTag(SYNC_SETTINGS_STATUS); |
|
| 182 | + self::$encoder->content($deviceinformation->Status); |
|
| 183 | + self::$encoder->endTag(); // SYNC_SETTINGS_STATUS |
|
| 184 | + self::$encoder->endTag(); // SYNC_SETTINGS_DEVICEINFORMATION |
|
| 185 | + } |
|
| 186 | + |
|
| 187 | + self::$encoder->startTag(SYNC_PROVISION_POLICIES); |
|
| 188 | + self::$encoder->startTag(SYNC_PROVISION_POLICY); |
|
| 189 | + |
|
| 190 | + if (isset($policytype)) { |
|
| 191 | + self::$encoder->startTag(SYNC_PROVISION_POLICYTYPE); |
|
| 192 | + self::$encoder->content($policytype); |
|
| 193 | + self::$encoder->endTag(); |
|
| 194 | + } |
|
| 195 | + |
|
| 196 | + self::$encoder->startTag(SYNC_PROVISION_STATUS); |
|
| 197 | + self::$encoder->content($policystatus); |
|
| 198 | + self::$encoder->endTag(); |
|
| 199 | + |
|
| 200 | + self::$encoder->startTag(SYNC_PROVISION_POLICYKEY); |
|
| 201 | + self::$encoder->content($policykey); |
|
| 202 | + self::$encoder->endTag(); |
|
| 203 | + |
|
| 204 | + if ($phase2 && $policystatus === SYNC_PROVISION_POLICYSTATUS_SUCCESS) { |
|
| 205 | + self::$encoder->startTag(SYNC_PROVISION_DATA); |
|
| 206 | + if ($policytype == 'MS-WAP-Provisioning-XML') { |
|
| 207 | + self::$encoder->content('<wap-provisioningdoc><characteristic type="SecurityPolicy"><parm name="4131" value="1"/><parm name="4133" value="1"/></characteristic></wap-provisioningdoc>'); |
|
| 208 | + } |
|
| 209 | + elseif ($policytype == 'MS-EAS-Provisioning-WBXML') { |
|
| 210 | + self::$encoder->startTag(SYNC_PROVISION_EASPROVISIONDOC); |
|
| 211 | + |
|
| 212 | + // get the provisioning object and log the loaded policy values |
|
| 213 | + $prov = GSync::GetProvisioningManager()->GetProvisioningObject(true); |
|
| 214 | + if (!$prov->Check()) { |
|
| 215 | + throw new FatalException("Invalid policies!"); |
|
| 216 | + } |
|
| 217 | + |
|
| 218 | + GSync::GetProvisioningManager()->SavePolicyHash($prov); |
|
| 219 | + $prov->Encode(self::$encoder); |
|
| 220 | + self::$encoder->endTag(); |
|
| 221 | + } |
|
| 222 | + else { |
|
| 223 | + SLog::Write(LOGLEVEL_WARN, "Wrong policy type"); |
|
| 224 | + self::$topCollector->AnnounceInformation("Policytype not supported", true); |
|
| 225 | + |
|
| 226 | + return false; |
|
| 227 | + } |
|
| 228 | + self::$topCollector->AnnounceInformation("Updated provisioning", true); |
|
| 229 | + |
|
| 230 | + self::$encoder->endTag(); // data |
|
| 231 | + } |
|
| 232 | + self::$encoder->endTag(); // policy |
|
| 233 | + self::$encoder->endTag(); // policies |
|
| 234 | + |
|
| 235 | + // set the new final policy key in the provisioning manager |
|
| 236 | + if (!$phase2 && !$wipeRequest) { |
|
| 237 | + GSync::GetProvisioningManager()->SetProvisioningPolicyKey($policykey); |
|
| 238 | + self::$topCollector->AnnounceInformation("Policies deployed", true); |
|
| 239 | + } |
|
| 240 | + |
|
| 241 | + // wipe data if a higher RWSTATUS is requested |
|
| 242 | + if ($rwstatus > SYNC_PROVISION_RWSTATUS_OK && $policystatus === SYNC_PROVISION_POLICYSTATUS_SUCCESS) { |
|
| 243 | + self::$encoder->startTag(SYNC_PROVISION_REMOTEWIPE, false, true); |
|
| 244 | + GSync::GetProvisioningManager()->SetProvisioningWipeStatus(($rwstatusWiped) ? SYNC_PROVISION_RWSTATUS_WIPED : SYNC_PROVISION_RWSTATUS_REQUESTED); |
|
| 245 | + self::$topCollector->AnnounceInformation(sprintf("Remote wipe %s", ($rwstatusWiped) ? "executed" : "requested"), true); |
|
| 246 | + } |
|
| 247 | + |
|
| 248 | + self::$encoder->endTag(); // provision |
|
| 249 | + |
|
| 250 | + return true; |
|
| 251 | + } |
|
| 252 | 252 | } |
@@ -138,8 +138,7 @@ discard block |
||
| 138 | 138 | if (!$wipeRequest) { |
| 139 | 139 | // for this operation the device manager is available |
| 140 | 140 | GSync::GetDeviceManager()->SaveDeviceInformation($deviceinformation); |
| 141 | - } |
|
| 142 | - else { |
|
| 141 | + } else { |
|
| 143 | 142 | SLog::Write(LOGLEVEL_DEBUG, "Ignoring incoming device information as WIPE is due."); |
| 144 | 143 | } |
| 145 | 144 | if (!self::$decoder->getElementEndTag()) { // SYNC_SETTINGS_SET |
@@ -205,8 +204,7 @@ discard block |
||
| 205 | 204 | self::$encoder->startTag(SYNC_PROVISION_DATA); |
| 206 | 205 | if ($policytype == 'MS-WAP-Provisioning-XML') { |
| 207 | 206 | self::$encoder->content('<wap-provisioningdoc><characteristic type="SecurityPolicy"><parm name="4131" value="1"/><parm name="4133" value="1"/></characteristic></wap-provisioningdoc>'); |
| 208 | - } |
|
| 209 | - elseif ($policytype == 'MS-EAS-Provisioning-WBXML') { |
|
| 207 | + } elseif ($policytype == 'MS-EAS-Provisioning-WBXML') { |
|
| 210 | 208 | self::$encoder->startTag(SYNC_PROVISION_EASPROVISIONDOC); |
| 211 | 209 | |
| 212 | 210 | // get the provisioning object and log the loaded policy values |
@@ -218,8 +216,7 @@ discard block |
||
| 218 | 216 | GSync::GetProvisioningManager()->SavePolicyHash($prov); |
| 219 | 217 | $prov->Encode(self::$encoder); |
| 220 | 218 | self::$encoder->endTag(); |
| 221 | - } |
|
| 222 | - else { |
|
| 219 | + } else { |
|
| 223 | 220 | SLog::Write(LOGLEVEL_WARN, "Wrong policy type"); |
| 224 | 221 | self::$topCollector->AnnounceInformation("Policytype not supported", true); |
| 225 | 222 | |
@@ -8,776 +8,776 @@ discard block |
||
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | 10 | class Request { |
| 11 | - public const MAXMEMORYUSAGE = 0.9; // use max. 90% of allowed memory when syncing |
|
| 12 | - public const UNKNOWN = "unknown"; |
|
| 13 | - public const IMPERSONATE_DELIM = '#'; |
|
| 14 | - |
|
| 15 | - /** |
|
| 16 | - * self::filterEvilInput() options. |
|
| 17 | - */ |
|
| 18 | - public const LETTERS_ONLY = 1; |
|
| 19 | - public const HEX_ONLY = 2; |
|
| 20 | - public const WORDCHAR_ONLY = 3; |
|
| 21 | - public const NUMBERS_ONLY = 4; |
|
| 22 | - public const NUMBERSDOT_ONLY = 5; |
|
| 23 | - public const HEX_EXTENDED = 6; |
|
| 24 | - public const ISO8601 = 7; |
|
| 25 | - public const HEX_EXTENDED2 = 8; |
|
| 26 | - |
|
| 27 | - /** |
|
| 28 | - * Command parameters for base64 encoded requests (AS >= 12.1). |
|
| 29 | - */ |
|
| 30 | - public const COMMANDPARAM_ATTACHMENTNAME = 0; |
|
| 31 | - public const COMMANDPARAM_COLLECTIONID = 1; // deprecated |
|
| 32 | - public const COMMANDPARAM_COLLECTIONNAME = 2; // deprecated |
|
| 33 | - public const COMMANDPARAM_ITEMID = 3; |
|
| 34 | - public const COMMANDPARAM_LONGID = 4; |
|
| 35 | - public const COMMANDPARAM_PARENTID = 5; // deprecated |
|
| 36 | - public const COMMANDPARAM_OCCURRENCE = 6; |
|
| 37 | - public const COMMANDPARAM_OPTIONS = 7; // used by SmartReply, SmartForward, SendMail, ItemOperations |
|
| 38 | - public const COMMANDPARAM_USER = 8; // used by any command |
|
| 39 | - // possible bitflags for COMMANDPARAM_OPTIONS |
|
| 40 | - public const COMMANDPARAM_OPTIONS_SAVEINSENT = 0x01; |
|
| 41 | - public const COMMANDPARAM_OPTIONS_ACCEPTMULTIPART = 0x02; |
|
| 42 | - |
|
| 43 | - private static $input; |
|
| 44 | - private static $output; |
|
| 45 | - private static $headers; |
|
| 46 | - private static $command; |
|
| 47 | - private static $method; |
|
| 48 | - private static $remoteAddr; |
|
| 49 | - private static $getUser; |
|
| 50 | - private static $devid; |
|
| 51 | - private static $devtype; |
|
| 52 | - private static $authUserString; |
|
| 53 | - private static $authUser; |
|
| 54 | - private static $authDomain; |
|
| 55 | - private static $authPassword; |
|
| 56 | - private static $impersonatedUser; |
|
| 57 | - private static $asProtocolVersion; |
|
| 58 | - private static $policykey; |
|
| 59 | - private static $useragent; |
|
| 60 | - private static $attachmentName; |
|
| 61 | - private static $collectionId; |
|
| 62 | - private static $itemId; |
|
| 63 | - private static $longId; // TODO |
|
| 64 | - private static $occurrence; // TODO |
|
| 65 | - private static $saveInSent; |
|
| 66 | - private static $acceptMultipart; |
|
| 67 | - private static $base64QueryDecoded; |
|
| 68 | - private static $expectedConnectionTimeout; |
|
| 69 | - private static $memoryLimit; |
|
| 70 | - |
|
| 71 | - /** |
|
| 72 | - * Initializes request data. |
|
| 73 | - * |
|
| 74 | - * @return |
|
| 75 | - */ |
|
| 76 | - public static function Initialize() { |
|
| 77 | - // try to open stdin & stdout |
|
| 78 | - self::$input = fopen("php://input", "r"); |
|
| 79 | - self::$output = fopen("php://output", "w+"); |
|
| 80 | - |
|
| 81 | - // Parse the standard GET parameters |
|
| 82 | - if (isset($_GET["Cmd"])) { |
|
| 83 | - self::$command = self::filterEvilInput($_GET["Cmd"], self::LETTERS_ONLY); |
|
| 84 | - } |
|
| 85 | - |
|
| 86 | - // getUser is unfiltered, as everything is allowed.. even "/", "\" or ".." |
|
| 87 | - if (isset($_GET["User"])) { |
|
| 88 | - self::$getUser = strtolower($_GET["User"]); |
|
| 89 | - if (defined('USE_FULLEMAIL_FOR_LOGIN') && !USE_FULLEMAIL_FOR_LOGIN) { |
|
| 90 | - self::$getUser = Utils::GetLocalPartFromEmail(self::$getUser); |
|
| 91 | - } |
|
| 92 | - } |
|
| 93 | - if (isset($_GET["DeviceId"])) { |
|
| 94 | - self::$devid = strtolower(self::filterEvilInput($_GET["DeviceId"], self::WORDCHAR_ONLY)); |
|
| 95 | - } |
|
| 96 | - if (isset($_GET["DeviceType"])) { |
|
| 97 | - self::$devtype = self::filterEvilInput($_GET["DeviceType"], self::LETTERS_ONLY); |
|
| 98 | - } |
|
| 99 | - if (isset($_GET["AttachmentName"])) { |
|
| 100 | - self::$attachmentName = self::filterEvilInput($_GET["AttachmentName"], self::HEX_EXTENDED2); |
|
| 101 | - } |
|
| 102 | - if (isset($_GET["CollectionId"])) { |
|
| 103 | - self::$collectionId = self::filterEvilInput($_GET["CollectionId"], self::HEX_EXTENDED2); |
|
| 104 | - } |
|
| 105 | - if (isset($_GET["ItemId"])) { |
|
| 106 | - self::$itemId = self::filterEvilInput($_GET["ItemId"], self::HEX_EXTENDED2); |
|
| 107 | - } |
|
| 108 | - if (isset($_GET["SaveInSent"]) && $_GET["SaveInSent"] == "T") { |
|
| 109 | - self::$saveInSent = true; |
|
| 110 | - } |
|
| 111 | - |
|
| 112 | - if (isset($_SERVER["REQUEST_METHOD"])) { |
|
| 113 | - self::$method = self::filterEvilInput($_SERVER["REQUEST_METHOD"], self::LETTERS_ONLY); |
|
| 114 | - } |
|
| 115 | - // TODO check IPv6 addresses |
|
| 116 | - if (isset($_SERVER["REMOTE_ADDR"])) { |
|
| 117 | - self::$remoteAddr = self::filterIP($_SERVER["REMOTE_ADDR"]); |
|
| 118 | - } |
|
| 119 | - |
|
| 120 | - // in protocol version > 14 mobile send these inputs as encoded query string |
|
| 121 | - if (!isset(self::$command) && !empty($_SERVER['QUERY_STRING']) && Utils::IsBase64String($_SERVER['QUERY_STRING'])) { |
|
| 122 | - self::decodeBase64URI(); |
|
| 123 | - if (!isset(self::$command) && isset(self::$base64QueryDecoded['Command'])) { |
|
| 124 | - self::$command = Utils::GetCommandFromCode(self::$base64QueryDecoded['Command']); |
|
| 125 | - } |
|
| 126 | - |
|
| 127 | - if (!isset(self::$getUser) && isset(self::$base64QueryDecoded[self::COMMANDPARAM_USER])) { |
|
| 128 | - self::$getUser = strtolower(self::$base64QueryDecoded[self::COMMANDPARAM_USER]); |
|
| 129 | - if (defined('USE_FULLEMAIL_FOR_LOGIN') && !USE_FULLEMAIL_FOR_LOGIN) { |
|
| 130 | - self::$getUser = Utils::GetLocalPartFromEmail(self::$getUser); |
|
| 131 | - } |
|
| 132 | - } |
|
| 133 | - |
|
| 134 | - if (!isset(self::$devid) && isset(self::$base64QueryDecoded['DevID'])) { |
|
| 135 | - self::$devid = strtolower(self::filterEvilInput(self::$base64QueryDecoded['DevID'], self::WORDCHAR_ONLY)); |
|
| 136 | - } |
|
| 137 | - |
|
| 138 | - if (!isset(self::$devtype) && isset(self::$base64QueryDecoded['DevType'])) { |
|
| 139 | - self::$devtype = self::filterEvilInput(self::$base64QueryDecoded['DevType'], self::LETTERS_ONLY); |
|
| 140 | - } |
|
| 141 | - |
|
| 142 | - if (isset(self::$base64QueryDecoded['PolKey'])) { |
|
| 143 | - self::$policykey = (int) self::filterEvilInput(self::$base64QueryDecoded['PolKey'], self::NUMBERS_ONLY); |
|
| 144 | - } |
|
| 145 | - |
|
| 146 | - if (isset(self::$base64QueryDecoded['ProtVer'])) { |
|
| 147 | - self::$asProtocolVersion = self::filterEvilInput(self::$base64QueryDecoded['ProtVer'], self::NUMBERS_ONLY) / 10; |
|
| 148 | - } |
|
| 149 | - |
|
| 150 | - if (isset(self::$base64QueryDecoded[self::COMMANDPARAM_ATTACHMENTNAME])) { |
|
| 151 | - self::$attachmentName = self::filterEvilInput(self::$base64QueryDecoded[self::COMMANDPARAM_ATTACHMENTNAME], self::HEX_EXTENDED2); |
|
| 152 | - } |
|
| 153 | - |
|
| 154 | - if (isset(self::$base64QueryDecoded[self::COMMANDPARAM_COLLECTIONID])) { |
|
| 155 | - self::$collectionId = self::filterEvilInput(self::$base64QueryDecoded[self::COMMANDPARAM_COLLECTIONID], self::HEX_EXTENDED2); |
|
| 156 | - } |
|
| 157 | - |
|
| 158 | - if (isset(self::$base64QueryDecoded[self::COMMANDPARAM_ITEMID])) { |
|
| 159 | - self::$itemId = self::filterEvilInput(self::$base64QueryDecoded[self::COMMANDPARAM_ITEMID], self::HEX_EXTENDED2); |
|
| 160 | - } |
|
| 161 | - |
|
| 162 | - if (isset(self::$base64QueryDecoded[self::COMMANDPARAM_OPTIONS]) && (ord(self::$base64QueryDecoded[self::COMMANDPARAM_OPTIONS]) & self::COMMANDPARAM_OPTIONS_SAVEINSENT)) { |
|
| 163 | - self::$saveInSent = true; |
|
| 164 | - } |
|
| 165 | - |
|
| 166 | - if (isset(self::$base64QueryDecoded[self::COMMANDPARAM_OPTIONS]) && (ord(self::$base64QueryDecoded[self::COMMANDPARAM_OPTIONS]) & self::COMMANDPARAM_OPTIONS_ACCEPTMULTIPART)) { |
|
| 167 | - self::$acceptMultipart = true; |
|
| 168 | - } |
|
| 169 | - } |
|
| 170 | - |
|
| 171 | - // in base64 encoded query string user is not necessarily set |
|
| 172 | - if (!isset(self::$getUser) && isset($_SERVER['PHP_AUTH_USER'])) { |
|
| 173 | - list(self::$getUser) = Utils::SplitDomainUser(strtolower($_SERVER['PHP_AUTH_USER'])); |
|
| 174 | - if (defined('USE_FULLEMAIL_FOR_LOGIN') && !USE_FULLEMAIL_FOR_LOGIN) { |
|
| 175 | - self::$getUser = Utils::GetLocalPartFromEmail(self::$getUser); |
|
| 176 | - } |
|
| 177 | - } |
|
| 178 | - |
|
| 179 | - // authUser & authPassword are unfiltered! |
|
| 180 | - // split username & domain if received as one |
|
| 181 | - if (isset($_SERVER['PHP_AUTH_USER'])) { |
|
| 182 | - list(self::$authUserString, self::$authDomain) = Utils::SplitDomainUser($_SERVER['PHP_AUTH_USER']); |
|
| 183 | - self::$authPassword = (isset($_SERVER['PHP_AUTH_PW'])) ? $_SERVER['PHP_AUTH_PW'] : ""; |
|
| 184 | - } |
|
| 185 | - |
|
| 186 | - // process impersonation |
|
| 187 | - self::$authUser = self::$authUserString; |
|
| 188 | - |
|
| 189 | - if (defined('USE_FULLEMAIL_FOR_LOGIN') && !USE_FULLEMAIL_FOR_LOGIN) { |
|
| 190 | - self::$authUser = Utils::GetLocalPartFromEmail(self::$authUser); |
|
| 191 | - } |
|
| 192 | - |
|
| 193 | - // get & convert configured memory limit |
|
| 194 | - $memoryLimit = ini_get('memory_limit'); |
|
| 195 | - if ($memoryLimit == -1) { |
|
| 196 | - self::$memoryLimit = false; |
|
| 197 | - } |
|
| 198 | - else { |
|
| 199 | - preg_replace_callback( |
|
| 200 | - '/(\-?\d+)(.?)/', |
|
| 201 | - function ($m) { |
|
| 202 | - self::$memoryLimit = $m[1] * pow(1024, strpos('BKMG', $m[2])) * self::MAXMEMORYUSAGE; |
|
| 203 | - }, |
|
| 204 | - strtoupper($memoryLimit) |
|
| 205 | - ); |
|
| 206 | - } |
|
| 207 | - } |
|
| 208 | - |
|
| 209 | - /** |
|
| 210 | - * Reads and processes the request headers. |
|
| 211 | - * |
|
| 212 | - * @return |
|
| 213 | - */ |
|
| 214 | - public static function ProcessHeaders() { |
|
| 215 | - self::$headers = array_change_key_case(apache_request_headers(), CASE_LOWER); |
|
| 216 | - self::$useragent = (isset(self::$headers["user-agent"])) ? self::$headers["user-agent"] : self::UNKNOWN; |
|
| 217 | - if (!isset(self::$asProtocolVersion)) { |
|
| 218 | - self::$asProtocolVersion = (isset(self::$headers["ms-asprotocolversion"])) ? self::filterEvilInput(self::$headers["ms-asprotocolversion"], self::NUMBERSDOT_ONLY) : GSync::GetLatestSupportedASVersion(); |
|
| 219 | - } |
|
| 220 | - |
|
| 221 | - // if policykey is not yet set, try to set it from the header |
|
| 222 | - // the policy key might be set in Request::Initialize from the base64 encoded query |
|
| 223 | - if (!isset(self::$policykey)) { |
|
| 224 | - if (isset(self::$headers["x-ms-policykey"])) { |
|
| 225 | - self::$policykey = (int) self::filterEvilInput(self::$headers["x-ms-policykey"], self::NUMBERS_ONLY); |
|
| 226 | - } |
|
| 227 | - else { |
|
| 228 | - self::$policykey = 0; |
|
| 229 | - } |
|
| 230 | - } |
|
| 231 | - |
|
| 232 | - if (isset(self::$base64QueryDecoded)) { |
|
| 233 | - SLog::Write(LOGLEVEL_DEBUG, sprintf("Request::ProcessHeaders(): base64 query string: '%s' (decoded: '%s')", $_SERVER['QUERY_STRING'], http_build_query(self::$base64QueryDecoded, '', ','))); |
|
| 234 | - if (isset(self::$policykey)) { |
|
| 235 | - self::$headers["x-ms-policykey"] = self::$policykey; |
|
| 236 | - } |
|
| 237 | - |
|
| 238 | - if (isset(self::$asProtocolVersion)) { |
|
| 239 | - self::$headers["ms-asprotocolversion"] = self::$asProtocolVersion; |
|
| 240 | - } |
|
| 241 | - } |
|
| 242 | - |
|
| 243 | - if (!isset(self::$acceptMultipart) && isset(self::$headers["ms-asacceptmultipart"]) && strtoupper(self::$headers["ms-asacceptmultipart"]) == "T") { |
|
| 244 | - self::$acceptMultipart = true; |
|
| 245 | - } |
|
| 246 | - |
|
| 247 | - SLog::Write(LOGLEVEL_DEBUG, sprintf("Request::ProcessHeaders() ASVersion: %s", self::$asProtocolVersion)); |
|
| 248 | - |
|
| 249 | - if (defined('USE_CUSTOM_REMOTE_IP_HEADER') && USE_CUSTOM_REMOTE_IP_HEADER !== false) { |
|
| 250 | - // make custom header compatible with Apache modphp (see ZP-1332) |
|
| 251 | - $header = $apacheHeader = strtolower(USE_CUSTOM_REMOTE_IP_HEADER); |
|
| 252 | - if (substr($apacheHeader, 0, 5) === 'http_') { |
|
| 253 | - $apacheHeader = substr($apacheHeader, 5); |
|
| 254 | - } |
|
| 255 | - $apacheHeader = str_replace("_", "-", $apacheHeader); |
|
| 256 | - if (isset(self::$headers[$header]) || isset(self::$headers[$apacheHeader])) { |
|
| 257 | - $remoteIP = isset(self::$headers[$header]) ? self::$headers[$header] : self::$headers[$apacheHeader]; |
|
| 258 | - // X-Forwarded-For may contain multiple IPs separated by comma: client, proxy1, proxy2. |
|
| 259 | - // In such case we will only check the client IP. See https://jira.z-hub.io/browse/ZP-1434. |
|
| 260 | - if (strpos($remoteIP, ',') !== false) { |
|
| 261 | - $remoteIP = trim(explode(',', $remoteIP)[0]); |
|
| 262 | - } |
|
| 263 | - $remoteIP = self::filterIP($remoteIP); |
|
| 264 | - if ($remoteIP) { |
|
| 265 | - SLog::Write(LOGLEVEL_DEBUG, sprintf("Using custom header '%s' to determine remote IP: %s - connect is coming from IP: %s", USE_CUSTOM_REMOTE_IP_HEADER, $remoteIP, self::$remoteAddr)); |
|
| 266 | - self::$remoteAddr = $remoteIP; |
|
| 267 | - } |
|
| 268 | - } |
|
| 269 | - } |
|
| 270 | - } |
|
| 271 | - |
|
| 272 | - /** |
|
| 273 | - * @return bool data sent or not |
|
| 274 | - */ |
|
| 275 | - public static function HasAuthenticationInfo() { |
|
| 276 | - return self::$authUser != "" && self::$authPassword != ""; |
|
| 277 | - } |
|
| 278 | - |
|
| 279 | - /*---------------------------------------------------------------------------------------------------------- |
|
| 11 | + public const MAXMEMORYUSAGE = 0.9; // use max. 90% of allowed memory when syncing |
|
| 12 | + public const UNKNOWN = "unknown"; |
|
| 13 | + public const IMPERSONATE_DELIM = '#'; |
|
| 14 | + |
|
| 15 | + /** |
|
| 16 | + * self::filterEvilInput() options. |
|
| 17 | + */ |
|
| 18 | + public const LETTERS_ONLY = 1; |
|
| 19 | + public const HEX_ONLY = 2; |
|
| 20 | + public const WORDCHAR_ONLY = 3; |
|
| 21 | + public const NUMBERS_ONLY = 4; |
|
| 22 | + public const NUMBERSDOT_ONLY = 5; |
|
| 23 | + public const HEX_EXTENDED = 6; |
|
| 24 | + public const ISO8601 = 7; |
|
| 25 | + public const HEX_EXTENDED2 = 8; |
|
| 26 | + |
|
| 27 | + /** |
|
| 28 | + * Command parameters for base64 encoded requests (AS >= 12.1). |
|
| 29 | + */ |
|
| 30 | + public const COMMANDPARAM_ATTACHMENTNAME = 0; |
|
| 31 | + public const COMMANDPARAM_COLLECTIONID = 1; // deprecated |
|
| 32 | + public const COMMANDPARAM_COLLECTIONNAME = 2; // deprecated |
|
| 33 | + public const COMMANDPARAM_ITEMID = 3; |
|
| 34 | + public const COMMANDPARAM_LONGID = 4; |
|
| 35 | + public const COMMANDPARAM_PARENTID = 5; // deprecated |
|
| 36 | + public const COMMANDPARAM_OCCURRENCE = 6; |
|
| 37 | + public const COMMANDPARAM_OPTIONS = 7; // used by SmartReply, SmartForward, SendMail, ItemOperations |
|
| 38 | + public const COMMANDPARAM_USER = 8; // used by any command |
|
| 39 | + // possible bitflags for COMMANDPARAM_OPTIONS |
|
| 40 | + public const COMMANDPARAM_OPTIONS_SAVEINSENT = 0x01; |
|
| 41 | + public const COMMANDPARAM_OPTIONS_ACCEPTMULTIPART = 0x02; |
|
| 42 | + |
|
| 43 | + private static $input; |
|
| 44 | + private static $output; |
|
| 45 | + private static $headers; |
|
| 46 | + private static $command; |
|
| 47 | + private static $method; |
|
| 48 | + private static $remoteAddr; |
|
| 49 | + private static $getUser; |
|
| 50 | + private static $devid; |
|
| 51 | + private static $devtype; |
|
| 52 | + private static $authUserString; |
|
| 53 | + private static $authUser; |
|
| 54 | + private static $authDomain; |
|
| 55 | + private static $authPassword; |
|
| 56 | + private static $impersonatedUser; |
|
| 57 | + private static $asProtocolVersion; |
|
| 58 | + private static $policykey; |
|
| 59 | + private static $useragent; |
|
| 60 | + private static $attachmentName; |
|
| 61 | + private static $collectionId; |
|
| 62 | + private static $itemId; |
|
| 63 | + private static $longId; // TODO |
|
| 64 | + private static $occurrence; // TODO |
|
| 65 | + private static $saveInSent; |
|
| 66 | + private static $acceptMultipart; |
|
| 67 | + private static $base64QueryDecoded; |
|
| 68 | + private static $expectedConnectionTimeout; |
|
| 69 | + private static $memoryLimit; |
|
| 70 | + |
|
| 71 | + /** |
|
| 72 | + * Initializes request data. |
|
| 73 | + * |
|
| 74 | + * @return |
|
| 75 | + */ |
|
| 76 | + public static function Initialize() { |
|
| 77 | + // try to open stdin & stdout |
|
| 78 | + self::$input = fopen("php://input", "r"); |
|
| 79 | + self::$output = fopen("php://output", "w+"); |
|
| 80 | + |
|
| 81 | + // Parse the standard GET parameters |
|
| 82 | + if (isset($_GET["Cmd"])) { |
|
| 83 | + self::$command = self::filterEvilInput($_GET["Cmd"], self::LETTERS_ONLY); |
|
| 84 | + } |
|
| 85 | + |
|
| 86 | + // getUser is unfiltered, as everything is allowed.. even "/", "\" or ".." |
|
| 87 | + if (isset($_GET["User"])) { |
|
| 88 | + self::$getUser = strtolower($_GET["User"]); |
|
| 89 | + if (defined('USE_FULLEMAIL_FOR_LOGIN') && !USE_FULLEMAIL_FOR_LOGIN) { |
|
| 90 | + self::$getUser = Utils::GetLocalPartFromEmail(self::$getUser); |
|
| 91 | + } |
|
| 92 | + } |
|
| 93 | + if (isset($_GET["DeviceId"])) { |
|
| 94 | + self::$devid = strtolower(self::filterEvilInput($_GET["DeviceId"], self::WORDCHAR_ONLY)); |
|
| 95 | + } |
|
| 96 | + if (isset($_GET["DeviceType"])) { |
|
| 97 | + self::$devtype = self::filterEvilInput($_GET["DeviceType"], self::LETTERS_ONLY); |
|
| 98 | + } |
|
| 99 | + if (isset($_GET["AttachmentName"])) { |
|
| 100 | + self::$attachmentName = self::filterEvilInput($_GET["AttachmentName"], self::HEX_EXTENDED2); |
|
| 101 | + } |
|
| 102 | + if (isset($_GET["CollectionId"])) { |
|
| 103 | + self::$collectionId = self::filterEvilInput($_GET["CollectionId"], self::HEX_EXTENDED2); |
|
| 104 | + } |
|
| 105 | + if (isset($_GET["ItemId"])) { |
|
| 106 | + self::$itemId = self::filterEvilInput($_GET["ItemId"], self::HEX_EXTENDED2); |
|
| 107 | + } |
|
| 108 | + if (isset($_GET["SaveInSent"]) && $_GET["SaveInSent"] == "T") { |
|
| 109 | + self::$saveInSent = true; |
|
| 110 | + } |
|
| 111 | + |
|
| 112 | + if (isset($_SERVER["REQUEST_METHOD"])) { |
|
| 113 | + self::$method = self::filterEvilInput($_SERVER["REQUEST_METHOD"], self::LETTERS_ONLY); |
|
| 114 | + } |
|
| 115 | + // TODO check IPv6 addresses |
|
| 116 | + if (isset($_SERVER["REMOTE_ADDR"])) { |
|
| 117 | + self::$remoteAddr = self::filterIP($_SERVER["REMOTE_ADDR"]); |
|
| 118 | + } |
|
| 119 | + |
|
| 120 | + // in protocol version > 14 mobile send these inputs as encoded query string |
|
| 121 | + if (!isset(self::$command) && !empty($_SERVER['QUERY_STRING']) && Utils::IsBase64String($_SERVER['QUERY_STRING'])) { |
|
| 122 | + self::decodeBase64URI(); |
|
| 123 | + if (!isset(self::$command) && isset(self::$base64QueryDecoded['Command'])) { |
|
| 124 | + self::$command = Utils::GetCommandFromCode(self::$base64QueryDecoded['Command']); |
|
| 125 | + } |
|
| 126 | + |
|
| 127 | + if (!isset(self::$getUser) && isset(self::$base64QueryDecoded[self::COMMANDPARAM_USER])) { |
|
| 128 | + self::$getUser = strtolower(self::$base64QueryDecoded[self::COMMANDPARAM_USER]); |
|
| 129 | + if (defined('USE_FULLEMAIL_FOR_LOGIN') && !USE_FULLEMAIL_FOR_LOGIN) { |
|
| 130 | + self::$getUser = Utils::GetLocalPartFromEmail(self::$getUser); |
|
| 131 | + } |
|
| 132 | + } |
|
| 133 | + |
|
| 134 | + if (!isset(self::$devid) && isset(self::$base64QueryDecoded['DevID'])) { |
|
| 135 | + self::$devid = strtolower(self::filterEvilInput(self::$base64QueryDecoded['DevID'], self::WORDCHAR_ONLY)); |
|
| 136 | + } |
|
| 137 | + |
|
| 138 | + if (!isset(self::$devtype) && isset(self::$base64QueryDecoded['DevType'])) { |
|
| 139 | + self::$devtype = self::filterEvilInput(self::$base64QueryDecoded['DevType'], self::LETTERS_ONLY); |
|
| 140 | + } |
|
| 141 | + |
|
| 142 | + if (isset(self::$base64QueryDecoded['PolKey'])) { |
|
| 143 | + self::$policykey = (int) self::filterEvilInput(self::$base64QueryDecoded['PolKey'], self::NUMBERS_ONLY); |
|
| 144 | + } |
|
| 145 | + |
|
| 146 | + if (isset(self::$base64QueryDecoded['ProtVer'])) { |
|
| 147 | + self::$asProtocolVersion = self::filterEvilInput(self::$base64QueryDecoded['ProtVer'], self::NUMBERS_ONLY) / 10; |
|
| 148 | + } |
|
| 149 | + |
|
| 150 | + if (isset(self::$base64QueryDecoded[self::COMMANDPARAM_ATTACHMENTNAME])) { |
|
| 151 | + self::$attachmentName = self::filterEvilInput(self::$base64QueryDecoded[self::COMMANDPARAM_ATTACHMENTNAME], self::HEX_EXTENDED2); |
|
| 152 | + } |
|
| 153 | + |
|
| 154 | + if (isset(self::$base64QueryDecoded[self::COMMANDPARAM_COLLECTIONID])) { |
|
| 155 | + self::$collectionId = self::filterEvilInput(self::$base64QueryDecoded[self::COMMANDPARAM_COLLECTIONID], self::HEX_EXTENDED2); |
|
| 156 | + } |
|
| 157 | + |
|
| 158 | + if (isset(self::$base64QueryDecoded[self::COMMANDPARAM_ITEMID])) { |
|
| 159 | + self::$itemId = self::filterEvilInput(self::$base64QueryDecoded[self::COMMANDPARAM_ITEMID], self::HEX_EXTENDED2); |
|
| 160 | + } |
|
| 161 | + |
|
| 162 | + if (isset(self::$base64QueryDecoded[self::COMMANDPARAM_OPTIONS]) && (ord(self::$base64QueryDecoded[self::COMMANDPARAM_OPTIONS]) & self::COMMANDPARAM_OPTIONS_SAVEINSENT)) { |
|
| 163 | + self::$saveInSent = true; |
|
| 164 | + } |
|
| 165 | + |
|
| 166 | + if (isset(self::$base64QueryDecoded[self::COMMANDPARAM_OPTIONS]) && (ord(self::$base64QueryDecoded[self::COMMANDPARAM_OPTIONS]) & self::COMMANDPARAM_OPTIONS_ACCEPTMULTIPART)) { |
|
| 167 | + self::$acceptMultipart = true; |
|
| 168 | + } |
|
| 169 | + } |
|
| 170 | + |
|
| 171 | + // in base64 encoded query string user is not necessarily set |
|
| 172 | + if (!isset(self::$getUser) && isset($_SERVER['PHP_AUTH_USER'])) { |
|
| 173 | + list(self::$getUser) = Utils::SplitDomainUser(strtolower($_SERVER['PHP_AUTH_USER'])); |
|
| 174 | + if (defined('USE_FULLEMAIL_FOR_LOGIN') && !USE_FULLEMAIL_FOR_LOGIN) { |
|
| 175 | + self::$getUser = Utils::GetLocalPartFromEmail(self::$getUser); |
|
| 176 | + } |
|
| 177 | + } |
|
| 178 | + |
|
| 179 | + // authUser & authPassword are unfiltered! |
|
| 180 | + // split username & domain if received as one |
|
| 181 | + if (isset($_SERVER['PHP_AUTH_USER'])) { |
|
| 182 | + list(self::$authUserString, self::$authDomain) = Utils::SplitDomainUser($_SERVER['PHP_AUTH_USER']); |
|
| 183 | + self::$authPassword = (isset($_SERVER['PHP_AUTH_PW'])) ? $_SERVER['PHP_AUTH_PW'] : ""; |
|
| 184 | + } |
|
| 185 | + |
|
| 186 | + // process impersonation |
|
| 187 | + self::$authUser = self::$authUserString; |
|
| 188 | + |
|
| 189 | + if (defined('USE_FULLEMAIL_FOR_LOGIN') && !USE_FULLEMAIL_FOR_LOGIN) { |
|
| 190 | + self::$authUser = Utils::GetLocalPartFromEmail(self::$authUser); |
|
| 191 | + } |
|
| 192 | + |
|
| 193 | + // get & convert configured memory limit |
|
| 194 | + $memoryLimit = ini_get('memory_limit'); |
|
| 195 | + if ($memoryLimit == -1) { |
|
| 196 | + self::$memoryLimit = false; |
|
| 197 | + } |
|
| 198 | + else { |
|
| 199 | + preg_replace_callback( |
|
| 200 | + '/(\-?\d+)(.?)/', |
|
| 201 | + function ($m) { |
|
| 202 | + self::$memoryLimit = $m[1] * pow(1024, strpos('BKMG', $m[2])) * self::MAXMEMORYUSAGE; |
|
| 203 | + }, |
|
| 204 | + strtoupper($memoryLimit) |
|
| 205 | + ); |
|
| 206 | + } |
|
| 207 | + } |
|
| 208 | + |
|
| 209 | + /** |
|
| 210 | + * Reads and processes the request headers. |
|
| 211 | + * |
|
| 212 | + * @return |
|
| 213 | + */ |
|
| 214 | + public static function ProcessHeaders() { |
|
| 215 | + self::$headers = array_change_key_case(apache_request_headers(), CASE_LOWER); |
|
| 216 | + self::$useragent = (isset(self::$headers["user-agent"])) ? self::$headers["user-agent"] : self::UNKNOWN; |
|
| 217 | + if (!isset(self::$asProtocolVersion)) { |
|
| 218 | + self::$asProtocolVersion = (isset(self::$headers["ms-asprotocolversion"])) ? self::filterEvilInput(self::$headers["ms-asprotocolversion"], self::NUMBERSDOT_ONLY) : GSync::GetLatestSupportedASVersion(); |
|
| 219 | + } |
|
| 220 | + |
|
| 221 | + // if policykey is not yet set, try to set it from the header |
|
| 222 | + // the policy key might be set in Request::Initialize from the base64 encoded query |
|
| 223 | + if (!isset(self::$policykey)) { |
|
| 224 | + if (isset(self::$headers["x-ms-policykey"])) { |
|
| 225 | + self::$policykey = (int) self::filterEvilInput(self::$headers["x-ms-policykey"], self::NUMBERS_ONLY); |
|
| 226 | + } |
|
| 227 | + else { |
|
| 228 | + self::$policykey = 0; |
|
| 229 | + } |
|
| 230 | + } |
|
| 231 | + |
|
| 232 | + if (isset(self::$base64QueryDecoded)) { |
|
| 233 | + SLog::Write(LOGLEVEL_DEBUG, sprintf("Request::ProcessHeaders(): base64 query string: '%s' (decoded: '%s')", $_SERVER['QUERY_STRING'], http_build_query(self::$base64QueryDecoded, '', ','))); |
|
| 234 | + if (isset(self::$policykey)) { |
|
| 235 | + self::$headers["x-ms-policykey"] = self::$policykey; |
|
| 236 | + } |
|
| 237 | + |
|
| 238 | + if (isset(self::$asProtocolVersion)) { |
|
| 239 | + self::$headers["ms-asprotocolversion"] = self::$asProtocolVersion; |
|
| 240 | + } |
|
| 241 | + } |
|
| 242 | + |
|
| 243 | + if (!isset(self::$acceptMultipart) && isset(self::$headers["ms-asacceptmultipart"]) && strtoupper(self::$headers["ms-asacceptmultipart"]) == "T") { |
|
| 244 | + self::$acceptMultipart = true; |
|
| 245 | + } |
|
| 246 | + |
|
| 247 | + SLog::Write(LOGLEVEL_DEBUG, sprintf("Request::ProcessHeaders() ASVersion: %s", self::$asProtocolVersion)); |
|
| 248 | + |
|
| 249 | + if (defined('USE_CUSTOM_REMOTE_IP_HEADER') && USE_CUSTOM_REMOTE_IP_HEADER !== false) { |
|
| 250 | + // make custom header compatible with Apache modphp (see ZP-1332) |
|
| 251 | + $header = $apacheHeader = strtolower(USE_CUSTOM_REMOTE_IP_HEADER); |
|
| 252 | + if (substr($apacheHeader, 0, 5) === 'http_') { |
|
| 253 | + $apacheHeader = substr($apacheHeader, 5); |
|
| 254 | + } |
|
| 255 | + $apacheHeader = str_replace("_", "-", $apacheHeader); |
|
| 256 | + if (isset(self::$headers[$header]) || isset(self::$headers[$apacheHeader])) { |
|
| 257 | + $remoteIP = isset(self::$headers[$header]) ? self::$headers[$header] : self::$headers[$apacheHeader]; |
|
| 258 | + // X-Forwarded-For may contain multiple IPs separated by comma: client, proxy1, proxy2. |
|
| 259 | + // In such case we will only check the client IP. See https://jira.z-hub.io/browse/ZP-1434. |
|
| 260 | + if (strpos($remoteIP, ',') !== false) { |
|
| 261 | + $remoteIP = trim(explode(',', $remoteIP)[0]); |
|
| 262 | + } |
|
| 263 | + $remoteIP = self::filterIP($remoteIP); |
|
| 264 | + if ($remoteIP) { |
|
| 265 | + SLog::Write(LOGLEVEL_DEBUG, sprintf("Using custom header '%s' to determine remote IP: %s - connect is coming from IP: %s", USE_CUSTOM_REMOTE_IP_HEADER, $remoteIP, self::$remoteAddr)); |
|
| 266 | + self::$remoteAddr = $remoteIP; |
|
| 267 | + } |
|
| 268 | + } |
|
| 269 | + } |
|
| 270 | + } |
|
| 271 | + |
|
| 272 | + /** |
|
| 273 | + * @return bool data sent or not |
|
| 274 | + */ |
|
| 275 | + public static function HasAuthenticationInfo() { |
|
| 276 | + return self::$authUser != "" && self::$authPassword != ""; |
|
| 277 | + } |
|
| 278 | + |
|
| 279 | + /*---------------------------------------------------------------------------------------------------------- |
|
| 280 | 280 | * Getter & Checker |
| 281 | 281 | */ |
| 282 | 282 | |
| 283 | - /** |
|
| 284 | - * Returns the input stream. |
|
| 285 | - * |
|
| 286 | - * @return handle/boolean false if not available |
|
| 287 | - */ |
|
| 288 | - public static function GetInputStream() { |
|
| 289 | - if (isset(self::$input)) { |
|
| 290 | - return self::$input; |
|
| 291 | - } |
|
| 292 | - |
|
| 293 | - return false; |
|
| 294 | - } |
|
| 295 | - |
|
| 296 | - /** |
|
| 297 | - * Returns the output stream. |
|
| 298 | - * |
|
| 299 | - * @return handle/boolean false if not available |
|
| 300 | - */ |
|
| 301 | - public static function GetOutputStream() { |
|
| 302 | - if (isset(self::$output)) { |
|
| 303 | - return self::$output; |
|
| 304 | - } |
|
| 305 | - |
|
| 306 | - return false; |
|
| 307 | - } |
|
| 308 | - |
|
| 309 | - /** |
|
| 310 | - * Returns the request method. |
|
| 311 | - * |
|
| 312 | - * @return string |
|
| 313 | - */ |
|
| 314 | - public static function GetMethod() { |
|
| 315 | - if (isset(self::$method)) { |
|
| 316 | - return self::$method; |
|
| 317 | - } |
|
| 318 | - |
|
| 319 | - return self::UNKNOWN; |
|
| 320 | - } |
|
| 321 | - |
|
| 322 | - /** |
|
| 323 | - * Returns the value of the user parameter of the querystring. |
|
| 324 | - * |
|
| 325 | - * @return string/boolean false if not available |
|
| 326 | - */ |
|
| 327 | - public static function GetGETUser() { |
|
| 328 | - if (isset(self::$getUser)) { |
|
| 329 | - return self::$getUser; |
|
| 330 | - } |
|
| 331 | - |
|
| 332 | - return self::UNKNOWN; |
|
| 333 | - } |
|
| 334 | - |
|
| 335 | - /** |
|
| 336 | - * Returns the value of the ItemId parameter of the querystring. |
|
| 337 | - * |
|
| 338 | - * @return string/boolean false if not available |
|
| 339 | - */ |
|
| 340 | - public static function GetGETItemId() { |
|
| 341 | - if (isset(self::$itemId)) { |
|
| 342 | - return self::$itemId; |
|
| 343 | - } |
|
| 344 | - |
|
| 345 | - return false; |
|
| 346 | - } |
|
| 347 | - |
|
| 348 | - /** |
|
| 349 | - * Returns the value of the CollectionId parameter of the querystring. |
|
| 350 | - * |
|
| 351 | - * @return string/boolean false if not available |
|
| 352 | - */ |
|
| 353 | - public static function GetGETCollectionId() { |
|
| 354 | - if (isset(self::$collectionId)) { |
|
| 355 | - return self::$collectionId; |
|
| 356 | - } |
|
| 357 | - |
|
| 358 | - return false; |
|
| 359 | - } |
|
| 360 | - |
|
| 361 | - /** |
|
| 362 | - * Returns if the SaveInSent parameter of the querystring is set. |
|
| 363 | - * |
|
| 364 | - * @return bool |
|
| 365 | - */ |
|
| 366 | - public static function GetGETSaveInSent() { |
|
| 367 | - if (isset(self::$saveInSent)) { |
|
| 368 | - return self::$saveInSent; |
|
| 369 | - } |
|
| 370 | - |
|
| 371 | - return true; |
|
| 372 | - } |
|
| 373 | - |
|
| 374 | - /** |
|
| 375 | - * Returns if the AcceptMultipart parameter of the querystring is set. |
|
| 376 | - * |
|
| 377 | - * @return bool |
|
| 378 | - */ |
|
| 379 | - public static function GetGETAcceptMultipart() { |
|
| 380 | - if (isset(self::$acceptMultipart)) { |
|
| 381 | - return self::$acceptMultipart; |
|
| 382 | - } |
|
| 383 | - |
|
| 384 | - return false; |
|
| 385 | - } |
|
| 386 | - |
|
| 387 | - /** |
|
| 388 | - * Returns the value of the AttachmentName parameter of the querystring. |
|
| 389 | - * |
|
| 390 | - * @return string/boolean false if not available |
|
| 391 | - */ |
|
| 392 | - public static function GetGETAttachmentName() { |
|
| 393 | - if (isset(self::$attachmentName)) { |
|
| 394 | - return self::$attachmentName; |
|
| 395 | - } |
|
| 396 | - |
|
| 397 | - return false; |
|
| 398 | - } |
|
| 399 | - |
|
| 400 | - /** |
|
| 401 | - * Returns user that is synchronizing data. |
|
| 402 | - * If impersonation is active it returns the impersonated user, |
|
| 403 | - * else the auth user. |
|
| 404 | - * |
|
| 405 | - * @return string/boolean false if not available |
|
| 406 | - */ |
|
| 407 | - public static function GetUser() { |
|
| 408 | - if (self::GetImpersonatedUser()) { |
|
| 409 | - return self::GetImpersonatedUser(); |
|
| 410 | - } |
|
| 411 | - |
|
| 412 | - return self::GetAuthUser(); |
|
| 413 | - } |
|
| 414 | - |
|
| 415 | - /** |
|
| 416 | - * Returns the AuthUser string send by the client. |
|
| 417 | - * |
|
| 418 | - * @return string/boolean false if not available |
|
| 419 | - */ |
|
| 420 | - public static function GetAuthUserString() { |
|
| 421 | - if (isset(self::$authUserString)) { |
|
| 422 | - return self::$authUserString; |
|
| 423 | - } |
|
| 424 | - |
|
| 425 | - return false; |
|
| 426 | - } |
|
| 427 | - |
|
| 428 | - /** |
|
| 429 | - * Returns the impersonated user. If not available, returns false. |
|
| 430 | - * |
|
| 431 | - * @return string/boolean false if not available |
|
| 432 | - */ |
|
| 433 | - public static function GetImpersonatedUser() { |
|
| 434 | - if (isset(self::$impersonatedUser)) { |
|
| 435 | - return self::$impersonatedUser; |
|
| 436 | - } |
|
| 437 | - |
|
| 438 | - return false; |
|
| 439 | - } |
|
| 440 | - |
|
| 441 | - /** |
|
| 442 | - * Returns the authenticated user. |
|
| 443 | - * |
|
| 444 | - * @return string/boolean false if not available |
|
| 445 | - */ |
|
| 446 | - public static function GetAuthUser() { |
|
| 447 | - if (isset(self::$authUser)) { |
|
| 448 | - return self::$authUser; |
|
| 449 | - } |
|
| 450 | - |
|
| 451 | - return false; |
|
| 452 | - } |
|
| 453 | - |
|
| 454 | - /** |
|
| 455 | - * Returns the authenticated domain for the user. |
|
| 456 | - * |
|
| 457 | - * @return string/boolean false if not available |
|
| 458 | - */ |
|
| 459 | - public static function GetAuthDomain() { |
|
| 460 | - if (isset(self::$authDomain)) { |
|
| 461 | - return self::$authDomain; |
|
| 462 | - } |
|
| 463 | - |
|
| 464 | - return false; |
|
| 465 | - } |
|
| 466 | - |
|
| 467 | - /** |
|
| 468 | - * Returns the transmitted password. |
|
| 469 | - * |
|
| 470 | - * @return string/boolean false if not available |
|
| 471 | - */ |
|
| 472 | - public static function GetAuthPassword() { |
|
| 473 | - if (isset(self::$authPassword)) { |
|
| 474 | - return self::$authPassword; |
|
| 475 | - } |
|
| 476 | - |
|
| 477 | - return false; |
|
| 478 | - } |
|
| 479 | - |
|
| 480 | - /** |
|
| 481 | - * Returns the RemoteAddress. |
|
| 482 | - * |
|
| 483 | - * @return string |
|
| 484 | - */ |
|
| 485 | - public static function GetRemoteAddr() { |
|
| 486 | - if (isset(self::$remoteAddr)) { |
|
| 487 | - return self::$remoteAddr; |
|
| 488 | - } |
|
| 489 | - |
|
| 490 | - return "UNKNOWN"; |
|
| 491 | - } |
|
| 492 | - |
|
| 493 | - /** |
|
| 494 | - * Returns the command to be executed. |
|
| 495 | - * |
|
| 496 | - * @return string/boolean false if not available |
|
| 497 | - */ |
|
| 498 | - public static function GetCommand() { |
|
| 499 | - if (isset(self::$command)) { |
|
| 500 | - return self::$command; |
|
| 501 | - } |
|
| 502 | - |
|
| 503 | - return false; |
|
| 504 | - } |
|
| 505 | - |
|
| 506 | - /** |
|
| 507 | - * Returns the command code which is being executed. |
|
| 508 | - * |
|
| 509 | - * @return string/boolean false if not available |
|
| 510 | - */ |
|
| 511 | - public static function GetCommandCode() { |
|
| 512 | - if (isset(self::$command)) { |
|
| 513 | - return Utils::GetCodeFromCommand(self::$command); |
|
| 514 | - } |
|
| 515 | - |
|
| 516 | - return false; |
|
| 517 | - } |
|
| 518 | - |
|
| 519 | - /** |
|
| 520 | - * Returns the device id transmitted. |
|
| 521 | - * |
|
| 522 | - * @return string/boolean false if not available |
|
| 523 | - */ |
|
| 524 | - public static function GetDeviceID() { |
|
| 525 | - if (isset(self::$devid)) { |
|
| 526 | - return self::$devid; |
|
| 527 | - } |
|
| 528 | - |
|
| 529 | - return false; |
|
| 530 | - } |
|
| 531 | - |
|
| 532 | - /** |
|
| 533 | - * Returns the device type if transmitted. |
|
| 534 | - * |
|
| 535 | - * @return string/boolean false if not available |
|
| 536 | - */ |
|
| 537 | - public static function GetDeviceType() { |
|
| 538 | - if (isset(self::$devtype)) { |
|
| 539 | - return self::$devtype; |
|
| 540 | - } |
|
| 541 | - |
|
| 542 | - return false; |
|
| 543 | - } |
|
| 544 | - |
|
| 545 | - /** |
|
| 546 | - * Returns the value of supported AS protocol from the headers. |
|
| 547 | - * |
|
| 548 | - * @return string/boolean false if not available |
|
| 549 | - */ |
|
| 550 | - public static function GetProtocolVersion() { |
|
| 551 | - if (isset(self::$asProtocolVersion)) { |
|
| 552 | - return self::$asProtocolVersion; |
|
| 553 | - } |
|
| 554 | - |
|
| 555 | - return false; |
|
| 556 | - } |
|
| 557 | - |
|
| 558 | - /** |
|
| 559 | - * Returns the user agent sent in the headers. |
|
| 560 | - * |
|
| 561 | - * @return string/boolean false if not available |
|
| 562 | - */ |
|
| 563 | - public static function GetUserAgent() { |
|
| 564 | - if (isset(self::$useragent)) { |
|
| 565 | - return self::$useragent; |
|
| 566 | - } |
|
| 567 | - |
|
| 568 | - return self::UNKNOWN; |
|
| 569 | - } |
|
| 570 | - |
|
| 571 | - /** |
|
| 572 | - * Returns policy key sent by the device. |
|
| 573 | - * |
|
| 574 | - * @return int/boolean false if not available |
|
| 575 | - */ |
|
| 576 | - public static function GetPolicyKey() { |
|
| 577 | - if (isset(self::$policykey)) { |
|
| 578 | - return self::$policykey; |
|
| 579 | - } |
|
| 580 | - |
|
| 581 | - return false; |
|
| 582 | - } |
|
| 583 | - |
|
| 584 | - /** |
|
| 585 | - * Indicates if a policy key was sent by the device. |
|
| 586 | - * |
|
| 587 | - * @return bool |
|
| 588 | - */ |
|
| 589 | - public static function WasPolicyKeySent() { |
|
| 590 | - return isset(self::$headers["x-ms-policykey"]); |
|
| 591 | - } |
|
| 592 | - |
|
| 593 | - /** |
|
| 594 | - * Indicates if grommunio-sync was called with a POST request. |
|
| 595 | - * |
|
| 596 | - * @return bool |
|
| 597 | - */ |
|
| 598 | - public static function IsMethodPOST() { |
|
| 599 | - return self::$method == "POST"; |
|
| 600 | - } |
|
| 601 | - |
|
| 602 | - /** |
|
| 603 | - * Indicates if grommunio-sync was called with a GET request. |
|
| 604 | - * |
|
| 605 | - * @return bool |
|
| 606 | - */ |
|
| 607 | - public static function IsMethodGET() { |
|
| 608 | - return self::$method == "GET"; |
|
| 609 | - } |
|
| 610 | - |
|
| 611 | - /** |
|
| 612 | - * Indicates if grommunio-sync was called with a OPTIONS request. |
|
| 613 | - * |
|
| 614 | - * @return bool |
|
| 615 | - */ |
|
| 616 | - public static function IsMethodOPTIONS() { |
|
| 617 | - return self::$method == "OPTIONS"; |
|
| 618 | - } |
|
| 619 | - |
|
| 620 | - /** |
|
| 621 | - * Sometimes strange device ids are submitted |
|
| 622 | - * No device information should be saved when this happens. |
|
| 623 | - * |
|
| 624 | - * @return bool false if invalid |
|
| 625 | - */ |
|
| 626 | - public static function IsValidDeviceID() { |
|
| 627 | - if (self::GetDeviceID() === "validate") { |
|
| 628 | - return false; |
|
| 629 | - } |
|
| 630 | - |
|
| 631 | - return true; |
|
| 632 | - } |
|
| 633 | - |
|
| 634 | - /** |
|
| 635 | - * Returns the amount of data sent in this request (from the headers). |
|
| 636 | - * |
|
| 637 | - * @return int |
|
| 638 | - */ |
|
| 639 | - public static function GetContentLength() { |
|
| 640 | - return (isset(self::$headers["content-length"])) ? (int) self::$headers["content-length"] : 0; |
|
| 641 | - } |
|
| 642 | - |
|
| 643 | - /** |
|
| 644 | - * Returns the amount of seconds this request is able to be kept open without the client |
|
| 645 | - * closing it. This depends on the vendor. |
|
| 646 | - * |
|
| 647 | - * @return bool |
|
| 648 | - */ |
|
| 649 | - public static function GetExpectedConnectionTimeout() { |
|
| 650 | - // Different vendors implement different connection timeouts. |
|
| 651 | - // In order to optimize processing, we return a specific time for the major |
|
| 652 | - // classes currently known (feedback welcome). |
|
| 653 | - // The amount of time returned is somehow lower than the max timeout so we have |
|
| 654 | - // time for processing. |
|
| 655 | - |
|
| 656 | - if (!isset(self::$expectedConnectionTimeout)) { |
|
| 657 | - // Apple and Windows Phone have higher timeouts (4min = 240sec) |
|
| 658 | - if (stripos(SYNC_TIMEOUT_LONG_DEVICETYPES, self::GetDeviceType()) !== false) { |
|
| 659 | - self::$expectedConnectionTimeout = 210; |
|
| 660 | - } |
|
| 661 | - // Samsung devices have a intermediate timeout (90sec) |
|
| 662 | - elseif (stripos(SYNC_TIMEOUT_MEDIUM_DEVICETYPES, self::GetDeviceType()) !== false) { |
|
| 663 | - self::$expectedConnectionTimeout = 85; |
|
| 664 | - } |
|
| 665 | - else { |
|
| 666 | - // for all other devices, a timeout of 30 seconds is expected |
|
| 667 | - self::$expectedConnectionTimeout = 28; |
|
| 668 | - } |
|
| 669 | - } |
|
| 670 | - |
|
| 671 | - return self::$expectedConnectionTimeout; |
|
| 672 | - } |
|
| 673 | - |
|
| 674 | - /** |
|
| 675 | - * Indicates if the maximum timeout for the devicetype of this request is |
|
| 676 | - * almost reached. |
|
| 677 | - * |
|
| 678 | - * @return bool |
|
| 679 | - */ |
|
| 680 | - public static function IsRequestTimeoutReached() { |
|
| 681 | - return (time() - $_SERVER["REQUEST_TIME"]) >= self::GetExpectedConnectionTimeout(); |
|
| 682 | - } |
|
| 683 | - |
|
| 684 | - /** |
|
| 685 | - * Indicates if the memory usage limit is almost reached. |
|
| 686 | - * Processing should stop then to prevent hard out-of-memory issues. |
|
| 687 | - * The threshold is hardcoded at 90% in Request::MAXMEMORYUSAGE. |
|
| 688 | - * |
|
| 689 | - * @return bool |
|
| 690 | - */ |
|
| 691 | - public static function IsRequestMemoryLimitReached() { |
|
| 692 | - if (self::$memoryLimit === false) { |
|
| 693 | - return false; |
|
| 694 | - } |
|
| 695 | - |
|
| 696 | - return memory_get_peak_usage(true) >= self::$memoryLimit; |
|
| 697 | - } |
|
| 698 | - |
|
| 699 | - /*---------------------------------------------------------------------------------------------------------- |
|
| 283 | + /** |
|
| 284 | + * Returns the input stream. |
|
| 285 | + * |
|
| 286 | + * @return handle/boolean false if not available |
|
| 287 | + */ |
|
| 288 | + public static function GetInputStream() { |
|
| 289 | + if (isset(self::$input)) { |
|
| 290 | + return self::$input; |
|
| 291 | + } |
|
| 292 | + |
|
| 293 | + return false; |
|
| 294 | + } |
|
| 295 | + |
|
| 296 | + /** |
|
| 297 | + * Returns the output stream. |
|
| 298 | + * |
|
| 299 | + * @return handle/boolean false if not available |
|
| 300 | + */ |
|
| 301 | + public static function GetOutputStream() { |
|
| 302 | + if (isset(self::$output)) { |
|
| 303 | + return self::$output; |
|
| 304 | + } |
|
| 305 | + |
|
| 306 | + return false; |
|
| 307 | + } |
|
| 308 | + |
|
| 309 | + /** |
|
| 310 | + * Returns the request method. |
|
| 311 | + * |
|
| 312 | + * @return string |
|
| 313 | + */ |
|
| 314 | + public static function GetMethod() { |
|
| 315 | + if (isset(self::$method)) { |
|
| 316 | + return self::$method; |
|
| 317 | + } |
|
| 318 | + |
|
| 319 | + return self::UNKNOWN; |
|
| 320 | + } |
|
| 321 | + |
|
| 322 | + /** |
|
| 323 | + * Returns the value of the user parameter of the querystring. |
|
| 324 | + * |
|
| 325 | + * @return string/boolean false if not available |
|
| 326 | + */ |
|
| 327 | + public static function GetGETUser() { |
|
| 328 | + if (isset(self::$getUser)) { |
|
| 329 | + return self::$getUser; |
|
| 330 | + } |
|
| 331 | + |
|
| 332 | + return self::UNKNOWN; |
|
| 333 | + } |
|
| 334 | + |
|
| 335 | + /** |
|
| 336 | + * Returns the value of the ItemId parameter of the querystring. |
|
| 337 | + * |
|
| 338 | + * @return string/boolean false if not available |
|
| 339 | + */ |
|
| 340 | + public static function GetGETItemId() { |
|
| 341 | + if (isset(self::$itemId)) { |
|
| 342 | + return self::$itemId; |
|
| 343 | + } |
|
| 344 | + |
|
| 345 | + return false; |
|
| 346 | + } |
|
| 347 | + |
|
| 348 | + /** |
|
| 349 | + * Returns the value of the CollectionId parameter of the querystring. |
|
| 350 | + * |
|
| 351 | + * @return string/boolean false if not available |
|
| 352 | + */ |
|
| 353 | + public static function GetGETCollectionId() { |
|
| 354 | + if (isset(self::$collectionId)) { |
|
| 355 | + return self::$collectionId; |
|
| 356 | + } |
|
| 357 | + |
|
| 358 | + return false; |
|
| 359 | + } |
|
| 360 | + |
|
| 361 | + /** |
|
| 362 | + * Returns if the SaveInSent parameter of the querystring is set. |
|
| 363 | + * |
|
| 364 | + * @return bool |
|
| 365 | + */ |
|
| 366 | + public static function GetGETSaveInSent() { |
|
| 367 | + if (isset(self::$saveInSent)) { |
|
| 368 | + return self::$saveInSent; |
|
| 369 | + } |
|
| 370 | + |
|
| 371 | + return true; |
|
| 372 | + } |
|
| 373 | + |
|
| 374 | + /** |
|
| 375 | + * Returns if the AcceptMultipart parameter of the querystring is set. |
|
| 376 | + * |
|
| 377 | + * @return bool |
|
| 378 | + */ |
|
| 379 | + public static function GetGETAcceptMultipart() { |
|
| 380 | + if (isset(self::$acceptMultipart)) { |
|
| 381 | + return self::$acceptMultipart; |
|
| 382 | + } |
|
| 383 | + |
|
| 384 | + return false; |
|
| 385 | + } |
|
| 386 | + |
|
| 387 | + /** |
|
| 388 | + * Returns the value of the AttachmentName parameter of the querystring. |
|
| 389 | + * |
|
| 390 | + * @return string/boolean false if not available |
|
| 391 | + */ |
|
| 392 | + public static function GetGETAttachmentName() { |
|
| 393 | + if (isset(self::$attachmentName)) { |
|
| 394 | + return self::$attachmentName; |
|
| 395 | + } |
|
| 396 | + |
|
| 397 | + return false; |
|
| 398 | + } |
|
| 399 | + |
|
| 400 | + /** |
|
| 401 | + * Returns user that is synchronizing data. |
|
| 402 | + * If impersonation is active it returns the impersonated user, |
|
| 403 | + * else the auth user. |
|
| 404 | + * |
|
| 405 | + * @return string/boolean false if not available |
|
| 406 | + */ |
|
| 407 | + public static function GetUser() { |
|
| 408 | + if (self::GetImpersonatedUser()) { |
|
| 409 | + return self::GetImpersonatedUser(); |
|
| 410 | + } |
|
| 411 | + |
|
| 412 | + return self::GetAuthUser(); |
|
| 413 | + } |
|
| 414 | + |
|
| 415 | + /** |
|
| 416 | + * Returns the AuthUser string send by the client. |
|
| 417 | + * |
|
| 418 | + * @return string/boolean false if not available |
|
| 419 | + */ |
|
| 420 | + public static function GetAuthUserString() { |
|
| 421 | + if (isset(self::$authUserString)) { |
|
| 422 | + return self::$authUserString; |
|
| 423 | + } |
|
| 424 | + |
|
| 425 | + return false; |
|
| 426 | + } |
|
| 427 | + |
|
| 428 | + /** |
|
| 429 | + * Returns the impersonated user. If not available, returns false. |
|
| 430 | + * |
|
| 431 | + * @return string/boolean false if not available |
|
| 432 | + */ |
|
| 433 | + public static function GetImpersonatedUser() { |
|
| 434 | + if (isset(self::$impersonatedUser)) { |
|
| 435 | + return self::$impersonatedUser; |
|
| 436 | + } |
|
| 437 | + |
|
| 438 | + return false; |
|
| 439 | + } |
|
| 440 | + |
|
| 441 | + /** |
|
| 442 | + * Returns the authenticated user. |
|
| 443 | + * |
|
| 444 | + * @return string/boolean false if not available |
|
| 445 | + */ |
|
| 446 | + public static function GetAuthUser() { |
|
| 447 | + if (isset(self::$authUser)) { |
|
| 448 | + return self::$authUser; |
|
| 449 | + } |
|
| 450 | + |
|
| 451 | + return false; |
|
| 452 | + } |
|
| 453 | + |
|
| 454 | + /** |
|
| 455 | + * Returns the authenticated domain for the user. |
|
| 456 | + * |
|
| 457 | + * @return string/boolean false if not available |
|
| 458 | + */ |
|
| 459 | + public static function GetAuthDomain() { |
|
| 460 | + if (isset(self::$authDomain)) { |
|
| 461 | + return self::$authDomain; |
|
| 462 | + } |
|
| 463 | + |
|
| 464 | + return false; |
|
| 465 | + } |
|
| 466 | + |
|
| 467 | + /** |
|
| 468 | + * Returns the transmitted password. |
|
| 469 | + * |
|
| 470 | + * @return string/boolean false if not available |
|
| 471 | + */ |
|
| 472 | + public static function GetAuthPassword() { |
|
| 473 | + if (isset(self::$authPassword)) { |
|
| 474 | + return self::$authPassword; |
|
| 475 | + } |
|
| 476 | + |
|
| 477 | + return false; |
|
| 478 | + } |
|
| 479 | + |
|
| 480 | + /** |
|
| 481 | + * Returns the RemoteAddress. |
|
| 482 | + * |
|
| 483 | + * @return string |
|
| 484 | + */ |
|
| 485 | + public static function GetRemoteAddr() { |
|
| 486 | + if (isset(self::$remoteAddr)) { |
|
| 487 | + return self::$remoteAddr; |
|
| 488 | + } |
|
| 489 | + |
|
| 490 | + return "UNKNOWN"; |
|
| 491 | + } |
|
| 492 | + |
|
| 493 | + /** |
|
| 494 | + * Returns the command to be executed. |
|
| 495 | + * |
|
| 496 | + * @return string/boolean false if not available |
|
| 497 | + */ |
|
| 498 | + public static function GetCommand() { |
|
| 499 | + if (isset(self::$command)) { |
|
| 500 | + return self::$command; |
|
| 501 | + } |
|
| 502 | + |
|
| 503 | + return false; |
|
| 504 | + } |
|
| 505 | + |
|
| 506 | + /** |
|
| 507 | + * Returns the command code which is being executed. |
|
| 508 | + * |
|
| 509 | + * @return string/boolean false if not available |
|
| 510 | + */ |
|
| 511 | + public static function GetCommandCode() { |
|
| 512 | + if (isset(self::$command)) { |
|
| 513 | + return Utils::GetCodeFromCommand(self::$command); |
|
| 514 | + } |
|
| 515 | + |
|
| 516 | + return false; |
|
| 517 | + } |
|
| 518 | + |
|
| 519 | + /** |
|
| 520 | + * Returns the device id transmitted. |
|
| 521 | + * |
|
| 522 | + * @return string/boolean false if not available |
|
| 523 | + */ |
|
| 524 | + public static function GetDeviceID() { |
|
| 525 | + if (isset(self::$devid)) { |
|
| 526 | + return self::$devid; |
|
| 527 | + } |
|
| 528 | + |
|
| 529 | + return false; |
|
| 530 | + } |
|
| 531 | + |
|
| 532 | + /** |
|
| 533 | + * Returns the device type if transmitted. |
|
| 534 | + * |
|
| 535 | + * @return string/boolean false if not available |
|
| 536 | + */ |
|
| 537 | + public static function GetDeviceType() { |
|
| 538 | + if (isset(self::$devtype)) { |
|
| 539 | + return self::$devtype; |
|
| 540 | + } |
|
| 541 | + |
|
| 542 | + return false; |
|
| 543 | + } |
|
| 544 | + |
|
| 545 | + /** |
|
| 546 | + * Returns the value of supported AS protocol from the headers. |
|
| 547 | + * |
|
| 548 | + * @return string/boolean false if not available |
|
| 549 | + */ |
|
| 550 | + public static function GetProtocolVersion() { |
|
| 551 | + if (isset(self::$asProtocolVersion)) { |
|
| 552 | + return self::$asProtocolVersion; |
|
| 553 | + } |
|
| 554 | + |
|
| 555 | + return false; |
|
| 556 | + } |
|
| 557 | + |
|
| 558 | + /** |
|
| 559 | + * Returns the user agent sent in the headers. |
|
| 560 | + * |
|
| 561 | + * @return string/boolean false if not available |
|
| 562 | + */ |
|
| 563 | + public static function GetUserAgent() { |
|
| 564 | + if (isset(self::$useragent)) { |
|
| 565 | + return self::$useragent; |
|
| 566 | + } |
|
| 567 | + |
|
| 568 | + return self::UNKNOWN; |
|
| 569 | + } |
|
| 570 | + |
|
| 571 | + /** |
|
| 572 | + * Returns policy key sent by the device. |
|
| 573 | + * |
|
| 574 | + * @return int/boolean false if not available |
|
| 575 | + */ |
|
| 576 | + public static function GetPolicyKey() { |
|
| 577 | + if (isset(self::$policykey)) { |
|
| 578 | + return self::$policykey; |
|
| 579 | + } |
|
| 580 | + |
|
| 581 | + return false; |
|
| 582 | + } |
|
| 583 | + |
|
| 584 | + /** |
|
| 585 | + * Indicates if a policy key was sent by the device. |
|
| 586 | + * |
|
| 587 | + * @return bool |
|
| 588 | + */ |
|
| 589 | + public static function WasPolicyKeySent() { |
|
| 590 | + return isset(self::$headers["x-ms-policykey"]); |
|
| 591 | + } |
|
| 592 | + |
|
| 593 | + /** |
|
| 594 | + * Indicates if grommunio-sync was called with a POST request. |
|
| 595 | + * |
|
| 596 | + * @return bool |
|
| 597 | + */ |
|
| 598 | + public static function IsMethodPOST() { |
|
| 599 | + return self::$method == "POST"; |
|
| 600 | + } |
|
| 601 | + |
|
| 602 | + /** |
|
| 603 | + * Indicates if grommunio-sync was called with a GET request. |
|
| 604 | + * |
|
| 605 | + * @return bool |
|
| 606 | + */ |
|
| 607 | + public static function IsMethodGET() { |
|
| 608 | + return self::$method == "GET"; |
|
| 609 | + } |
|
| 610 | + |
|
| 611 | + /** |
|
| 612 | + * Indicates if grommunio-sync was called with a OPTIONS request. |
|
| 613 | + * |
|
| 614 | + * @return bool |
|
| 615 | + */ |
|
| 616 | + public static function IsMethodOPTIONS() { |
|
| 617 | + return self::$method == "OPTIONS"; |
|
| 618 | + } |
|
| 619 | + |
|
| 620 | + /** |
|
| 621 | + * Sometimes strange device ids are submitted |
|
| 622 | + * No device information should be saved when this happens. |
|
| 623 | + * |
|
| 624 | + * @return bool false if invalid |
|
| 625 | + */ |
|
| 626 | + public static function IsValidDeviceID() { |
|
| 627 | + if (self::GetDeviceID() === "validate") { |
|
| 628 | + return false; |
|
| 629 | + } |
|
| 630 | + |
|
| 631 | + return true; |
|
| 632 | + } |
|
| 633 | + |
|
| 634 | + /** |
|
| 635 | + * Returns the amount of data sent in this request (from the headers). |
|
| 636 | + * |
|
| 637 | + * @return int |
|
| 638 | + */ |
|
| 639 | + public static function GetContentLength() { |
|
| 640 | + return (isset(self::$headers["content-length"])) ? (int) self::$headers["content-length"] : 0; |
|
| 641 | + } |
|
| 642 | + |
|
| 643 | + /** |
|
| 644 | + * Returns the amount of seconds this request is able to be kept open without the client |
|
| 645 | + * closing it. This depends on the vendor. |
|
| 646 | + * |
|
| 647 | + * @return bool |
|
| 648 | + */ |
|
| 649 | + public static function GetExpectedConnectionTimeout() { |
|
| 650 | + // Different vendors implement different connection timeouts. |
|
| 651 | + // In order to optimize processing, we return a specific time for the major |
|
| 652 | + // classes currently known (feedback welcome). |
|
| 653 | + // The amount of time returned is somehow lower than the max timeout so we have |
|
| 654 | + // time for processing. |
|
| 655 | + |
|
| 656 | + if (!isset(self::$expectedConnectionTimeout)) { |
|
| 657 | + // Apple and Windows Phone have higher timeouts (4min = 240sec) |
|
| 658 | + if (stripos(SYNC_TIMEOUT_LONG_DEVICETYPES, self::GetDeviceType()) !== false) { |
|
| 659 | + self::$expectedConnectionTimeout = 210; |
|
| 660 | + } |
|
| 661 | + // Samsung devices have a intermediate timeout (90sec) |
|
| 662 | + elseif (stripos(SYNC_TIMEOUT_MEDIUM_DEVICETYPES, self::GetDeviceType()) !== false) { |
|
| 663 | + self::$expectedConnectionTimeout = 85; |
|
| 664 | + } |
|
| 665 | + else { |
|
| 666 | + // for all other devices, a timeout of 30 seconds is expected |
|
| 667 | + self::$expectedConnectionTimeout = 28; |
|
| 668 | + } |
|
| 669 | + } |
|
| 670 | + |
|
| 671 | + return self::$expectedConnectionTimeout; |
|
| 672 | + } |
|
| 673 | + |
|
| 674 | + /** |
|
| 675 | + * Indicates if the maximum timeout for the devicetype of this request is |
|
| 676 | + * almost reached. |
|
| 677 | + * |
|
| 678 | + * @return bool |
|
| 679 | + */ |
|
| 680 | + public static function IsRequestTimeoutReached() { |
|
| 681 | + return (time() - $_SERVER["REQUEST_TIME"]) >= self::GetExpectedConnectionTimeout(); |
|
| 682 | + } |
|
| 683 | + |
|
| 684 | + /** |
|
| 685 | + * Indicates if the memory usage limit is almost reached. |
|
| 686 | + * Processing should stop then to prevent hard out-of-memory issues. |
|
| 687 | + * The threshold is hardcoded at 90% in Request::MAXMEMORYUSAGE. |
|
| 688 | + * |
|
| 689 | + * @return bool |
|
| 690 | + */ |
|
| 691 | + public static function IsRequestMemoryLimitReached() { |
|
| 692 | + if (self::$memoryLimit === false) { |
|
| 693 | + return false; |
|
| 694 | + } |
|
| 695 | + |
|
| 696 | + return memory_get_peak_usage(true) >= self::$memoryLimit; |
|
| 697 | + } |
|
| 698 | + |
|
| 699 | + /*---------------------------------------------------------------------------------------------------------- |
|
| 700 | 700 | * Private stuff |
| 701 | 701 | */ |
| 702 | 702 | |
| 703 | - /** |
|
| 704 | - * Replaces all not allowed characters in a string. |
|
| 705 | - * |
|
| 706 | - * @param string $input the input string |
|
| 707 | - * @param int $filter one of the predefined filters: LETTERS_ONLY, HEX_ONLY, WORDCHAR_ONLY, NUMBERS_ONLY, NUMBERSDOT_ONLY |
|
| 708 | - * @param char $replacevalue (opt) a character the filtered characters should be replaced with |
|
| 709 | - * |
|
| 710 | - * @return string |
|
| 711 | - */ |
|
| 712 | - private static function filterEvilInput($input, $filter, $replacevalue = '') { |
|
| 713 | - $re = false; |
|
| 714 | - if ($filter == self::LETTERS_ONLY) { |
|
| 715 | - $re = "/[^A-Za-z]/"; |
|
| 716 | - } |
|
| 717 | - elseif ($filter == self::HEX_ONLY) { |
|
| 718 | - $re = "/[^A-Fa-f0-9]/"; |
|
| 719 | - } |
|
| 720 | - elseif ($filter == self::WORDCHAR_ONLY) { |
|
| 721 | - $re = "/[^A-Za-z0-9]/"; |
|
| 722 | - } |
|
| 723 | - elseif ($filter == self::NUMBERS_ONLY) { |
|
| 724 | - $re = "/[^0-9]/"; |
|
| 725 | - } |
|
| 726 | - elseif ($filter == self::NUMBERSDOT_ONLY) { |
|
| 727 | - $re = "/[^0-9\\.]/"; |
|
| 728 | - } |
|
| 729 | - elseif ($filter == self::HEX_EXTENDED) { |
|
| 730 | - $re = "/[^A-Fa-f0-9\\:\\.]/"; |
|
| 731 | - } |
|
| 732 | - elseif ($filter == self::HEX_EXTENDED2) { |
|
| 733 | - $re = "/[^A-Fa-f0-9\\:USGI]/"; |
|
| 734 | - } // Folder origin constants from DeviceManager::FLD_ORIGIN_* (C already hex) |
|
| 735 | - elseif ($filter == self::ISO8601) { |
|
| 736 | - $re = "/[^\\d{8}T\\d{6}Z]/"; |
|
| 737 | - } |
|
| 738 | - |
|
| 739 | - return ($re) ? preg_replace($re, $replacevalue, $input) : ''; |
|
| 740 | - } |
|
| 741 | - |
|
| 742 | - /** |
|
| 743 | - * If $input is a valid IPv4 or IPv6 address, returns a valid compact IPv4 or IPv6 address string. |
|
| 744 | - * Otherwise, it will strip all characters that are neither numerical or '.' and prefix with "bad-ip". |
|
| 745 | - * |
|
| 746 | - * @param string $input The ipv4/ipv6 address |
|
| 747 | - * |
|
| 748 | - * @return string |
|
| 749 | - */ |
|
| 750 | - private static function filterIP($input) { |
|
| 751 | - $in_addr = @inet_pton($input); |
|
| 752 | - if ($in_addr === false) { |
|
| 753 | - return 'badip-' . self::filterEvilInput($input, self::HEX_EXTENDED); |
|
| 754 | - } |
|
| 755 | - |
|
| 756 | - return inet_ntop($in_addr); |
|
| 757 | - } |
|
| 758 | - |
|
| 759 | - /** |
|
| 760 | - * Returns base64 encoded "php://input" |
|
| 761 | - * With POST request (our case), you can open and read |
|
| 762 | - * multiple times "php://input". |
|
| 763 | - * |
|
| 764 | - * @param int $maxLength max. length to be returned. Default: return all |
|
| 765 | - * |
|
| 766 | - * @return string - base64 encoded wbxml |
|
| 767 | - */ |
|
| 768 | - public static function GetInputAsBase64($maxLength = -1) { |
|
| 769 | - $input = fopen('php://input', 'r'); |
|
| 770 | - $wbxml = base64_encode(stream_get_contents($input, $maxLength)); |
|
| 771 | - fclose($input); |
|
| 772 | - |
|
| 773 | - return $wbxml; |
|
| 774 | - } |
|
| 775 | - |
|
| 776 | - /** |
|
| 777 | - * Decodes base64 encoded query parameters. Based on dw2412 contribution. |
|
| 778 | - */ |
|
| 779 | - private static function decodeBase64URI() { |
|
| 780 | - /* |
|
| 703 | + /** |
|
| 704 | + * Replaces all not allowed characters in a string. |
|
| 705 | + * |
|
| 706 | + * @param string $input the input string |
|
| 707 | + * @param int $filter one of the predefined filters: LETTERS_ONLY, HEX_ONLY, WORDCHAR_ONLY, NUMBERS_ONLY, NUMBERSDOT_ONLY |
|
| 708 | + * @param char $replacevalue (opt) a character the filtered characters should be replaced with |
|
| 709 | + * |
|
| 710 | + * @return string |
|
| 711 | + */ |
|
| 712 | + private static function filterEvilInput($input, $filter, $replacevalue = '') { |
|
| 713 | + $re = false; |
|
| 714 | + if ($filter == self::LETTERS_ONLY) { |
|
| 715 | + $re = "/[^A-Za-z]/"; |
|
| 716 | + } |
|
| 717 | + elseif ($filter == self::HEX_ONLY) { |
|
| 718 | + $re = "/[^A-Fa-f0-9]/"; |
|
| 719 | + } |
|
| 720 | + elseif ($filter == self::WORDCHAR_ONLY) { |
|
| 721 | + $re = "/[^A-Za-z0-9]/"; |
|
| 722 | + } |
|
| 723 | + elseif ($filter == self::NUMBERS_ONLY) { |
|
| 724 | + $re = "/[^0-9]/"; |
|
| 725 | + } |
|
| 726 | + elseif ($filter == self::NUMBERSDOT_ONLY) { |
|
| 727 | + $re = "/[^0-9\\.]/"; |
|
| 728 | + } |
|
| 729 | + elseif ($filter == self::HEX_EXTENDED) { |
|
| 730 | + $re = "/[^A-Fa-f0-9\\:\\.]/"; |
|
| 731 | + } |
|
| 732 | + elseif ($filter == self::HEX_EXTENDED2) { |
|
| 733 | + $re = "/[^A-Fa-f0-9\\:USGI]/"; |
|
| 734 | + } // Folder origin constants from DeviceManager::FLD_ORIGIN_* (C already hex) |
|
| 735 | + elseif ($filter == self::ISO8601) { |
|
| 736 | + $re = "/[^\\d{8}T\\d{6}Z]/"; |
|
| 737 | + } |
|
| 738 | + |
|
| 739 | + return ($re) ? preg_replace($re, $replacevalue, $input) : ''; |
|
| 740 | + } |
|
| 741 | + |
|
| 742 | + /** |
|
| 743 | + * If $input is a valid IPv4 or IPv6 address, returns a valid compact IPv4 or IPv6 address string. |
|
| 744 | + * Otherwise, it will strip all characters that are neither numerical or '.' and prefix with "bad-ip". |
|
| 745 | + * |
|
| 746 | + * @param string $input The ipv4/ipv6 address |
|
| 747 | + * |
|
| 748 | + * @return string |
|
| 749 | + */ |
|
| 750 | + private static function filterIP($input) { |
|
| 751 | + $in_addr = @inet_pton($input); |
|
| 752 | + if ($in_addr === false) { |
|
| 753 | + return 'badip-' . self::filterEvilInput($input, self::HEX_EXTENDED); |
|
| 754 | + } |
|
| 755 | + |
|
| 756 | + return inet_ntop($in_addr); |
|
| 757 | + } |
|
| 758 | + |
|
| 759 | + /** |
|
| 760 | + * Returns base64 encoded "php://input" |
|
| 761 | + * With POST request (our case), you can open and read |
|
| 762 | + * multiple times "php://input". |
|
| 763 | + * |
|
| 764 | + * @param int $maxLength max. length to be returned. Default: return all |
|
| 765 | + * |
|
| 766 | + * @return string - base64 encoded wbxml |
|
| 767 | + */ |
|
| 768 | + public static function GetInputAsBase64($maxLength = -1) { |
|
| 769 | + $input = fopen('php://input', 'r'); |
|
| 770 | + $wbxml = base64_encode(stream_get_contents($input, $maxLength)); |
|
| 771 | + fclose($input); |
|
| 772 | + |
|
| 773 | + return $wbxml; |
|
| 774 | + } |
|
| 775 | + |
|
| 776 | + /** |
|
| 777 | + * Decodes base64 encoded query parameters. Based on dw2412 contribution. |
|
| 778 | + */ |
|
| 779 | + private static function decodeBase64URI() { |
|
| 780 | + /* |
|
| 781 | 781 | * The query string has a following structure. Number in () is position: |
| 782 | 782 | * 1 byte - protocol version (0) |
| 783 | 783 | * 1 byte - command code (1) |
@@ -794,22 +794,22 @@ discard block |
||
| 794 | 794 | * variable - value of the parameter |
| 795 | 795 | * |
| 796 | 796 | */ |
| 797 | - $decoded = base64_decode($_SERVER['QUERY_STRING']); |
|
| 798 | - $devIdLength = ord($decoded[4]); // device ID length |
|
| 799 | - $polKeyLength = ord($decoded[5 + $devIdLength]); // policy key length |
|
| 800 | - $devTypeLength = ord($decoded[6 + $devIdLength + $polKeyLength]); // device type length |
|
| 801 | - // unpack the decoded query string values |
|
| 802 | - self::$base64QueryDecoded = unpack("CProtVer/CCommand/vLocale/CDevIDLen/H" . ($devIdLength * 2) . "DevID/CPolKeyLen" . ($polKeyLength == 4 ? "/VPolKey" : "") . "/CDevTypeLen/A" . ($devTypeLength) . "DevType", $decoded); |
|
| 803 | - |
|
| 804 | - // get the command parameters |
|
| 805 | - $pos = 7 + $devIdLength + $polKeyLength + $devTypeLength; |
|
| 806 | - $decoded = substr($decoded, $pos); |
|
| 807 | - while (strlen($decoded) > 0) { |
|
| 808 | - $paramLength = ord($decoded[1]); |
|
| 809 | - $unpackedParam = unpack("CParamTag/CParamLength/A" . $paramLength . "ParamValue", $decoded); |
|
| 810 | - self::$base64QueryDecoded[ord($decoded[0])] = $unpackedParam['ParamValue']; |
|
| 811 | - // remove parameter from decoded query string |
|
| 812 | - $decoded = substr($decoded, 2 + $paramLength); |
|
| 813 | - } |
|
| 814 | - } |
|
| 797 | + $decoded = base64_decode($_SERVER['QUERY_STRING']); |
|
| 798 | + $devIdLength = ord($decoded[4]); // device ID length |
|
| 799 | + $polKeyLength = ord($decoded[5 + $devIdLength]); // policy key length |
|
| 800 | + $devTypeLength = ord($decoded[6 + $devIdLength + $polKeyLength]); // device type length |
|
| 801 | + // unpack the decoded query string values |
|
| 802 | + self::$base64QueryDecoded = unpack("CProtVer/CCommand/vLocale/CDevIDLen/H" . ($devIdLength * 2) . "DevID/CPolKeyLen" . ($polKeyLength == 4 ? "/VPolKey" : "") . "/CDevTypeLen/A" . ($devTypeLength) . "DevType", $decoded); |
|
| 803 | + |
|
| 804 | + // get the command parameters |
|
| 805 | + $pos = 7 + $devIdLength + $polKeyLength + $devTypeLength; |
|
| 806 | + $decoded = substr($decoded, $pos); |
|
| 807 | + while (strlen($decoded) > 0) { |
|
| 808 | + $paramLength = ord($decoded[1]); |
|
| 809 | + $unpackedParam = unpack("CParamTag/CParamLength/A" . $paramLength . "ParamValue", $decoded); |
|
| 810 | + self::$base64QueryDecoded[ord($decoded[0])] = $unpackedParam['ParamValue']; |
|
| 811 | + // remove parameter from decoded query string |
|
| 812 | + $decoded = substr($decoded, 2 + $paramLength); |
|
| 813 | + } |
|
| 814 | + } |
|
| 815 | 815 | } |
@@ -8,7 +8,7 @@ discard block |
||
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | 10 | class Request { |
| 11 | - public const MAXMEMORYUSAGE = 0.9; // use max. 90% of allowed memory when syncing |
|
| 11 | + public const MAXMEMORYUSAGE = 0.9; // use max. 90% of allowed memory when syncing |
|
| 12 | 12 | public const UNKNOWN = "unknown"; |
| 13 | 13 | public const IMPERSONATE_DELIM = '#'; |
| 14 | 14 | |
@@ -140,7 +140,7 @@ discard block |
||
| 140 | 140 | } |
| 141 | 141 | |
| 142 | 142 | if (isset(self::$base64QueryDecoded['PolKey'])) { |
| 143 | - self::$policykey = (int) self::filterEvilInput(self::$base64QueryDecoded['PolKey'], self::NUMBERS_ONLY); |
|
| 143 | + self::$policykey = (int)self::filterEvilInput(self::$base64QueryDecoded['PolKey'], self::NUMBERS_ONLY); |
|
| 144 | 144 | } |
| 145 | 145 | |
| 146 | 146 | if (isset(self::$base64QueryDecoded['ProtVer'])) { |
@@ -198,7 +198,7 @@ discard block |
||
| 198 | 198 | else { |
| 199 | 199 | preg_replace_callback( |
| 200 | 200 | '/(\-?\d+)(.?)/', |
| 201 | - function ($m) { |
|
| 201 | + function($m) { |
|
| 202 | 202 | self::$memoryLimit = $m[1] * pow(1024, strpos('BKMG', $m[2])) * self::MAXMEMORYUSAGE; |
| 203 | 203 | }, |
| 204 | 204 | strtoupper($memoryLimit) |
@@ -222,7 +222,7 @@ discard block |
||
| 222 | 222 | // the policy key might be set in Request::Initialize from the base64 encoded query |
| 223 | 223 | if (!isset(self::$policykey)) { |
| 224 | 224 | if (isset(self::$headers["x-ms-policykey"])) { |
| 225 | - self::$policykey = (int) self::filterEvilInput(self::$headers["x-ms-policykey"], self::NUMBERS_ONLY); |
|
| 225 | + self::$policykey = (int)self::filterEvilInput(self::$headers["x-ms-policykey"], self::NUMBERS_ONLY); |
|
| 226 | 226 | } |
| 227 | 227 | else { |
| 228 | 228 | self::$policykey = 0; |
@@ -637,7 +637,7 @@ discard block |
||
| 637 | 637 | * @return int |
| 638 | 638 | */ |
| 639 | 639 | public static function GetContentLength() { |
| 640 | - return (isset(self::$headers["content-length"])) ? (int) self::$headers["content-length"] : 0; |
|
| 640 | + return (isset(self::$headers["content-length"])) ? (int)self::$headers["content-length"] : 0; |
|
| 641 | 641 | } |
| 642 | 642 | |
| 643 | 643 | /** |
@@ -750,7 +750,7 @@ discard block |
||
| 750 | 750 | private static function filterIP($input) { |
| 751 | 751 | $in_addr = @inet_pton($input); |
| 752 | 752 | if ($in_addr === false) { |
| 753 | - return 'badip-' . self::filterEvilInput($input, self::HEX_EXTENDED); |
|
| 753 | + return 'badip-'.self::filterEvilInput($input, self::HEX_EXTENDED); |
|
| 754 | 754 | } |
| 755 | 755 | |
| 756 | 756 | return inet_ntop($in_addr); |
@@ -799,14 +799,14 @@ discard block |
||
| 799 | 799 | $polKeyLength = ord($decoded[5 + $devIdLength]); // policy key length |
| 800 | 800 | $devTypeLength = ord($decoded[6 + $devIdLength + $polKeyLength]); // device type length |
| 801 | 801 | // unpack the decoded query string values |
| 802 | - self::$base64QueryDecoded = unpack("CProtVer/CCommand/vLocale/CDevIDLen/H" . ($devIdLength * 2) . "DevID/CPolKeyLen" . ($polKeyLength == 4 ? "/VPolKey" : "") . "/CDevTypeLen/A" . ($devTypeLength) . "DevType", $decoded); |
|
| 802 | + self::$base64QueryDecoded = unpack("CProtVer/CCommand/vLocale/CDevIDLen/H".($devIdLength * 2)."DevID/CPolKeyLen".($polKeyLength == 4 ? "/VPolKey" : "")."/CDevTypeLen/A".($devTypeLength)."DevType", $decoded); |
|
| 803 | 803 | |
| 804 | 804 | // get the command parameters |
| 805 | 805 | $pos = 7 + $devIdLength + $polKeyLength + $devTypeLength; |
| 806 | 806 | $decoded = substr($decoded, $pos); |
| 807 | 807 | while (strlen($decoded) > 0) { |
| 808 | 808 | $paramLength = ord($decoded[1]); |
| 809 | - $unpackedParam = unpack("CParamTag/CParamLength/A" . $paramLength . "ParamValue", $decoded); |
|
| 809 | + $unpackedParam = unpack("CParamTag/CParamLength/A".$paramLength."ParamValue", $decoded); |
|
| 810 | 810 | self::$base64QueryDecoded[ord($decoded[0])] = $unpackedParam['ParamValue']; |
| 811 | 811 | // remove parameter from decoded query string |
| 812 | 812 | $decoded = substr($decoded, 2 + $paramLength); |
@@ -194,8 +194,7 @@ discard block |
||
| 194 | 194 | $memoryLimit = ini_get('memory_limit'); |
| 195 | 195 | if ($memoryLimit == -1) { |
| 196 | 196 | self::$memoryLimit = false; |
| 197 | - } |
|
| 198 | - else { |
|
| 197 | + } else { |
|
| 199 | 198 | preg_replace_callback( |
| 200 | 199 | '/(\-?\d+)(.?)/', |
| 201 | 200 | function ($m) { |
@@ -223,8 +222,7 @@ discard block |
||
| 223 | 222 | if (!isset(self::$policykey)) { |
| 224 | 223 | if (isset(self::$headers["x-ms-policykey"])) { |
| 225 | 224 | self::$policykey = (int) self::filterEvilInput(self::$headers["x-ms-policykey"], self::NUMBERS_ONLY); |
| 226 | - } |
|
| 227 | - else { |
|
| 225 | + } else { |
|
| 228 | 226 | self::$policykey = 0; |
| 229 | 227 | } |
| 230 | 228 | } |
@@ -661,8 +659,7 @@ discard block |
||
| 661 | 659 | // Samsung devices have a intermediate timeout (90sec) |
| 662 | 660 | elseif (stripos(SYNC_TIMEOUT_MEDIUM_DEVICETYPES, self::GetDeviceType()) !== false) { |
| 663 | 661 | self::$expectedConnectionTimeout = 85; |
| 664 | - } |
|
| 665 | - else { |
|
| 662 | + } else { |
|
| 666 | 663 | // for all other devices, a timeout of 30 seconds is expected |
| 667 | 664 | self::$expectedConnectionTimeout = 28; |
| 668 | 665 | } |
@@ -713,23 +710,17 @@ discard block |
||
| 713 | 710 | $re = false; |
| 714 | 711 | if ($filter == self::LETTERS_ONLY) { |
| 715 | 712 | $re = "/[^A-Za-z]/"; |
| 716 | - } |
|
| 717 | - elseif ($filter == self::HEX_ONLY) { |
|
| 713 | + } elseif ($filter == self::HEX_ONLY) { |
|
| 718 | 714 | $re = "/[^A-Fa-f0-9]/"; |
| 719 | - } |
|
| 720 | - elseif ($filter == self::WORDCHAR_ONLY) { |
|
| 715 | + } elseif ($filter == self::WORDCHAR_ONLY) { |
|
| 721 | 716 | $re = "/[^A-Za-z0-9]/"; |
| 722 | - } |
|
| 723 | - elseif ($filter == self::NUMBERS_ONLY) { |
|
| 717 | + } elseif ($filter == self::NUMBERS_ONLY) { |
|
| 724 | 718 | $re = "/[^0-9]/"; |
| 725 | - } |
|
| 726 | - elseif ($filter == self::NUMBERSDOT_ONLY) { |
|
| 719 | + } elseif ($filter == self::NUMBERSDOT_ONLY) { |
|
| 727 | 720 | $re = "/[^0-9\\.]/"; |
| 728 | - } |
|
| 729 | - elseif ($filter == self::HEX_EXTENDED) { |
|
| 721 | + } elseif ($filter == self::HEX_EXTENDED) { |
|
| 730 | 722 | $re = "/[^A-Fa-f0-9\\:\\.]/"; |
| 731 | - } |
|
| 732 | - elseif ($filter == self::HEX_EXTENDED2) { |
|
| 723 | + } elseif ($filter == self::HEX_EXTENDED2) { |
|
| 733 | 724 | $re = "/[^A-Fa-f0-9\\:USGI]/"; |
| 734 | 725 | } // Folder origin constants from DeviceManager::FLD_ORIGIN_* (C already hex) |
| 735 | 726 | elseif ($filter == self::ISO8601) { |
@@ -8,266 +8,266 @@ |
||
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | 10 | class GetItemEstimate extends RequestProcessor { |
| 11 | - /** |
|
| 12 | - * Handles the GetItemEstimate command |
|
| 13 | - * Returns an estimation of how many items will be synchronized at the next sync |
|
| 14 | - * This is mostly used to show something in the progress bar. |
|
| 15 | - * |
|
| 16 | - * @param int $commandCode |
|
| 17 | - * |
|
| 18 | - * @return bool |
|
| 19 | - */ |
|
| 20 | - public function Handle($commandCode) { |
|
| 21 | - $sc = new SyncCollections(); |
|
| 22 | - |
|
| 23 | - if (!self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_GETITEMESTIMATE)) { |
|
| 24 | - return false; |
|
| 25 | - } |
|
| 26 | - |
|
| 27 | - if (!self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDERS)) { |
|
| 28 | - return false; |
|
| 29 | - } |
|
| 30 | - |
|
| 31 | - while (self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDER)) { |
|
| 32 | - $spa = new SyncParameters(); |
|
| 33 | - $spastatus = false; |
|
| 34 | - |
|
| 35 | - // read the folder properties |
|
| 36 | - WBXMLDecoder::ResetInWhile("getItemEstimateFolders"); |
|
| 37 | - while (WBXMLDecoder::InWhile("getItemEstimateFolders")) { |
|
| 38 | - if (self::$decoder->getElementStartTag(SYNC_SYNCKEY)) { |
|
| 39 | - try { |
|
| 40 | - $spa->SetSyncKey(self::$decoder->getElementContent()); |
|
| 41 | - } |
|
| 42 | - catch (StateInvalidException $siex) { |
|
| 43 | - $spastatus = SYNC_GETITEMESTSTATUS_SYNCSTATENOTPRIMED; |
|
| 44 | - } |
|
| 45 | - |
|
| 46 | - if (!self::$decoder->getElementEndTag()) { |
|
| 47 | - return false; |
|
| 48 | - } |
|
| 49 | - } |
|
| 50 | - elseif (self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDERID)) { |
|
| 51 | - $fid = self::$decoder->getElementContent(); |
|
| 52 | - $spa->SetFolderId($fid); |
|
| 53 | - $spa->SetBackendFolderId(self::$deviceManager->GetBackendIdForFolderId($fid)); |
|
| 54 | - |
|
| 55 | - if (!self::$decoder->getElementEndTag()) { |
|
| 56 | - return false; |
|
| 57 | - } |
|
| 58 | - } |
|
| 59 | - |
|
| 60 | - // conversation mode requested |
|
| 61 | - elseif (self::$decoder->getElementStartTag(SYNC_CONVERSATIONMODE)) { |
|
| 62 | - $spa->SetConversationMode(true); |
|
| 63 | - if (($conversationmode = self::$decoder->getElementContent()) !== false) { |
|
| 64 | - $spa->SetConversationMode((bool) $conversationmode); |
|
| 65 | - if (!self::$decoder->getElementEndTag()) { |
|
| 66 | - return false; |
|
| 67 | - } |
|
| 68 | - } |
|
| 69 | - } |
|
| 70 | - |
|
| 71 | - // get items estimate does not necessarily send the folder type |
|
| 72 | - elseif (self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDERTYPE)) { |
|
| 73 | - $spa->SetContentClass(self::$decoder->getElementContent()); |
|
| 74 | - |
|
| 75 | - if (!self::$decoder->getElementEndTag()) { |
|
| 76 | - return false; |
|
| 77 | - } |
|
| 78 | - } |
|
| 79 | - |
|
| 80 | - // TODO AS 2.5 and filtertype not set |
|
| 81 | - elseif (self::$decoder->getElementStartTag(SYNC_FILTERTYPE)) { |
|
| 82 | - $spa->SetFilterType(self::$decoder->getElementContent()); |
|
| 83 | - |
|
| 84 | - if (!self::$decoder->getElementEndTag()) { |
|
| 85 | - return false; |
|
| 86 | - } |
|
| 87 | - } |
|
| 88 | - |
|
| 89 | - while (self::$decoder->getElementStartTag(SYNC_OPTIONS)) { |
|
| 90 | - WBXMLDecoder::ResetInWhile("getItemEstimateOptions"); |
|
| 91 | - while (WBXMLDecoder::InWhile("getItemEstimateOptions")) { |
|
| 92 | - $firstOption = true; |
|
| 93 | - // foldertype definition |
|
| 94 | - if (self::$decoder->getElementStartTag(SYNC_FOLDERTYPE)) { |
|
| 95 | - $foldertype = self::$decoder->getElementContent(); |
|
| 96 | - SLog::Write(LOGLEVEL_DEBUG, sprintf("HandleGetItemEstimate(): specified options block with foldertype '%s'", $foldertype)); |
|
| 97 | - |
|
| 98 | - // switch the foldertype for the next options |
|
| 99 | - $spa->UseCPO($foldertype); |
|
| 100 | - |
|
| 101 | - // set to synchronize all changes. The mobile could overwrite this value |
|
| 102 | - $spa->SetFilterType(SYNC_FILTERTYPE_ALL); |
|
| 103 | - |
|
| 104 | - if (!self::$decoder->getElementEndTag()) { |
|
| 105 | - return false; |
|
| 106 | - } |
|
| 107 | - } |
|
| 108 | - // if no foldertype is defined, use default cpo |
|
| 109 | - elseif ($firstOption) { |
|
| 110 | - $spa->UseCPO(); |
|
| 111 | - // set to synchronize all changes. The mobile could overwrite this value |
|
| 112 | - $spa->SetFilterType(SYNC_FILTERTYPE_ALL); |
|
| 113 | - } |
|
| 114 | - $firstOption = false; |
|
| 115 | - |
|
| 116 | - if (self::$decoder->getElementStartTag(SYNC_FILTERTYPE)) { |
|
| 117 | - $spa->SetFilterType(self::$decoder->getElementContent()); |
|
| 118 | - if (!self::$decoder->getElementEndTag()) { |
|
| 119 | - return false; |
|
| 120 | - } |
|
| 121 | - } |
|
| 122 | - |
|
| 123 | - if (self::$decoder->getElementStartTag(SYNC_MAXITEMS)) { |
|
| 124 | - $spa->SetWindowSize($maxitems = self::$decoder->getElementContent()); |
|
| 125 | - if (!self::$decoder->getElementEndTag()) { |
|
| 126 | - return false; |
|
| 127 | - } |
|
| 128 | - } |
|
| 129 | - |
|
| 130 | - $e = self::$decoder->peek(); |
|
| 131 | - if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { |
|
| 132 | - self::$decoder->getElementEndTag(); |
|
| 133 | - |
|
| 134 | - break; |
|
| 135 | - } |
|
| 136 | - } |
|
| 137 | - } |
|
| 138 | - |
|
| 139 | - $e = self::$decoder->peek(); |
|
| 140 | - if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { |
|
| 141 | - self::$decoder->getElementEndTag(); // SYNC_GETITEMESTIMATE_FOLDER |
|
| 142 | - |
|
| 143 | - break; |
|
| 144 | - } |
|
| 145 | - } |
|
| 146 | - // Process folder data |
|
| 147 | - |
|
| 148 | - // In AS 14 request only collectionid is sent, without class |
|
| 149 | - if (!$spa->HasContentClass() && $spa->HasFolderId()) { |
|
| 150 | - try { |
|
| 151 | - $spa->SetContentClass(self::$deviceManager->GetFolderClassFromCacheByID($spa->GetFolderId())); |
|
| 152 | - } |
|
| 153 | - catch (NoHierarchyCacheAvailableException $nhca) { |
|
| 154 | - $spastatus = SYNC_GETITEMESTSTATUS_COLLECTIONINVALID; |
|
| 155 | - } |
|
| 156 | - } |
|
| 157 | - |
|
| 158 | - // compatibility mode AS 1.0 - get folderid which was sent during GetHierarchy() |
|
| 159 | - if (!$spa->HasFolderId() && $spa->HasContentClass()) { |
|
| 160 | - $spa->SetFolderId(self::$deviceManager->GetFolderIdFromCacheByClass($spa->GetContentClass())); |
|
| 161 | - } |
|
| 162 | - |
|
| 163 | - // Add collection to SC and load state |
|
| 164 | - $sc->AddCollection($spa); |
|
| 165 | - if ($spastatus) { |
|
| 166 | - // the CPO has a folder id now, so we can set the status |
|
| 167 | - $sc->AddParameter($spa, "status", $spastatus); |
|
| 168 | - } |
|
| 169 | - else { |
|
| 170 | - try { |
|
| 171 | - $sc->AddParameter($spa, "state", self::$deviceManager->GetStateManager()->GetSyncState($spa->GetSyncKey())); |
|
| 172 | - |
|
| 173 | - // if this is an additional folder the backend has to be setup correctly |
|
| 174 | - if (!self::$backend->Setup(GSync::GetAdditionalSyncFolderStore($spa->GetBackendFolderId()))) { |
|
| 175 | - throw new StatusException(sprintf("HandleGetItemEstimate() could not Setup() the backend for folder id %s/%s", $spa->GetFolderId(), $spa->GetBackendFolderId()), SYNC_GETITEMESTSTATUS_COLLECTIONINVALID); |
|
| 176 | - } |
|
| 177 | - } |
|
| 178 | - catch (StateNotFoundException $snfex) { |
|
| 179 | - // ok, the key is invalid. Question is, if the hierarchycache is still ok |
|
| 180 | - // if not, we have to issue SYNC_GETITEMESTSTATUS_COLLECTIONINVALID which triggers a FolderSync |
|
| 181 | - try { |
|
| 182 | - self::$deviceManager->GetFolderClassFromCacheByID($spa->GetFolderId()); |
|
| 183 | - // we got here, so the HierarchyCache is ok |
|
| 184 | - $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_SYNCKKEYINVALID); |
|
| 185 | - } |
|
| 186 | - catch (NoHierarchyCacheAvailableException $nhca) { |
|
| 187 | - $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_COLLECTIONINVALID); |
|
| 188 | - } |
|
| 189 | - |
|
| 190 | - self::$topCollector->AnnounceInformation("StateNotFoundException " . $sc->GetParameter($spa, "status"), true); |
|
| 191 | - } |
|
| 192 | - catch (StatusException $stex) { |
|
| 193 | - if ($stex->getCode() == SYNC_GETITEMESTSTATUS_COLLECTIONINVALID) { |
|
| 194 | - $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_COLLECTIONINVALID); |
|
| 195 | - } |
|
| 196 | - else { |
|
| 197 | - $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_SYNCSTATENOTPRIMED); |
|
| 198 | - } |
|
| 199 | - self::$topCollector->AnnounceInformation("StatusException " . $sc->GetParameter($spa, "status"), true); |
|
| 200 | - } |
|
| 201 | - } |
|
| 202 | - } |
|
| 203 | - if (!self::$decoder->getElementEndTag()) { |
|
| 204 | - return false; |
|
| 205 | - } // SYNC_GETITEMESTIMATE_FOLDERS |
|
| 206 | - |
|
| 207 | - if (!self::$decoder->getElementEndTag()) { |
|
| 208 | - return false; |
|
| 209 | - } // SYNC_GETITEMESTIMATE_GETITEMESTIMATE |
|
| 210 | - |
|
| 211 | - self::$encoder->startWBXML(); |
|
| 212 | - self::$encoder->startTag(SYNC_GETITEMESTIMATE_GETITEMESTIMATE); |
|
| 213 | - |
|
| 214 | - $status = SYNC_GETITEMESTSTATUS_SUCCESS; |
|
| 215 | - // look for changes in all collections |
|
| 216 | - |
|
| 217 | - try { |
|
| 218 | - $sc->CountChanges(); |
|
| 219 | - } |
|
| 220 | - catch (StatusException $ste) { |
|
| 221 | - $status = SYNC_GETITEMESTSTATUS_COLLECTIONINVALID; |
|
| 222 | - } |
|
| 223 | - $changes = $sc->GetChangedFolderIds(); |
|
| 224 | - |
|
| 225 | - foreach ($sc as $folderid => $spa) { |
|
| 226 | - self::$encoder->startTag(SYNC_GETITEMESTIMATE_RESPONSE); |
|
| 227 | - |
|
| 228 | - if ($sc->GetParameter($spa, "status")) { |
|
| 229 | - $status = $sc->GetParameter($spa, "status"); |
|
| 230 | - } |
|
| 231 | - |
|
| 232 | - self::$encoder->startTag(SYNC_GETITEMESTIMATE_STATUS); |
|
| 233 | - self::$encoder->content($status); |
|
| 234 | - self::$encoder->endTag(); |
|
| 235 | - |
|
| 236 | - self::$encoder->startTag(SYNC_GETITEMESTIMATE_FOLDER); |
|
| 237 | - |
|
| 238 | - self::$encoder->startTag(SYNC_GETITEMESTIMATE_FOLDERTYPE); |
|
| 239 | - self::$encoder->content($spa->GetContentClass()); |
|
| 240 | - self::$encoder->endTag(); |
|
| 241 | - |
|
| 242 | - self::$encoder->startTag(SYNC_GETITEMESTIMATE_FOLDERID); |
|
| 243 | - self::$encoder->content($spa->GetFolderId()); |
|
| 244 | - self::$encoder->endTag(); |
|
| 245 | - |
|
| 246 | - if (isset($changes[$folderid]) && $changes[$folderid] !== false) { |
|
| 247 | - self::$encoder->startTag(SYNC_GETITEMESTIMATE_ESTIMATE); |
|
| 248 | - self::$encoder->content($changes[$folderid]); |
|
| 249 | - self::$encoder->endTag(); |
|
| 250 | - |
|
| 251 | - if ($changes[$folderid] > 0) { |
|
| 252 | - self::$topCollector->AnnounceInformation(sprintf("%s %d changes", $spa->GetContentClass(), $changes[$folderid]), true); |
|
| 253 | - } |
|
| 254 | - |
|
| 255 | - // update the device data to mark folders as complete when syncing with WM |
|
| 256 | - if ($changes[$folderid] == 0) { |
|
| 257 | - self::$deviceManager->SetFolderSyncStatus($folderid, DeviceManager::FLD_SYNC_COMPLETED); |
|
| 258 | - } |
|
| 259 | - } |
|
| 260 | - |
|
| 261 | - self::$encoder->endTag(); |
|
| 262 | - |
|
| 263 | - self::$encoder->endTag(); |
|
| 264 | - } |
|
| 265 | - if (array_sum($changes) == 0) { |
|
| 266 | - self::$topCollector->AnnounceInformation("No changes found", true); |
|
| 267 | - } |
|
| 268 | - |
|
| 269 | - self::$encoder->endTag(); |
|
| 270 | - |
|
| 271 | - return true; |
|
| 272 | - } |
|
| 11 | + /** |
|
| 12 | + * Handles the GetItemEstimate command |
|
| 13 | + * Returns an estimation of how many items will be synchronized at the next sync |
|
| 14 | + * This is mostly used to show something in the progress bar. |
|
| 15 | + * |
|
| 16 | + * @param int $commandCode |
|
| 17 | + * |
|
| 18 | + * @return bool |
|
| 19 | + */ |
|
| 20 | + public function Handle($commandCode) { |
|
| 21 | + $sc = new SyncCollections(); |
|
| 22 | + |
|
| 23 | + if (!self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_GETITEMESTIMATE)) { |
|
| 24 | + return false; |
|
| 25 | + } |
|
| 26 | + |
|
| 27 | + if (!self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDERS)) { |
|
| 28 | + return false; |
|
| 29 | + } |
|
| 30 | + |
|
| 31 | + while (self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDER)) { |
|
| 32 | + $spa = new SyncParameters(); |
|
| 33 | + $spastatus = false; |
|
| 34 | + |
|
| 35 | + // read the folder properties |
|
| 36 | + WBXMLDecoder::ResetInWhile("getItemEstimateFolders"); |
|
| 37 | + while (WBXMLDecoder::InWhile("getItemEstimateFolders")) { |
|
| 38 | + if (self::$decoder->getElementStartTag(SYNC_SYNCKEY)) { |
|
| 39 | + try { |
|
| 40 | + $spa->SetSyncKey(self::$decoder->getElementContent()); |
|
| 41 | + } |
|
| 42 | + catch (StateInvalidException $siex) { |
|
| 43 | + $spastatus = SYNC_GETITEMESTSTATUS_SYNCSTATENOTPRIMED; |
|
| 44 | + } |
|
| 45 | + |
|
| 46 | + if (!self::$decoder->getElementEndTag()) { |
|
| 47 | + return false; |
|
| 48 | + } |
|
| 49 | + } |
|
| 50 | + elseif (self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDERID)) { |
|
| 51 | + $fid = self::$decoder->getElementContent(); |
|
| 52 | + $spa->SetFolderId($fid); |
|
| 53 | + $spa->SetBackendFolderId(self::$deviceManager->GetBackendIdForFolderId($fid)); |
|
| 54 | + |
|
| 55 | + if (!self::$decoder->getElementEndTag()) { |
|
| 56 | + return false; |
|
| 57 | + } |
|
| 58 | + } |
|
| 59 | + |
|
| 60 | + // conversation mode requested |
|
| 61 | + elseif (self::$decoder->getElementStartTag(SYNC_CONVERSATIONMODE)) { |
|
| 62 | + $spa->SetConversationMode(true); |
|
| 63 | + if (($conversationmode = self::$decoder->getElementContent()) !== false) { |
|
| 64 | + $spa->SetConversationMode((bool) $conversationmode); |
|
| 65 | + if (!self::$decoder->getElementEndTag()) { |
|
| 66 | + return false; |
|
| 67 | + } |
|
| 68 | + } |
|
| 69 | + } |
|
| 70 | + |
|
| 71 | + // get items estimate does not necessarily send the folder type |
|
| 72 | + elseif (self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDERTYPE)) { |
|
| 73 | + $spa->SetContentClass(self::$decoder->getElementContent()); |
|
| 74 | + |
|
| 75 | + if (!self::$decoder->getElementEndTag()) { |
|
| 76 | + return false; |
|
| 77 | + } |
|
| 78 | + } |
|
| 79 | + |
|
| 80 | + // TODO AS 2.5 and filtertype not set |
|
| 81 | + elseif (self::$decoder->getElementStartTag(SYNC_FILTERTYPE)) { |
|
| 82 | + $spa->SetFilterType(self::$decoder->getElementContent()); |
|
| 83 | + |
|
| 84 | + if (!self::$decoder->getElementEndTag()) { |
|
| 85 | + return false; |
|
| 86 | + } |
|
| 87 | + } |
|
| 88 | + |
|
| 89 | + while (self::$decoder->getElementStartTag(SYNC_OPTIONS)) { |
|
| 90 | + WBXMLDecoder::ResetInWhile("getItemEstimateOptions"); |
|
| 91 | + while (WBXMLDecoder::InWhile("getItemEstimateOptions")) { |
|
| 92 | + $firstOption = true; |
|
| 93 | + // foldertype definition |
|
| 94 | + if (self::$decoder->getElementStartTag(SYNC_FOLDERTYPE)) { |
|
| 95 | + $foldertype = self::$decoder->getElementContent(); |
|
| 96 | + SLog::Write(LOGLEVEL_DEBUG, sprintf("HandleGetItemEstimate(): specified options block with foldertype '%s'", $foldertype)); |
|
| 97 | + |
|
| 98 | + // switch the foldertype for the next options |
|
| 99 | + $spa->UseCPO($foldertype); |
|
| 100 | + |
|
| 101 | + // set to synchronize all changes. The mobile could overwrite this value |
|
| 102 | + $spa->SetFilterType(SYNC_FILTERTYPE_ALL); |
|
| 103 | + |
|
| 104 | + if (!self::$decoder->getElementEndTag()) { |
|
| 105 | + return false; |
|
| 106 | + } |
|
| 107 | + } |
|
| 108 | + // if no foldertype is defined, use default cpo |
|
| 109 | + elseif ($firstOption) { |
|
| 110 | + $spa->UseCPO(); |
|
| 111 | + // set to synchronize all changes. The mobile could overwrite this value |
|
| 112 | + $spa->SetFilterType(SYNC_FILTERTYPE_ALL); |
|
| 113 | + } |
|
| 114 | + $firstOption = false; |
|
| 115 | + |
|
| 116 | + if (self::$decoder->getElementStartTag(SYNC_FILTERTYPE)) { |
|
| 117 | + $spa->SetFilterType(self::$decoder->getElementContent()); |
|
| 118 | + if (!self::$decoder->getElementEndTag()) { |
|
| 119 | + return false; |
|
| 120 | + } |
|
| 121 | + } |
|
| 122 | + |
|
| 123 | + if (self::$decoder->getElementStartTag(SYNC_MAXITEMS)) { |
|
| 124 | + $spa->SetWindowSize($maxitems = self::$decoder->getElementContent()); |
|
| 125 | + if (!self::$decoder->getElementEndTag()) { |
|
| 126 | + return false; |
|
| 127 | + } |
|
| 128 | + } |
|
| 129 | + |
|
| 130 | + $e = self::$decoder->peek(); |
|
| 131 | + if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { |
|
| 132 | + self::$decoder->getElementEndTag(); |
|
| 133 | + |
|
| 134 | + break; |
|
| 135 | + } |
|
| 136 | + } |
|
| 137 | + } |
|
| 138 | + |
|
| 139 | + $e = self::$decoder->peek(); |
|
| 140 | + if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { |
|
| 141 | + self::$decoder->getElementEndTag(); // SYNC_GETITEMESTIMATE_FOLDER |
|
| 142 | + |
|
| 143 | + break; |
|
| 144 | + } |
|
| 145 | + } |
|
| 146 | + // Process folder data |
|
| 147 | + |
|
| 148 | + // In AS 14 request only collectionid is sent, without class |
|
| 149 | + if (!$spa->HasContentClass() && $spa->HasFolderId()) { |
|
| 150 | + try { |
|
| 151 | + $spa->SetContentClass(self::$deviceManager->GetFolderClassFromCacheByID($spa->GetFolderId())); |
|
| 152 | + } |
|
| 153 | + catch (NoHierarchyCacheAvailableException $nhca) { |
|
| 154 | + $spastatus = SYNC_GETITEMESTSTATUS_COLLECTIONINVALID; |
|
| 155 | + } |
|
| 156 | + } |
|
| 157 | + |
|
| 158 | + // compatibility mode AS 1.0 - get folderid which was sent during GetHierarchy() |
|
| 159 | + if (!$spa->HasFolderId() && $spa->HasContentClass()) { |
|
| 160 | + $spa->SetFolderId(self::$deviceManager->GetFolderIdFromCacheByClass($spa->GetContentClass())); |
|
| 161 | + } |
|
| 162 | + |
|
| 163 | + // Add collection to SC and load state |
|
| 164 | + $sc->AddCollection($spa); |
|
| 165 | + if ($spastatus) { |
|
| 166 | + // the CPO has a folder id now, so we can set the status |
|
| 167 | + $sc->AddParameter($spa, "status", $spastatus); |
|
| 168 | + } |
|
| 169 | + else { |
|
| 170 | + try { |
|
| 171 | + $sc->AddParameter($spa, "state", self::$deviceManager->GetStateManager()->GetSyncState($spa->GetSyncKey())); |
|
| 172 | + |
|
| 173 | + // if this is an additional folder the backend has to be setup correctly |
|
| 174 | + if (!self::$backend->Setup(GSync::GetAdditionalSyncFolderStore($spa->GetBackendFolderId()))) { |
|
| 175 | + throw new StatusException(sprintf("HandleGetItemEstimate() could not Setup() the backend for folder id %s/%s", $spa->GetFolderId(), $spa->GetBackendFolderId()), SYNC_GETITEMESTSTATUS_COLLECTIONINVALID); |
|
| 176 | + } |
|
| 177 | + } |
|
| 178 | + catch (StateNotFoundException $snfex) { |
|
| 179 | + // ok, the key is invalid. Question is, if the hierarchycache is still ok |
|
| 180 | + // if not, we have to issue SYNC_GETITEMESTSTATUS_COLLECTIONINVALID which triggers a FolderSync |
|
| 181 | + try { |
|
| 182 | + self::$deviceManager->GetFolderClassFromCacheByID($spa->GetFolderId()); |
|
| 183 | + // we got here, so the HierarchyCache is ok |
|
| 184 | + $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_SYNCKKEYINVALID); |
|
| 185 | + } |
|
| 186 | + catch (NoHierarchyCacheAvailableException $nhca) { |
|
| 187 | + $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_COLLECTIONINVALID); |
|
| 188 | + } |
|
| 189 | + |
|
| 190 | + self::$topCollector->AnnounceInformation("StateNotFoundException " . $sc->GetParameter($spa, "status"), true); |
|
| 191 | + } |
|
| 192 | + catch (StatusException $stex) { |
|
| 193 | + if ($stex->getCode() == SYNC_GETITEMESTSTATUS_COLLECTIONINVALID) { |
|
| 194 | + $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_COLLECTIONINVALID); |
|
| 195 | + } |
|
| 196 | + else { |
|
| 197 | + $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_SYNCSTATENOTPRIMED); |
|
| 198 | + } |
|
| 199 | + self::$topCollector->AnnounceInformation("StatusException " . $sc->GetParameter($spa, "status"), true); |
|
| 200 | + } |
|
| 201 | + } |
|
| 202 | + } |
|
| 203 | + if (!self::$decoder->getElementEndTag()) { |
|
| 204 | + return false; |
|
| 205 | + } // SYNC_GETITEMESTIMATE_FOLDERS |
|
| 206 | + |
|
| 207 | + if (!self::$decoder->getElementEndTag()) { |
|
| 208 | + return false; |
|
| 209 | + } // SYNC_GETITEMESTIMATE_GETITEMESTIMATE |
|
| 210 | + |
|
| 211 | + self::$encoder->startWBXML(); |
|
| 212 | + self::$encoder->startTag(SYNC_GETITEMESTIMATE_GETITEMESTIMATE); |
|
| 213 | + |
|
| 214 | + $status = SYNC_GETITEMESTSTATUS_SUCCESS; |
|
| 215 | + // look for changes in all collections |
|
| 216 | + |
|
| 217 | + try { |
|
| 218 | + $sc->CountChanges(); |
|
| 219 | + } |
|
| 220 | + catch (StatusException $ste) { |
|
| 221 | + $status = SYNC_GETITEMESTSTATUS_COLLECTIONINVALID; |
|
| 222 | + } |
|
| 223 | + $changes = $sc->GetChangedFolderIds(); |
|
| 224 | + |
|
| 225 | + foreach ($sc as $folderid => $spa) { |
|
| 226 | + self::$encoder->startTag(SYNC_GETITEMESTIMATE_RESPONSE); |
|
| 227 | + |
|
| 228 | + if ($sc->GetParameter($spa, "status")) { |
|
| 229 | + $status = $sc->GetParameter($spa, "status"); |
|
| 230 | + } |
|
| 231 | + |
|
| 232 | + self::$encoder->startTag(SYNC_GETITEMESTIMATE_STATUS); |
|
| 233 | + self::$encoder->content($status); |
|
| 234 | + self::$encoder->endTag(); |
|
| 235 | + |
|
| 236 | + self::$encoder->startTag(SYNC_GETITEMESTIMATE_FOLDER); |
|
| 237 | + |
|
| 238 | + self::$encoder->startTag(SYNC_GETITEMESTIMATE_FOLDERTYPE); |
|
| 239 | + self::$encoder->content($spa->GetContentClass()); |
|
| 240 | + self::$encoder->endTag(); |
|
| 241 | + |
|
| 242 | + self::$encoder->startTag(SYNC_GETITEMESTIMATE_FOLDERID); |
|
| 243 | + self::$encoder->content($spa->GetFolderId()); |
|
| 244 | + self::$encoder->endTag(); |
|
| 245 | + |
|
| 246 | + if (isset($changes[$folderid]) && $changes[$folderid] !== false) { |
|
| 247 | + self::$encoder->startTag(SYNC_GETITEMESTIMATE_ESTIMATE); |
|
| 248 | + self::$encoder->content($changes[$folderid]); |
|
| 249 | + self::$encoder->endTag(); |
|
| 250 | + |
|
| 251 | + if ($changes[$folderid] > 0) { |
|
| 252 | + self::$topCollector->AnnounceInformation(sprintf("%s %d changes", $spa->GetContentClass(), $changes[$folderid]), true); |
|
| 253 | + } |
|
| 254 | + |
|
| 255 | + // update the device data to mark folders as complete when syncing with WM |
|
| 256 | + if ($changes[$folderid] == 0) { |
|
| 257 | + self::$deviceManager->SetFolderSyncStatus($folderid, DeviceManager::FLD_SYNC_COMPLETED); |
|
| 258 | + } |
|
| 259 | + } |
|
| 260 | + |
|
| 261 | + self::$encoder->endTag(); |
|
| 262 | + |
|
| 263 | + self::$encoder->endTag(); |
|
| 264 | + } |
|
| 265 | + if (array_sum($changes) == 0) { |
|
| 266 | + self::$topCollector->AnnounceInformation("No changes found", true); |
|
| 267 | + } |
|
| 268 | + |
|
| 269 | + self::$encoder->endTag(); |
|
| 270 | + |
|
| 271 | + return true; |
|
| 272 | + } |
|
| 273 | 273 | } |
@@ -61,7 +61,7 @@ discard block |
||
| 61 | 61 | elseif (self::$decoder->getElementStartTag(SYNC_CONVERSATIONMODE)) { |
| 62 | 62 | $spa->SetConversationMode(true); |
| 63 | 63 | if (($conversationmode = self::$decoder->getElementContent()) !== false) { |
| 64 | - $spa->SetConversationMode((bool) $conversationmode); |
|
| 64 | + $spa->SetConversationMode((bool)$conversationmode); |
|
| 65 | 65 | if (!self::$decoder->getElementEndTag()) { |
| 66 | 66 | return false; |
| 67 | 67 | } |
@@ -187,7 +187,7 @@ discard block |
||
| 187 | 187 | $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_COLLECTIONINVALID); |
| 188 | 188 | } |
| 189 | 189 | |
| 190 | - self::$topCollector->AnnounceInformation("StateNotFoundException " . $sc->GetParameter($spa, "status"), true); |
|
| 190 | + self::$topCollector->AnnounceInformation("StateNotFoundException ".$sc->GetParameter($spa, "status"), true); |
|
| 191 | 191 | } |
| 192 | 192 | catch (StatusException $stex) { |
| 193 | 193 | if ($stex->getCode() == SYNC_GETITEMESTSTATUS_COLLECTIONINVALID) { |
@@ -196,7 +196,7 @@ discard block |
||
| 196 | 196 | else { |
| 197 | 197 | $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_SYNCSTATENOTPRIMED); |
| 198 | 198 | } |
| 199 | - self::$topCollector->AnnounceInformation("StatusException " . $sc->GetParameter($spa, "status"), true); |
|
| 199 | + self::$topCollector->AnnounceInformation("StatusException ".$sc->GetParameter($spa, "status"), true); |
|
| 200 | 200 | } |
| 201 | 201 | } |
| 202 | 202 | } |
@@ -38,16 +38,14 @@ discard block |
||
| 38 | 38 | if (self::$decoder->getElementStartTag(SYNC_SYNCKEY)) { |
| 39 | 39 | try { |
| 40 | 40 | $spa->SetSyncKey(self::$decoder->getElementContent()); |
| 41 | - } |
|
| 42 | - catch (StateInvalidException $siex) { |
|
| 41 | + } catch (StateInvalidException $siex) { |
|
| 43 | 42 | $spastatus = SYNC_GETITEMESTSTATUS_SYNCSTATENOTPRIMED; |
| 44 | 43 | } |
| 45 | 44 | |
| 46 | 45 | if (!self::$decoder->getElementEndTag()) { |
| 47 | 46 | return false; |
| 48 | 47 | } |
| 49 | - } |
|
| 50 | - elseif (self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDERID)) { |
|
| 48 | + } elseif (self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDERID)) { |
|
| 51 | 49 | $fid = self::$decoder->getElementContent(); |
| 52 | 50 | $spa->SetFolderId($fid); |
| 53 | 51 | $spa->SetBackendFolderId(self::$deviceManager->GetBackendIdForFolderId($fid)); |
@@ -149,8 +147,7 @@ discard block |
||
| 149 | 147 | if (!$spa->HasContentClass() && $spa->HasFolderId()) { |
| 150 | 148 | try { |
| 151 | 149 | $spa->SetContentClass(self::$deviceManager->GetFolderClassFromCacheByID($spa->GetFolderId())); |
| 152 | - } |
|
| 153 | - catch (NoHierarchyCacheAvailableException $nhca) { |
|
| 150 | + } catch (NoHierarchyCacheAvailableException $nhca) { |
|
| 154 | 151 | $spastatus = SYNC_GETITEMESTSTATUS_COLLECTIONINVALID; |
| 155 | 152 | } |
| 156 | 153 | } |
@@ -165,8 +162,7 @@ discard block |
||
| 165 | 162 | if ($spastatus) { |
| 166 | 163 | // the CPO has a folder id now, so we can set the status |
| 167 | 164 | $sc->AddParameter($spa, "status", $spastatus); |
| 168 | - } |
|
| 169 | - else { |
|
| 165 | + } else { |
|
| 170 | 166 | try { |
| 171 | 167 | $sc->AddParameter($spa, "state", self::$deviceManager->GetStateManager()->GetSyncState($spa->GetSyncKey())); |
| 172 | 168 | |
@@ -174,26 +170,22 @@ discard block |
||
| 174 | 170 | if (!self::$backend->Setup(GSync::GetAdditionalSyncFolderStore($spa->GetBackendFolderId()))) { |
| 175 | 171 | throw new StatusException(sprintf("HandleGetItemEstimate() could not Setup() the backend for folder id %s/%s", $spa->GetFolderId(), $spa->GetBackendFolderId()), SYNC_GETITEMESTSTATUS_COLLECTIONINVALID); |
| 176 | 172 | } |
| 177 | - } |
|
| 178 | - catch (StateNotFoundException $snfex) { |
|
| 173 | + } catch (StateNotFoundException $snfex) { |
|
| 179 | 174 | // ok, the key is invalid. Question is, if the hierarchycache is still ok |
| 180 | 175 | // if not, we have to issue SYNC_GETITEMESTSTATUS_COLLECTIONINVALID which triggers a FolderSync |
| 181 | 176 | try { |
| 182 | 177 | self::$deviceManager->GetFolderClassFromCacheByID($spa->GetFolderId()); |
| 183 | 178 | // we got here, so the HierarchyCache is ok |
| 184 | 179 | $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_SYNCKKEYINVALID); |
| 185 | - } |
|
| 186 | - catch (NoHierarchyCacheAvailableException $nhca) { |
|
| 180 | + } catch (NoHierarchyCacheAvailableException $nhca) { |
|
| 187 | 181 | $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_COLLECTIONINVALID); |
| 188 | 182 | } |
| 189 | 183 | |
| 190 | 184 | self::$topCollector->AnnounceInformation("StateNotFoundException " . $sc->GetParameter($spa, "status"), true); |
| 191 | - } |
|
| 192 | - catch (StatusException $stex) { |
|
| 185 | + } catch (StatusException $stex) { |
|
| 193 | 186 | if ($stex->getCode() == SYNC_GETITEMESTSTATUS_COLLECTIONINVALID) { |
| 194 | 187 | $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_COLLECTIONINVALID); |
| 195 | - } |
|
| 196 | - else { |
|
| 188 | + } else { |
|
| 197 | 189 | $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_SYNCSTATENOTPRIMED); |
| 198 | 190 | } |
| 199 | 191 | self::$topCollector->AnnounceInformation("StatusException " . $sc->GetParameter($spa, "status"), true); |
@@ -216,8 +208,7 @@ discard block |
||
| 216 | 208 | |
| 217 | 209 | try { |
| 218 | 210 | $sc->CountChanges(); |
| 219 | - } |
|
| 220 | - catch (StatusException $ste) { |
|
| 211 | + } catch (StatusException $ste) { |
|
| 221 | 212 | $status = SYNC_GETITEMESTSTATUS_COLLECTIONINVALID; |
| 222 | 213 | } |
| 223 | 214 | $changes = $sc->GetChangedFolderIds(); |
@@ -8,64 +8,64 @@ |
||
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | 10 | class ResolveRecipients extends RequestProcessor { |
| 11 | - /** |
|
| 12 | - * Handles the ResolveRecipients command. |
|
| 13 | - * |
|
| 14 | - * @param int $commandCode |
|
| 15 | - * |
|
| 16 | - * @return bool |
|
| 17 | - */ |
|
| 18 | - public function Handle($commandCode) { |
|
| 19 | - // Parse input |
|
| 20 | - if (!self::$decoder->getElementStartTag(SYNC_RESOLVERECIPIENTS_RESOLVERECIPIENTS)) { |
|
| 21 | - return false; |
|
| 22 | - } |
|
| 11 | + /** |
|
| 12 | + * Handles the ResolveRecipients command. |
|
| 13 | + * |
|
| 14 | + * @param int $commandCode |
|
| 15 | + * |
|
| 16 | + * @return bool |
|
| 17 | + */ |
|
| 18 | + public function Handle($commandCode) { |
|
| 19 | + // Parse input |
|
| 20 | + if (!self::$decoder->getElementStartTag(SYNC_RESOLVERECIPIENTS_RESOLVERECIPIENTS)) { |
|
| 21 | + return false; |
|
| 22 | + } |
|
| 23 | 23 | |
| 24 | - $resolveRecipients = new SyncResolveRecipients(); |
|
| 25 | - $resolveRecipients->Decode(self::$decoder); |
|
| 24 | + $resolveRecipients = new SyncResolveRecipients(); |
|
| 25 | + $resolveRecipients->Decode(self::$decoder); |
|
| 26 | 26 | |
| 27 | - if (!self::$decoder->getElementEndTag()) { |
|
| 28 | - return false; |
|
| 29 | - } // SYNC_RESOLVERECIPIENTS_RESOLVERECIPIENTS |
|
| 27 | + if (!self::$decoder->getElementEndTag()) { |
|
| 28 | + return false; |
|
| 29 | + } // SYNC_RESOLVERECIPIENTS_RESOLVERECIPIENTS |
|
| 30 | 30 | |
| 31 | - $resolveRecipients = self::$backend->ResolveRecipients($resolveRecipients); |
|
| 31 | + $resolveRecipients = self::$backend->ResolveRecipients($resolveRecipients); |
|
| 32 | 32 | |
| 33 | - self::$encoder->startWBXML(); |
|
| 34 | - self::$encoder->startTag(SYNC_RESOLVERECIPIENTS_RESOLVERECIPIENTS); |
|
| 33 | + self::$encoder->startWBXML(); |
|
| 34 | + self::$encoder->startTag(SYNC_RESOLVERECIPIENTS_RESOLVERECIPIENTS); |
|
| 35 | 35 | |
| 36 | - self::$encoder->startTag(SYNC_RESOLVERECIPIENTS_STATUS); |
|
| 37 | - self::$encoder->content($resolveRecipients->status); |
|
| 38 | - self::$encoder->endTag(); // SYNC_RESOLVERECIPIENTS_STATUS |
|
| 36 | + self::$encoder->startTag(SYNC_RESOLVERECIPIENTS_STATUS); |
|
| 37 | + self::$encoder->content($resolveRecipients->status); |
|
| 38 | + self::$encoder->endTag(); // SYNC_RESOLVERECIPIENTS_STATUS |
|
| 39 | 39 | |
| 40 | - if ($resolveRecipients->status == SYNC_COMMONSTATUS_SUCCESS && !empty($resolveRecipients->response)) { |
|
| 41 | - foreach ($resolveRecipients->response as $i => $response) { |
|
| 42 | - self::$encoder->startTag(SYNC_RESOLVERECIPIENTS_RESPONSE); |
|
| 43 | - self::$encoder->startTag(SYNC_RESOLVERECIPIENTS_TO); |
|
| 44 | - self::$encoder->content($response->to); |
|
| 45 | - self::$encoder->endTag(); // SYNC_RESOLVERECIPIENTS_TO |
|
| 40 | + if ($resolveRecipients->status == SYNC_COMMONSTATUS_SUCCESS && !empty($resolveRecipients->response)) { |
|
| 41 | + foreach ($resolveRecipients->response as $i => $response) { |
|
| 42 | + self::$encoder->startTag(SYNC_RESOLVERECIPIENTS_RESPONSE); |
|
| 43 | + self::$encoder->startTag(SYNC_RESOLVERECIPIENTS_TO); |
|
| 44 | + self::$encoder->content($response->to); |
|
| 45 | + self::$encoder->endTag(); // SYNC_RESOLVERECIPIENTS_TO |
|
| 46 | 46 | |
| 47 | - self::$encoder->startTag(SYNC_RESOLVERECIPIENTS_STATUS); |
|
| 48 | - self::$encoder->content($response->status); |
|
| 49 | - self::$encoder->endTag(); // SYNC_RESOLVERECIPIENTS_STATUS |
|
| 47 | + self::$encoder->startTag(SYNC_RESOLVERECIPIENTS_STATUS); |
|
| 48 | + self::$encoder->content($response->status); |
|
| 49 | + self::$encoder->endTag(); // SYNC_RESOLVERECIPIENTS_STATUS |
|
| 50 | 50 | |
| 51 | - // do only if recipient is resolved |
|
| 52 | - if ($response->status != SYNC_RESOLVERECIPSSTATUS_RESPONSE_UNRESOLVEDRECIP && !empty($response->recipient)) { |
|
| 53 | - self::$encoder->startTag(SYNC_RESOLVERECIPIENTS_RECIPIENTCOUNT); |
|
| 54 | - self::$encoder->content(count($response->recipient)); |
|
| 55 | - self::$encoder->endTag(); // SYNC_RESOLVERECIPIENTS_RECIPIENTCOUNT |
|
| 51 | + // do only if recipient is resolved |
|
| 52 | + if ($response->status != SYNC_RESOLVERECIPSSTATUS_RESPONSE_UNRESOLVEDRECIP && !empty($response->recipient)) { |
|
| 53 | + self::$encoder->startTag(SYNC_RESOLVERECIPIENTS_RECIPIENTCOUNT); |
|
| 54 | + self::$encoder->content(count($response->recipient)); |
|
| 55 | + self::$encoder->endTag(); // SYNC_RESOLVERECIPIENTS_RECIPIENTCOUNT |
|
| 56 | 56 | |
| 57 | - foreach ($response->recipient as $recipient) { |
|
| 58 | - self::$encoder->startTag(SYNC_RESOLVERECIPIENTS_RECIPIENT); |
|
| 59 | - $recipient->Encode(self::$encoder); |
|
| 60 | - self::$encoder->endTag(); // SYNC_RESOLVERECIPIENTS_RECIPIENT |
|
| 61 | - } |
|
| 62 | - } |
|
| 63 | - self::$encoder->endTag(); // SYNC_RESOLVERECIPIENTS_RESPONSE |
|
| 64 | - } |
|
| 65 | - } |
|
| 57 | + foreach ($response->recipient as $recipient) { |
|
| 58 | + self::$encoder->startTag(SYNC_RESOLVERECIPIENTS_RECIPIENT); |
|
| 59 | + $recipient->Encode(self::$encoder); |
|
| 60 | + self::$encoder->endTag(); // SYNC_RESOLVERECIPIENTS_RECIPIENT |
|
| 61 | + } |
|
| 62 | + } |
|
| 63 | + self::$encoder->endTag(); // SYNC_RESOLVERECIPIENTS_RESPONSE |
|
| 64 | + } |
|
| 65 | + } |
|
| 66 | 66 | |
| 67 | - self::$encoder->endTag(); // SYNC_RESOLVERECIPIENTS_RESOLVERECIPIENTS |
|
| 67 | + self::$encoder->endTag(); // SYNC_RESOLVERECIPIENTS_RESOLVERECIPIENTS |
|
| 68 | 68 | |
| 69 | - return true; |
|
| 70 | - } |
|
| 69 | + return true; |
|
| 70 | + } |
|
| 71 | 71 | } |
@@ -8,512 +8,512 @@ |
||
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | 10 | class Search extends RequestProcessor { |
| 11 | - /** |
|
| 12 | - * Handles the Search command. |
|
| 13 | - * |
|
| 14 | - * @param int $commandCode |
|
| 15 | - * |
|
| 16 | - * @return bool |
|
| 17 | - */ |
|
| 18 | - public function Handle($commandCode) { |
|
| 19 | - $searchrange = '0'; |
|
| 20 | - $searchpicture = false; |
|
| 21 | - $cpo = new ContentParameters(); |
|
| 22 | - |
|
| 23 | - if (!self::$decoder->getElementStartTag(SYNC_SEARCH_SEARCH)) { |
|
| 24 | - return false; |
|
| 25 | - } |
|
| 26 | - |
|
| 27 | - // TODO check: possible to search in other stores? |
|
| 28 | - if (!self::$decoder->getElementStartTag(SYNC_SEARCH_STORE)) { |
|
| 29 | - return false; |
|
| 30 | - } |
|
| 31 | - |
|
| 32 | - if (!self::$decoder->getElementStartTag(SYNC_SEARCH_NAME)) { |
|
| 33 | - return false; |
|
| 34 | - } |
|
| 35 | - $searchname = strtoupper(self::$decoder->getElementContent()); |
|
| 36 | - if (!self::$decoder->getElementEndTag()) { |
|
| 37 | - return false; |
|
| 38 | - } |
|
| 39 | - |
|
| 40 | - if (!self::$decoder->getElementStartTag(SYNC_SEARCH_QUERY)) { |
|
| 41 | - return false; |
|
| 42 | - } |
|
| 43 | - |
|
| 44 | - // check if it is a content of an element (= GAL search) |
|
| 45 | - // or a starttag (= mailbox or documentlibrary search) |
|
| 46 | - $searchquery = self::$decoder->getElementContent(); |
|
| 47 | - if ($searchquery && !self::$decoder->getElementEndTag()) { |
|
| 48 | - return false; |
|
| 49 | - } |
|
| 50 | - |
|
| 51 | - if ($searchquery === false) { |
|
| 52 | - $cpo->SetSearchName($searchname); |
|
| 53 | - if (self::$decoder->getElementStartTag(SYNC_SEARCH_AND)) { |
|
| 54 | - if (self::$decoder->getElementStartTag(SYNC_FOLDERID)) { |
|
| 55 | - $searchfolderid = self::$decoder->getElementContent(); |
|
| 56 | - $cpo->SetSearchFolderid($searchfolderid); |
|
| 57 | - if (!self::$decoder->getElementEndTag()) { // SYNC_FOLDERTYPE |
|
| 58 | - return false; |
|
| 59 | - } |
|
| 60 | - } |
|
| 61 | - |
|
| 62 | - if (self::$decoder->getElementStartTag(SYNC_FOLDERTYPE)) { |
|
| 63 | - $searchclass = self::$decoder->getElementContent(); |
|
| 64 | - $cpo->SetSearchClass($searchclass); |
|
| 65 | - if (!self::$decoder->getElementEndTag()) { // SYNC_FOLDERTYPE |
|
| 66 | - return false; |
|
| 67 | - } |
|
| 68 | - } |
|
| 69 | - |
|
| 70 | - if (self::$decoder->getElementStartTag(SYNC_FOLDERID)) { |
|
| 71 | - $searchfolderid = self::$decoder->getElementContent(); |
|
| 72 | - $cpo->SetSearchFolderid($searchfolderid); |
|
| 73 | - if (!self::$decoder->getElementEndTag()) { // SYNC_FOLDERTYPE |
|
| 74 | - return false; |
|
| 75 | - } |
|
| 76 | - } |
|
| 77 | - |
|
| 78 | - if (self::$decoder->getElementStartTag(SYNC_SEARCH_FREETEXT)) { |
|
| 79 | - $searchfreetext = self::$decoder->getElementContent(); |
|
| 80 | - $cpo->SetSearchFreeText($searchfreetext); |
|
| 81 | - if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_FREETEXT |
|
| 82 | - return false; |
|
| 83 | - } |
|
| 84 | - } |
|
| 85 | - |
|
| 86 | - // TODO - review |
|
| 87 | - if (self::$decoder->getElementStartTag(SYNC_SEARCH_GREATERTHAN)) { |
|
| 88 | - if (self::$decoder->getElementStartTag(SYNC_POOMMAIL_DATERECEIVED)) { |
|
| 89 | - $datereceivedgreater = true; |
|
| 90 | - if (($dam = self::$decoder->getElementContent()) !== false) { |
|
| 91 | - $datereceivedgreater = true; |
|
| 92 | - if (!self::$decoder->getElementEndTag()) { |
|
| 93 | - return false; |
|
| 94 | - } |
|
| 95 | - } |
|
| 96 | - $cpo->SetSearchDateReceivedGreater($datereceivedgreater); |
|
| 97 | - } |
|
| 98 | - |
|
| 99 | - if (self::$decoder->getElementStartTag(SYNC_SEARCH_VALUE)) { |
|
| 100 | - $searchvalue = self::$decoder->getElementContent(); |
|
| 101 | - $cpo->SetSearchValueGreater($searchvalue); |
|
| 102 | - if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_VALUE |
|
| 103 | - return false; |
|
| 104 | - } |
|
| 105 | - } |
|
| 106 | - |
|
| 107 | - if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_GREATERTHAN |
|
| 108 | - return false; |
|
| 109 | - } |
|
| 110 | - } |
|
| 111 | - |
|
| 112 | - if (self::$decoder->getElementStartTag(SYNC_SEARCH_LESSTHAN)) { |
|
| 113 | - if (self::$decoder->getElementStartTag(SYNC_POOMMAIL_DATERECEIVED)) { |
|
| 114 | - $datereceivedless = true; |
|
| 115 | - if (($dam = self::$decoder->getElementContent()) !== false) { |
|
| 116 | - $datereceivedless = true; |
|
| 117 | - if (!self::$decoder->getElementEndTag()) { |
|
| 118 | - return false; |
|
| 119 | - } |
|
| 120 | - } |
|
| 121 | - $cpo->SetSearchDateReceivedLess($datereceivedless); |
|
| 122 | - } |
|
| 123 | - |
|
| 124 | - if (self::$decoder->getElementStartTag(SYNC_SEARCH_VALUE)) { |
|
| 125 | - $searchvalue = self::$decoder->getElementContent(); |
|
| 126 | - $cpo->SetSearchValueLess($searchvalue); |
|
| 127 | - if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_VALUE |
|
| 128 | - return false; |
|
| 129 | - } |
|
| 130 | - } |
|
| 131 | - |
|
| 132 | - if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_LESSTHAN |
|
| 133 | - return false; |
|
| 134 | - } |
|
| 135 | - } |
|
| 136 | - |
|
| 137 | - if (self::$decoder->getElementStartTag(SYNC_SEARCH_FREETEXT)) { |
|
| 138 | - $searchfreetext = self::$decoder->getElementContent(); |
|
| 139 | - $cpo->SetSearchFreeText($searchfreetext); |
|
| 140 | - if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_FREETEXT |
|
| 141 | - return false; |
|
| 142 | - } |
|
| 143 | - } |
|
| 144 | - |
|
| 145 | - if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_AND |
|
| 146 | - return false; |
|
| 147 | - } |
|
| 148 | - } |
|
| 149 | - elseif (self::$decoder->getElementStartTag(SYNC_SEARCH_EQUALTO)) { |
|
| 150 | - // linkid can be an empty tag as well as have value |
|
| 151 | - if (self::$decoder->getElementStartTag(SYNC_DOCUMENTLIBRARY_LINKID)) { |
|
| 152 | - if (($linkId = self::$decoder->getElementContent()) !== false) { |
|
| 153 | - $cpo->SetLinkId($linkId); |
|
| 154 | - if (!self::$decoder->getElementEndTag()) { // SYNC_DOCUMENTLIBRARY_LINKID |
|
| 155 | - return false; |
|
| 156 | - } |
|
| 157 | - } |
|
| 158 | - } |
|
| 159 | - |
|
| 160 | - if (self::$decoder->getElementStartTag(SYNC_SEARCH_VALUE)) { |
|
| 161 | - $searchvalue = self::$decoder->getElementContent(); |
|
| 162 | - $cpo->SetSearchValueEqualTo($searchvalue); |
|
| 163 | - if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_VALUE |
|
| 164 | - return false; |
|
| 165 | - } |
|
| 166 | - } |
|
| 167 | - |
|
| 168 | - if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_EQUALTO |
|
| 169 | - return false; |
|
| 170 | - } |
|
| 171 | - } |
|
| 172 | - |
|
| 173 | - if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_QUERY |
|
| 174 | - return false; |
|
| 175 | - } |
|
| 176 | - } |
|
| 177 | - |
|
| 178 | - if (self::$decoder->getElementStartTag(SYNC_SEARCH_OPTIONS)) { |
|
| 179 | - WBXMLDecoder::ResetInWhile("searchOptions"); |
|
| 180 | - while (WBXMLDecoder::InWhile("searchOptions")) { |
|
| 181 | - if (self::$decoder->getElementStartTag(SYNC_SEARCH_RANGE)) { |
|
| 182 | - $searchrange = self::$decoder->getElementContent(); |
|
| 183 | - $cpo->SetSearchRange($searchrange); |
|
| 184 | - if (!self::$decoder->getElementEndTag()) { |
|
| 185 | - return false; |
|
| 186 | - } |
|
| 187 | - } |
|
| 188 | - |
|
| 189 | - if (self::$decoder->getElementStartTag(SYNC_SEARCH_REBUILDRESULTS)) { |
|
| 190 | - $rebuildresults = true; |
|
| 191 | - if (($dam = self::$decoder->getElementContent()) !== false) { |
|
| 192 | - $rebuildresults = true; |
|
| 193 | - if (!self::$decoder->getElementEndTag()) { |
|
| 194 | - return false; |
|
| 195 | - } |
|
| 196 | - } |
|
| 197 | - $cpo->SetSearchRebuildResults($rebuildresults); |
|
| 198 | - } |
|
| 199 | - |
|
| 200 | - if (self::$decoder->getElementStartTag(SYNC_SEARCH_DEEPTRAVERSAL)) { |
|
| 201 | - $deeptraversal = true; |
|
| 202 | - if (($dam = self::$decoder->getElementContent()) !== false) { |
|
| 203 | - $deeptraversal = true; |
|
| 204 | - if (!self::$decoder->getElementEndTag()) { |
|
| 205 | - return false; |
|
| 206 | - } |
|
| 207 | - } |
|
| 208 | - $cpo->SetSearchDeepTraversal($deeptraversal); |
|
| 209 | - } |
|
| 210 | - |
|
| 211 | - if (self::$decoder->getElementStartTag(SYNC_MIMESUPPORT)) { |
|
| 212 | - $cpo->SetMimeSupport(self::$decoder->getElementContent()); |
|
| 213 | - if (!self::$decoder->getElementEndTag()) { |
|
| 214 | - return false; |
|
| 215 | - } |
|
| 216 | - } |
|
| 217 | - |
|
| 218 | - // TODO body preferences |
|
| 219 | - while (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_BODYPREFERENCE)) { |
|
| 220 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TYPE)) { |
|
| 221 | - $bptype = self::$decoder->getElementContent(); |
|
| 222 | - $cpo->BodyPreference($bptype); |
|
| 223 | - if (!self::$decoder->getElementEndTag()) { |
|
| 224 | - return false; |
|
| 225 | - } |
|
| 226 | - } |
|
| 227 | - |
|
| 228 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TRUNCATIONSIZE)) { |
|
| 229 | - $cpo->BodyPreference($bptype)->SetTruncationSize(self::$decoder->getElementContent()); |
|
| 230 | - if (!self::$decoder->getElementEndTag()) { |
|
| 231 | - return false; |
|
| 232 | - } |
|
| 233 | - } |
|
| 234 | - |
|
| 235 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_ALLORNONE)) { |
|
| 236 | - $cpo->BodyPreference($bptype)->SetAllOrNone(self::$decoder->getElementContent()); |
|
| 237 | - if (!self::$decoder->getElementEndTag()) { |
|
| 238 | - return false; |
|
| 239 | - } |
|
| 240 | - } |
|
| 241 | - |
|
| 242 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_PREVIEW)) { |
|
| 243 | - $cpo->BodyPreference($bptype)->SetPreview(self::$decoder->getElementContent()); |
|
| 244 | - if (!self::$decoder->getElementEndTag()) { |
|
| 245 | - return false; |
|
| 246 | - } |
|
| 247 | - } |
|
| 248 | - |
|
| 249 | - if (!self::$decoder->getElementEndTag()) { |
|
| 250 | - return false; |
|
| 251 | - } |
|
| 252 | - } |
|
| 253 | - |
|
| 254 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_BODYPARTPREFERENCE)) { |
|
| 255 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TYPE)) { |
|
| 256 | - $bpptype = self::$decoder->getElementContent(); |
|
| 257 | - $cpo->BodyPartPreference($bpptype); |
|
| 258 | - if (!self::$decoder->getElementEndTag()) { |
|
| 259 | - return false; |
|
| 260 | - } |
|
| 261 | - } |
|
| 262 | - |
|
| 263 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TRUNCATIONSIZE)) { |
|
| 264 | - $cpo->BodyPartPreference($bpptype)->SetTruncationSize(self::$decoder->getElementContent()); |
|
| 265 | - if (!self::$decoder->getElementEndTag()) { |
|
| 266 | - return false; |
|
| 267 | - } |
|
| 268 | - } |
|
| 269 | - |
|
| 270 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_ALLORNONE)) { |
|
| 271 | - $cpo->BodyPartPreference($bpptype)->SetAllOrNone(self::$decoder->getElementContent()); |
|
| 272 | - if (!self::$decoder->getElementEndTag()) { |
|
| 273 | - return false; |
|
| 274 | - } |
|
| 275 | - } |
|
| 276 | - |
|
| 277 | - if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_PREVIEW)) { |
|
| 278 | - $cpo->BodyPartPreference($bpptype)->SetPreview(self::$decoder->getElementContent()); |
|
| 279 | - if (!self::$decoder->getElementEndTag()) { |
|
| 280 | - return false; |
|
| 281 | - } |
|
| 282 | - } |
|
| 283 | - |
|
| 284 | - if (!self::$decoder->getElementEndTag()) { |
|
| 285 | - return false; |
|
| 286 | - } |
|
| 287 | - } |
|
| 288 | - |
|
| 289 | - if (self::$decoder->getElementStartTag(SYNC_RIGHTSMANAGEMENT_SUPPORT)) { |
|
| 290 | - $cpo->SetRmSupport(self::$decoder->getElementContent()); |
|
| 291 | - if (!self::$decoder->getElementEndTag()) { |
|
| 292 | - return false; |
|
| 293 | - } |
|
| 294 | - } |
|
| 295 | - |
|
| 296 | - if (self::$decoder->getElementStartTag(SYNC_SEARCH_PICTURE)) { // TODO - do something with maxsize and maxpictures in the backend |
|
| 297 | - $searchpicture = new SyncResolveRecipientsPicture(); |
|
| 298 | - if (self::$decoder->getElementStartTag(SYNC_SEARCH_MAXSIZE)) { |
|
| 299 | - $searchpicture->maxsize = self::$decoder->getElementContent(); |
|
| 300 | - if (!self::$decoder->getElementEndTag()) { |
|
| 301 | - return false; |
|
| 302 | - } |
|
| 303 | - } |
|
| 304 | - |
|
| 305 | - if (self::$decoder->getElementStartTag(SYNC_SEARCH_MAXPICTURES)) { |
|
| 306 | - $searchpicture->maxpictures = self::$decoder->getElementContent(); |
|
| 307 | - if (!self::$decoder->getElementEndTag()) { |
|
| 308 | - return false; |
|
| 309 | - } |
|
| 310 | - } |
|
| 311 | - |
|
| 312 | - // iOs devices send empty picture tag: <Search:Picture/> |
|
| 313 | - if (($sp = self::$decoder->getElementContent()) !== false) { |
|
| 314 | - if (!self::$decoder->getElementEndTag()) { |
|
| 315 | - return false; |
|
| 316 | - } |
|
| 317 | - } |
|
| 318 | - } |
|
| 319 | - |
|
| 320 | - $e = self::$decoder->peek(); |
|
| 321 | - if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { |
|
| 322 | - self::$decoder->getElementEndTag(); |
|
| 323 | - |
|
| 324 | - break; |
|
| 325 | - } |
|
| 326 | - } |
|
| 327 | - } |
|
| 328 | - if (!self::$decoder->getElementEndTag()) { // store |
|
| 329 | - return false; |
|
| 330 | - } |
|
| 331 | - |
|
| 332 | - if (!self::$decoder->getElementEndTag()) { // search |
|
| 333 | - return false; |
|
| 334 | - } |
|
| 335 | - |
|
| 336 | - // get SearchProvider |
|
| 337 | - $searchprovider = GSync::GetBackend()->GetSearchProvider(); |
|
| 338 | - $status = SYNC_SEARCHSTATUS_SUCCESS; |
|
| 339 | - $rows = []; |
|
| 340 | - |
|
| 341 | - // TODO support other searches |
|
| 342 | - if ($searchprovider->SupportsType($searchname)) { |
|
| 343 | - $storestatus = SYNC_SEARCHSTATUS_STORE_SUCCESS; |
|
| 344 | - |
|
| 345 | - try { |
|
| 346 | - if ($searchname == ISearchProvider::SEARCH_GAL) { |
|
| 347 | - // get search results from the searchprovider |
|
| 348 | - $rows = $searchprovider->GetGALSearchResults($searchquery, $searchrange, $searchpicture); |
|
| 349 | - } |
|
| 350 | - elseif ($searchname == ISearchProvider::SEARCH_MAILBOX) { |
|
| 351 | - $backendFolderId = self::$deviceManager->GetBackendIdForFolderId($cpo->GetSearchFolderid()); |
|
| 352 | - $cpo->SetSearchFolderid($backendFolderId); |
|
| 353 | - $rows = $searchprovider->GetMailboxSearchResults($cpo); |
|
| 354 | - } |
|
| 355 | - } |
|
| 356 | - catch (StatusException $stex) { |
|
| 357 | - $storestatus = $stex->getCode(); |
|
| 358 | - } |
|
| 359 | - } |
|
| 360 | - else { |
|
| 361 | - $rows = ['searchtotal' => 0]; |
|
| 362 | - $status = SYNC_SEARCHSTATUS_SERVERERROR; |
|
| 363 | - SLog::Write(LOGLEVEL_WARN, sprintf("Searchtype '%s' is not supported.", $searchname)); |
|
| 364 | - self::$topCollector->AnnounceInformation(sprintf("Unsupported type '%s''", $searchname), true); |
|
| 365 | - } |
|
| 366 | - $searchprovider->Disconnect(); |
|
| 367 | - |
|
| 368 | - self::$topCollector->AnnounceInformation(sprintf("'%s' search found %d results", $searchname, (isset($rows['searchtotal']) ? $rows['searchtotal'] : 0)), true); |
|
| 369 | - |
|
| 370 | - self::$encoder->startWBXML(); |
|
| 371 | - self::$encoder->startTag(SYNC_SEARCH_SEARCH); |
|
| 372 | - |
|
| 373 | - self::$encoder->startTag(SYNC_SEARCH_STATUS); |
|
| 374 | - self::$encoder->content($status); |
|
| 375 | - self::$encoder->endTag(); |
|
| 376 | - |
|
| 377 | - if ($status == SYNC_SEARCHSTATUS_SUCCESS) { |
|
| 378 | - self::$encoder->startTag(SYNC_SEARCH_RESPONSE); |
|
| 379 | - self::$encoder->startTag(SYNC_SEARCH_STORE); |
|
| 380 | - |
|
| 381 | - self::$encoder->startTag(SYNC_SEARCH_STATUS); |
|
| 382 | - self::$encoder->content($storestatus); |
|
| 383 | - self::$encoder->endTag(); |
|
| 384 | - |
|
| 385 | - if (isset($rows['range'])) { |
|
| 386 | - $searchrange = $rows['range']; |
|
| 387 | - unset($rows['range']); |
|
| 388 | - } |
|
| 389 | - if (isset($rows['searchtotal'])) { |
|
| 390 | - $searchtotal = $rows['searchtotal']; |
|
| 391 | - unset($rows['searchtotal']); |
|
| 392 | - } |
|
| 393 | - if ($searchname == ISearchProvider::SEARCH_GAL) { |
|
| 394 | - if (is_array($rows) && !empty($rows)) { |
|
| 395 | - foreach ($rows as $u) { |
|
| 396 | - self::$encoder->startTag(SYNC_SEARCH_RESULT); |
|
| 397 | - self::$encoder->startTag(SYNC_SEARCH_PROPERTIES); |
|
| 398 | - |
|
| 399 | - self::$encoder->startTag(SYNC_GAL_DISPLAYNAME); |
|
| 400 | - self::$encoder->content((isset($u[SYNC_GAL_DISPLAYNAME])) ? $u[SYNC_GAL_DISPLAYNAME] : "No name"); |
|
| 401 | - self::$encoder->endTag(); |
|
| 402 | - |
|
| 403 | - if (isset($u[SYNC_GAL_PHONE])) { |
|
| 404 | - self::$encoder->startTag(SYNC_GAL_PHONE); |
|
| 405 | - self::$encoder->content($u[SYNC_GAL_PHONE]); |
|
| 406 | - self::$encoder->endTag(); |
|
| 407 | - } |
|
| 408 | - |
|
| 409 | - if (isset($u[SYNC_GAL_OFFICE])) { |
|
| 410 | - self::$encoder->startTag(SYNC_GAL_OFFICE); |
|
| 411 | - self::$encoder->content($u[SYNC_GAL_OFFICE]); |
|
| 412 | - self::$encoder->endTag(); |
|
| 413 | - } |
|
| 414 | - |
|
| 415 | - if (isset($u[SYNC_GAL_TITLE])) { |
|
| 416 | - self::$encoder->startTag(SYNC_GAL_TITLE); |
|
| 417 | - self::$encoder->content($u[SYNC_GAL_TITLE]); |
|
| 418 | - self::$encoder->endTag(); |
|
| 419 | - } |
|
| 420 | - |
|
| 421 | - if (isset($u[SYNC_GAL_COMPANY])) { |
|
| 422 | - self::$encoder->startTag(SYNC_GAL_COMPANY); |
|
| 423 | - self::$encoder->content($u[SYNC_GAL_COMPANY]); |
|
| 424 | - self::$encoder->endTag(); |
|
| 425 | - } |
|
| 426 | - |
|
| 427 | - if (isset($u[SYNC_GAL_ALIAS])) { |
|
| 428 | - self::$encoder->startTag(SYNC_GAL_ALIAS); |
|
| 429 | - self::$encoder->content($u[SYNC_GAL_ALIAS]); |
|
| 430 | - self::$encoder->endTag(); |
|
| 431 | - } |
|
| 432 | - |
|
| 433 | - // Always send the firstname, even empty. Nokia needs this to display the entry |
|
| 434 | - self::$encoder->startTag(SYNC_GAL_FIRSTNAME); |
|
| 435 | - self::$encoder->content((isset($u[SYNC_GAL_FIRSTNAME])) ? $u[SYNC_GAL_FIRSTNAME] : ""); |
|
| 436 | - self::$encoder->endTag(); |
|
| 437 | - |
|
| 438 | - self::$encoder->startTag(SYNC_GAL_LASTNAME); |
|
| 439 | - self::$encoder->content((isset($u[SYNC_GAL_LASTNAME])) ? $u[SYNC_GAL_LASTNAME] : "No name"); |
|
| 440 | - self::$encoder->endTag(); |
|
| 441 | - |
|
| 442 | - if (isset($u[SYNC_GAL_HOMEPHONE])) { |
|
| 443 | - self::$encoder->startTag(SYNC_GAL_HOMEPHONE); |
|
| 444 | - self::$encoder->content($u[SYNC_GAL_HOMEPHONE]); |
|
| 445 | - self::$encoder->endTag(); |
|
| 446 | - } |
|
| 447 | - |
|
| 448 | - if (isset($u[SYNC_GAL_MOBILEPHONE])) { |
|
| 449 | - self::$encoder->startTag(SYNC_GAL_MOBILEPHONE); |
|
| 450 | - self::$encoder->content($u[SYNC_GAL_MOBILEPHONE]); |
|
| 451 | - self::$encoder->endTag(); |
|
| 452 | - } |
|
| 453 | - |
|
| 454 | - self::$encoder->startTag(SYNC_GAL_EMAILADDRESS); |
|
| 455 | - self::$encoder->content((isset($u[SYNC_GAL_EMAILADDRESS])) ? $u[SYNC_GAL_EMAILADDRESS] : ""); |
|
| 456 | - self::$encoder->endTag(); |
|
| 457 | - |
|
| 458 | - if (isset($u[SYNC_GAL_PICTURE])) { |
|
| 459 | - self::$encoder->startTag(SYNC_GAL_PICTURE); |
|
| 460 | - self::$encoder->startTag(SYNC_GAL_STATUS); |
|
| 461 | - self::$encoder->content(SYNC_SEARCHSTATUS_PICTURE_SUCCESS); // FIXME: status code |
|
| 462 | - self::$encoder->endTag(); // SYNC_SEARCH_STATUS |
|
| 463 | - |
|
| 464 | - self::$encoder->startTag(SYNC_GAL_DATA); |
|
| 465 | - self::$encoder->contentStream($u[SYNC_GAL_PICTURE], false, true); |
|
| 466 | - self::$encoder->endTag(); // SYNC_GAL_DATA |
|
| 467 | - self::$encoder->endTag(); // SYNC_GAL_PICTURE |
|
| 468 | - } |
|
| 469 | - |
|
| 470 | - self::$encoder->endTag(); // result |
|
| 471 | - self::$encoder->endTag(); // properties |
|
| 472 | - } |
|
| 473 | - } |
|
| 474 | - } |
|
| 475 | - elseif ($searchname == ISearchProvider::SEARCH_MAILBOX) { |
|
| 476 | - foreach ($rows as $u) { |
|
| 477 | - // TODO: unclear if any clients *require* the folder id where the message is located (it's not available anymore) |
|
| 478 | - // $folderid = self::$deviceManager->GetFolderIdForBackendId($u['folderid']); |
|
| 479 | - |
|
| 480 | - self::$encoder->startTag(SYNC_SEARCH_RESULT); |
|
| 481 | - self::$encoder->startTag(SYNC_FOLDERTYPE); |
|
| 482 | - self::$encoder->content($u['class']); |
|
| 483 | - self::$encoder->endTag(); |
|
| 484 | - self::$encoder->startTag(SYNC_SEARCH_LONGID); |
|
| 485 | - self::$encoder->content($u['longid']); |
|
| 486 | - self::$encoder->endTag(); |
|
| 487 | - // self::$encoder->startTag(SYNC_FOLDERID); |
|
| 488 | - // self::$encoder->content($folderid); |
|
| 489 | - // self::$encoder->endTag(); |
|
| 490 | - |
|
| 491 | - self::$encoder->startTag(SYNC_SEARCH_PROPERTIES); |
|
| 492 | - $message = self::$backend->Fetch(false, $u['longid'], $cpo); |
|
| 493 | - $message->Encode(self::$encoder); |
|
| 494 | - |
|
| 495 | - self::$encoder->endTag(); // result |
|
| 496 | - self::$encoder->endTag(); // properties |
|
| 497 | - } |
|
| 498 | - } |
|
| 499 | - // it seems that android 4 requires range and searchtotal |
|
| 500 | - // or it won't display the search results |
|
| 501 | - if (isset($searchrange)) { |
|
| 502 | - self::$encoder->startTag(SYNC_SEARCH_RANGE); |
|
| 503 | - self::$encoder->content($searchrange); |
|
| 504 | - self::$encoder->endTag(); |
|
| 505 | - } |
|
| 506 | - if (isset($searchtotal) && $searchtotal > 0) { |
|
| 507 | - self::$encoder->startTag(SYNC_SEARCH_TOTAL); |
|
| 508 | - self::$encoder->content($searchtotal); |
|
| 509 | - self::$encoder->endTag(); |
|
| 510 | - } |
|
| 511 | - |
|
| 512 | - self::$encoder->endTag(); // store |
|
| 513 | - self::$encoder->endTag(); // response |
|
| 514 | - } |
|
| 515 | - self::$encoder->endTag(); // search |
|
| 516 | - |
|
| 517 | - return true; |
|
| 518 | - } |
|
| 11 | + /** |
|
| 12 | + * Handles the Search command. |
|
| 13 | + * |
|
| 14 | + * @param int $commandCode |
|
| 15 | + * |
|
| 16 | + * @return bool |
|
| 17 | + */ |
|
| 18 | + public function Handle($commandCode) { |
|
| 19 | + $searchrange = '0'; |
|
| 20 | + $searchpicture = false; |
|
| 21 | + $cpo = new ContentParameters(); |
|
| 22 | + |
|
| 23 | + if (!self::$decoder->getElementStartTag(SYNC_SEARCH_SEARCH)) { |
|
| 24 | + return false; |
|
| 25 | + } |
|
| 26 | + |
|
| 27 | + // TODO check: possible to search in other stores? |
|
| 28 | + if (!self::$decoder->getElementStartTag(SYNC_SEARCH_STORE)) { |
|
| 29 | + return false; |
|
| 30 | + } |
|
| 31 | + |
|
| 32 | + if (!self::$decoder->getElementStartTag(SYNC_SEARCH_NAME)) { |
|
| 33 | + return false; |
|
| 34 | + } |
|
| 35 | + $searchname = strtoupper(self::$decoder->getElementContent()); |
|
| 36 | + if (!self::$decoder->getElementEndTag()) { |
|
| 37 | + return false; |
|
| 38 | + } |
|
| 39 | + |
|
| 40 | + if (!self::$decoder->getElementStartTag(SYNC_SEARCH_QUERY)) { |
|
| 41 | + return false; |
|
| 42 | + } |
|
| 43 | + |
|
| 44 | + // check if it is a content of an element (= GAL search) |
|
| 45 | + // or a starttag (= mailbox or documentlibrary search) |
|
| 46 | + $searchquery = self::$decoder->getElementContent(); |
|
| 47 | + if ($searchquery && !self::$decoder->getElementEndTag()) { |
|
| 48 | + return false; |
|
| 49 | + } |
|
| 50 | + |
|
| 51 | + if ($searchquery === false) { |
|
| 52 | + $cpo->SetSearchName($searchname); |
|
| 53 | + if (self::$decoder->getElementStartTag(SYNC_SEARCH_AND)) { |
|
| 54 | + if (self::$decoder->getElementStartTag(SYNC_FOLDERID)) { |
|
| 55 | + $searchfolderid = self::$decoder->getElementContent(); |
|
| 56 | + $cpo->SetSearchFolderid($searchfolderid); |
|
| 57 | + if (!self::$decoder->getElementEndTag()) { // SYNC_FOLDERTYPE |
|
| 58 | + return false; |
|
| 59 | + } |
|
| 60 | + } |
|
| 61 | + |
|
| 62 | + if (self::$decoder->getElementStartTag(SYNC_FOLDERTYPE)) { |
|
| 63 | + $searchclass = self::$decoder->getElementContent(); |
|
| 64 | + $cpo->SetSearchClass($searchclass); |
|
| 65 | + if (!self::$decoder->getElementEndTag()) { // SYNC_FOLDERTYPE |
|
| 66 | + return false; |
|
| 67 | + } |
|
| 68 | + } |
|
| 69 | + |
|
| 70 | + if (self::$decoder->getElementStartTag(SYNC_FOLDERID)) { |
|
| 71 | + $searchfolderid = self::$decoder->getElementContent(); |
|
| 72 | + $cpo->SetSearchFolderid($searchfolderid); |
|
| 73 | + if (!self::$decoder->getElementEndTag()) { // SYNC_FOLDERTYPE |
|
| 74 | + return false; |
|
| 75 | + } |
|
| 76 | + } |
|
| 77 | + |
|
| 78 | + if (self::$decoder->getElementStartTag(SYNC_SEARCH_FREETEXT)) { |
|
| 79 | + $searchfreetext = self::$decoder->getElementContent(); |
|
| 80 | + $cpo->SetSearchFreeText($searchfreetext); |
|
| 81 | + if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_FREETEXT |
|
| 82 | + return false; |
|
| 83 | + } |
|
| 84 | + } |
|
| 85 | + |
|
| 86 | + // TODO - review |
|
| 87 | + if (self::$decoder->getElementStartTag(SYNC_SEARCH_GREATERTHAN)) { |
|
| 88 | + if (self::$decoder->getElementStartTag(SYNC_POOMMAIL_DATERECEIVED)) { |
|
| 89 | + $datereceivedgreater = true; |
|
| 90 | + if (($dam = self::$decoder->getElementContent()) !== false) { |
|
| 91 | + $datereceivedgreater = true; |
|
| 92 | + if (!self::$decoder->getElementEndTag()) { |
|
| 93 | + return false; |
|
| 94 | + } |
|
| 95 | + } |
|
| 96 | + $cpo->SetSearchDateReceivedGreater($datereceivedgreater); |
|
| 97 | + } |
|
| 98 | + |
|
| 99 | + if (self::$decoder->getElementStartTag(SYNC_SEARCH_VALUE)) { |
|
| 100 | + $searchvalue = self::$decoder->getElementContent(); |
|
| 101 | + $cpo->SetSearchValueGreater($searchvalue); |
|
| 102 | + if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_VALUE |
|
| 103 | + return false; |
|
| 104 | + } |
|
| 105 | + } |
|
| 106 | + |
|
| 107 | + if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_GREATERTHAN |
|
| 108 | + return false; |
|
| 109 | + } |
|
| 110 | + } |
|
| 111 | + |
|
| 112 | + if (self::$decoder->getElementStartTag(SYNC_SEARCH_LESSTHAN)) { |
|
| 113 | + if (self::$decoder->getElementStartTag(SYNC_POOMMAIL_DATERECEIVED)) { |
|
| 114 | + $datereceivedless = true; |
|
| 115 | + if (($dam = self::$decoder->getElementContent()) !== false) { |
|
| 116 | + $datereceivedless = true; |
|
| 117 | + if (!self::$decoder->getElementEndTag()) { |
|
| 118 | + return false; |
|
| 119 | + } |
|
| 120 | + } |
|
| 121 | + $cpo->SetSearchDateReceivedLess($datereceivedless); |
|
| 122 | + } |
|
| 123 | + |
|
| 124 | + if (self::$decoder->getElementStartTag(SYNC_SEARCH_VALUE)) { |
|
| 125 | + $searchvalue = self::$decoder->getElementContent(); |
|
| 126 | + $cpo->SetSearchValueLess($searchvalue); |
|
| 127 | + if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_VALUE |
|
| 128 | + return false; |
|
| 129 | + } |
|
| 130 | + } |
|
| 131 | + |
|
| 132 | + if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_LESSTHAN |
|
| 133 | + return false; |
|
| 134 | + } |
|
| 135 | + } |
|
| 136 | + |
|
| 137 | + if (self::$decoder->getElementStartTag(SYNC_SEARCH_FREETEXT)) { |
|
| 138 | + $searchfreetext = self::$decoder->getElementContent(); |
|
| 139 | + $cpo->SetSearchFreeText($searchfreetext); |
|
| 140 | + if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_FREETEXT |
|
| 141 | + return false; |
|
| 142 | + } |
|
| 143 | + } |
|
| 144 | + |
|
| 145 | + if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_AND |
|
| 146 | + return false; |
|
| 147 | + } |
|
| 148 | + } |
|
| 149 | + elseif (self::$decoder->getElementStartTag(SYNC_SEARCH_EQUALTO)) { |
|
| 150 | + // linkid can be an empty tag as well as have value |
|
| 151 | + if (self::$decoder->getElementStartTag(SYNC_DOCUMENTLIBRARY_LINKID)) { |
|
| 152 | + if (($linkId = self::$decoder->getElementContent()) !== false) { |
|
| 153 | + $cpo->SetLinkId($linkId); |
|
| 154 | + if (!self::$decoder->getElementEndTag()) { // SYNC_DOCUMENTLIBRARY_LINKID |
|
| 155 | + return false; |
|
| 156 | + } |
|
| 157 | + } |
|
| 158 | + } |
|
| 159 | + |
|
| 160 | + if (self::$decoder->getElementStartTag(SYNC_SEARCH_VALUE)) { |
|
| 161 | + $searchvalue = self::$decoder->getElementContent(); |
|
| 162 | + $cpo->SetSearchValueEqualTo($searchvalue); |
|
| 163 | + if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_VALUE |
|
| 164 | + return false; |
|
| 165 | + } |
|
| 166 | + } |
|
| 167 | + |
|
| 168 | + if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_EQUALTO |
|
| 169 | + return false; |
|
| 170 | + } |
|
| 171 | + } |
|
| 172 | + |
|
| 173 | + if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_QUERY |
|
| 174 | + return false; |
|
| 175 | + } |
|
| 176 | + } |
|
| 177 | + |
|
| 178 | + if (self::$decoder->getElementStartTag(SYNC_SEARCH_OPTIONS)) { |
|
| 179 | + WBXMLDecoder::ResetInWhile("searchOptions"); |
|
| 180 | + while (WBXMLDecoder::InWhile("searchOptions")) { |
|
| 181 | + if (self::$decoder->getElementStartTag(SYNC_SEARCH_RANGE)) { |
|
| 182 | + $searchrange = self::$decoder->getElementContent(); |
|
| 183 | + $cpo->SetSearchRange($searchrange); |
|
| 184 | + if (!self::$decoder->getElementEndTag()) { |
|
| 185 | + return false; |
|
| 186 | + } |
|
| 187 | + } |
|
| 188 | + |
|
| 189 | + if (self::$decoder->getElementStartTag(SYNC_SEARCH_REBUILDRESULTS)) { |
|
| 190 | + $rebuildresults = true; |
|
| 191 | + if (($dam = self::$decoder->getElementContent()) !== false) { |
|
| 192 | + $rebuildresults = true; |
|
| 193 | + if (!self::$decoder->getElementEndTag()) { |
|
| 194 | + return false; |
|
| 195 | + } |
|
| 196 | + } |
|
| 197 | + $cpo->SetSearchRebuildResults($rebuildresults); |
|
| 198 | + } |
|
| 199 | + |
|
| 200 | + if (self::$decoder->getElementStartTag(SYNC_SEARCH_DEEPTRAVERSAL)) { |
|
| 201 | + $deeptraversal = true; |
|
| 202 | + if (($dam = self::$decoder->getElementContent()) !== false) { |
|
| 203 | + $deeptraversal = true; |
|
| 204 | + if (!self::$decoder->getElementEndTag()) { |
|
| 205 | + return false; |
|
| 206 | + } |
|
| 207 | + } |
|
| 208 | + $cpo->SetSearchDeepTraversal($deeptraversal); |
|
| 209 | + } |
|
| 210 | + |
|
| 211 | + if (self::$decoder->getElementStartTag(SYNC_MIMESUPPORT)) { |
|
| 212 | + $cpo->SetMimeSupport(self::$decoder->getElementContent()); |
|
| 213 | + if (!self::$decoder->getElementEndTag()) { |
|
| 214 | + return false; |
|
| 215 | + } |
|
| 216 | + } |
|
| 217 | + |
|
| 218 | + // TODO body preferences |
|
| 219 | + while (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_BODYPREFERENCE)) { |
|
| 220 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TYPE)) { |
|
| 221 | + $bptype = self::$decoder->getElementContent(); |
|
| 222 | + $cpo->BodyPreference($bptype); |
|
| 223 | + if (!self::$decoder->getElementEndTag()) { |
|
| 224 | + return false; |
|
| 225 | + } |
|
| 226 | + } |
|
| 227 | + |
|
| 228 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TRUNCATIONSIZE)) { |
|
| 229 | + $cpo->BodyPreference($bptype)->SetTruncationSize(self::$decoder->getElementContent()); |
|
| 230 | + if (!self::$decoder->getElementEndTag()) { |
|
| 231 | + return false; |
|
| 232 | + } |
|
| 233 | + } |
|
| 234 | + |
|
| 235 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_ALLORNONE)) { |
|
| 236 | + $cpo->BodyPreference($bptype)->SetAllOrNone(self::$decoder->getElementContent()); |
|
| 237 | + if (!self::$decoder->getElementEndTag()) { |
|
| 238 | + return false; |
|
| 239 | + } |
|
| 240 | + } |
|
| 241 | + |
|
| 242 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_PREVIEW)) { |
|
| 243 | + $cpo->BodyPreference($bptype)->SetPreview(self::$decoder->getElementContent()); |
|
| 244 | + if (!self::$decoder->getElementEndTag()) { |
|
| 245 | + return false; |
|
| 246 | + } |
|
| 247 | + } |
|
| 248 | + |
|
| 249 | + if (!self::$decoder->getElementEndTag()) { |
|
| 250 | + return false; |
|
| 251 | + } |
|
| 252 | + } |
|
| 253 | + |
|
| 254 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_BODYPARTPREFERENCE)) { |
|
| 255 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TYPE)) { |
|
| 256 | + $bpptype = self::$decoder->getElementContent(); |
|
| 257 | + $cpo->BodyPartPreference($bpptype); |
|
| 258 | + if (!self::$decoder->getElementEndTag()) { |
|
| 259 | + return false; |
|
| 260 | + } |
|
| 261 | + } |
|
| 262 | + |
|
| 263 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TRUNCATIONSIZE)) { |
|
| 264 | + $cpo->BodyPartPreference($bpptype)->SetTruncationSize(self::$decoder->getElementContent()); |
|
| 265 | + if (!self::$decoder->getElementEndTag()) { |
|
| 266 | + return false; |
|
| 267 | + } |
|
| 268 | + } |
|
| 269 | + |
|
| 270 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_ALLORNONE)) { |
|
| 271 | + $cpo->BodyPartPreference($bpptype)->SetAllOrNone(self::$decoder->getElementContent()); |
|
| 272 | + if (!self::$decoder->getElementEndTag()) { |
|
| 273 | + return false; |
|
| 274 | + } |
|
| 275 | + } |
|
| 276 | + |
|
| 277 | + if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_PREVIEW)) { |
|
| 278 | + $cpo->BodyPartPreference($bpptype)->SetPreview(self::$decoder->getElementContent()); |
|
| 279 | + if (!self::$decoder->getElementEndTag()) { |
|
| 280 | + return false; |
|
| 281 | + } |
|
| 282 | + } |
|
| 283 | + |
|
| 284 | + if (!self::$decoder->getElementEndTag()) { |
|
| 285 | + return false; |
|
| 286 | + } |
|
| 287 | + } |
|
| 288 | + |
|
| 289 | + if (self::$decoder->getElementStartTag(SYNC_RIGHTSMANAGEMENT_SUPPORT)) { |
|
| 290 | + $cpo->SetRmSupport(self::$decoder->getElementContent()); |
|
| 291 | + if (!self::$decoder->getElementEndTag()) { |
|
| 292 | + return false; |
|
| 293 | + } |
|
| 294 | + } |
|
| 295 | + |
|
| 296 | + if (self::$decoder->getElementStartTag(SYNC_SEARCH_PICTURE)) { // TODO - do something with maxsize and maxpictures in the backend |
|
| 297 | + $searchpicture = new SyncResolveRecipientsPicture(); |
|
| 298 | + if (self::$decoder->getElementStartTag(SYNC_SEARCH_MAXSIZE)) { |
|
| 299 | + $searchpicture->maxsize = self::$decoder->getElementContent(); |
|
| 300 | + if (!self::$decoder->getElementEndTag()) { |
|
| 301 | + return false; |
|
| 302 | + } |
|
| 303 | + } |
|
| 304 | + |
|
| 305 | + if (self::$decoder->getElementStartTag(SYNC_SEARCH_MAXPICTURES)) { |
|
| 306 | + $searchpicture->maxpictures = self::$decoder->getElementContent(); |
|
| 307 | + if (!self::$decoder->getElementEndTag()) { |
|
| 308 | + return false; |
|
| 309 | + } |
|
| 310 | + } |
|
| 311 | + |
|
| 312 | + // iOs devices send empty picture tag: <Search:Picture/> |
|
| 313 | + if (($sp = self::$decoder->getElementContent()) !== false) { |
|
| 314 | + if (!self::$decoder->getElementEndTag()) { |
|
| 315 | + return false; |
|
| 316 | + } |
|
| 317 | + } |
|
| 318 | + } |
|
| 319 | + |
|
| 320 | + $e = self::$decoder->peek(); |
|
| 321 | + if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { |
|
| 322 | + self::$decoder->getElementEndTag(); |
|
| 323 | + |
|
| 324 | + break; |
|
| 325 | + } |
|
| 326 | + } |
|
| 327 | + } |
|
| 328 | + if (!self::$decoder->getElementEndTag()) { // store |
|
| 329 | + return false; |
|
| 330 | + } |
|
| 331 | + |
|
| 332 | + if (!self::$decoder->getElementEndTag()) { // search |
|
| 333 | + return false; |
|
| 334 | + } |
|
| 335 | + |
|
| 336 | + // get SearchProvider |
|
| 337 | + $searchprovider = GSync::GetBackend()->GetSearchProvider(); |
|
| 338 | + $status = SYNC_SEARCHSTATUS_SUCCESS; |
|
| 339 | + $rows = []; |
|
| 340 | + |
|
| 341 | + // TODO support other searches |
|
| 342 | + if ($searchprovider->SupportsType($searchname)) { |
|
| 343 | + $storestatus = SYNC_SEARCHSTATUS_STORE_SUCCESS; |
|
| 344 | + |
|
| 345 | + try { |
|
| 346 | + if ($searchname == ISearchProvider::SEARCH_GAL) { |
|
| 347 | + // get search results from the searchprovider |
|
| 348 | + $rows = $searchprovider->GetGALSearchResults($searchquery, $searchrange, $searchpicture); |
|
| 349 | + } |
|
| 350 | + elseif ($searchname == ISearchProvider::SEARCH_MAILBOX) { |
|
| 351 | + $backendFolderId = self::$deviceManager->GetBackendIdForFolderId($cpo->GetSearchFolderid()); |
|
| 352 | + $cpo->SetSearchFolderid($backendFolderId); |
|
| 353 | + $rows = $searchprovider->GetMailboxSearchResults($cpo); |
|
| 354 | + } |
|
| 355 | + } |
|
| 356 | + catch (StatusException $stex) { |
|
| 357 | + $storestatus = $stex->getCode(); |
|
| 358 | + } |
|
| 359 | + } |
|
| 360 | + else { |
|
| 361 | + $rows = ['searchtotal' => 0]; |
|
| 362 | + $status = SYNC_SEARCHSTATUS_SERVERERROR; |
|
| 363 | + SLog::Write(LOGLEVEL_WARN, sprintf("Searchtype '%s' is not supported.", $searchname)); |
|
| 364 | + self::$topCollector->AnnounceInformation(sprintf("Unsupported type '%s''", $searchname), true); |
|
| 365 | + } |
|
| 366 | + $searchprovider->Disconnect(); |
|
| 367 | + |
|
| 368 | + self::$topCollector->AnnounceInformation(sprintf("'%s' search found %d results", $searchname, (isset($rows['searchtotal']) ? $rows['searchtotal'] : 0)), true); |
|
| 369 | + |
|
| 370 | + self::$encoder->startWBXML(); |
|
| 371 | + self::$encoder->startTag(SYNC_SEARCH_SEARCH); |
|
| 372 | + |
|
| 373 | + self::$encoder->startTag(SYNC_SEARCH_STATUS); |
|
| 374 | + self::$encoder->content($status); |
|
| 375 | + self::$encoder->endTag(); |
|
| 376 | + |
|
| 377 | + if ($status == SYNC_SEARCHSTATUS_SUCCESS) { |
|
| 378 | + self::$encoder->startTag(SYNC_SEARCH_RESPONSE); |
|
| 379 | + self::$encoder->startTag(SYNC_SEARCH_STORE); |
|
| 380 | + |
|
| 381 | + self::$encoder->startTag(SYNC_SEARCH_STATUS); |
|
| 382 | + self::$encoder->content($storestatus); |
|
| 383 | + self::$encoder->endTag(); |
|
| 384 | + |
|
| 385 | + if (isset($rows['range'])) { |
|
| 386 | + $searchrange = $rows['range']; |
|
| 387 | + unset($rows['range']); |
|
| 388 | + } |
|
| 389 | + if (isset($rows['searchtotal'])) { |
|
| 390 | + $searchtotal = $rows['searchtotal']; |
|
| 391 | + unset($rows['searchtotal']); |
|
| 392 | + } |
|
| 393 | + if ($searchname == ISearchProvider::SEARCH_GAL) { |
|
| 394 | + if (is_array($rows) && !empty($rows)) { |
|
| 395 | + foreach ($rows as $u) { |
|
| 396 | + self::$encoder->startTag(SYNC_SEARCH_RESULT); |
|
| 397 | + self::$encoder->startTag(SYNC_SEARCH_PROPERTIES); |
|
| 398 | + |
|
| 399 | + self::$encoder->startTag(SYNC_GAL_DISPLAYNAME); |
|
| 400 | + self::$encoder->content((isset($u[SYNC_GAL_DISPLAYNAME])) ? $u[SYNC_GAL_DISPLAYNAME] : "No name"); |
|
| 401 | + self::$encoder->endTag(); |
|
| 402 | + |
|
| 403 | + if (isset($u[SYNC_GAL_PHONE])) { |
|
| 404 | + self::$encoder->startTag(SYNC_GAL_PHONE); |
|
| 405 | + self::$encoder->content($u[SYNC_GAL_PHONE]); |
|
| 406 | + self::$encoder->endTag(); |
|
| 407 | + } |
|
| 408 | + |
|
| 409 | + if (isset($u[SYNC_GAL_OFFICE])) { |
|
| 410 | + self::$encoder->startTag(SYNC_GAL_OFFICE); |
|
| 411 | + self::$encoder->content($u[SYNC_GAL_OFFICE]); |
|
| 412 | + self::$encoder->endTag(); |
|
| 413 | + } |
|
| 414 | + |
|
| 415 | + if (isset($u[SYNC_GAL_TITLE])) { |
|
| 416 | + self::$encoder->startTag(SYNC_GAL_TITLE); |
|
| 417 | + self::$encoder->content($u[SYNC_GAL_TITLE]); |
|
| 418 | + self::$encoder->endTag(); |
|
| 419 | + } |
|
| 420 | + |
|
| 421 | + if (isset($u[SYNC_GAL_COMPANY])) { |
|
| 422 | + self::$encoder->startTag(SYNC_GAL_COMPANY); |
|
| 423 | + self::$encoder->content($u[SYNC_GAL_COMPANY]); |
|
| 424 | + self::$encoder->endTag(); |
|
| 425 | + } |
|
| 426 | + |
|
| 427 | + if (isset($u[SYNC_GAL_ALIAS])) { |
|
| 428 | + self::$encoder->startTag(SYNC_GAL_ALIAS); |
|
| 429 | + self::$encoder->content($u[SYNC_GAL_ALIAS]); |
|
| 430 | + self::$encoder->endTag(); |
|
| 431 | + } |
|
| 432 | + |
|
| 433 | + // Always send the firstname, even empty. Nokia needs this to display the entry |
|
| 434 | + self::$encoder->startTag(SYNC_GAL_FIRSTNAME); |
|
| 435 | + self::$encoder->content((isset($u[SYNC_GAL_FIRSTNAME])) ? $u[SYNC_GAL_FIRSTNAME] : ""); |
|
| 436 | + self::$encoder->endTag(); |
|
| 437 | + |
|
| 438 | + self::$encoder->startTag(SYNC_GAL_LASTNAME); |
|
| 439 | + self::$encoder->content((isset($u[SYNC_GAL_LASTNAME])) ? $u[SYNC_GAL_LASTNAME] : "No name"); |
|
| 440 | + self::$encoder->endTag(); |
|
| 441 | + |
|
| 442 | + if (isset($u[SYNC_GAL_HOMEPHONE])) { |
|
| 443 | + self::$encoder->startTag(SYNC_GAL_HOMEPHONE); |
|
| 444 | + self::$encoder->content($u[SYNC_GAL_HOMEPHONE]); |
|
| 445 | + self::$encoder->endTag(); |
|
| 446 | + } |
|
| 447 | + |
|
| 448 | + if (isset($u[SYNC_GAL_MOBILEPHONE])) { |
|
| 449 | + self::$encoder->startTag(SYNC_GAL_MOBILEPHONE); |
|
| 450 | + self::$encoder->content($u[SYNC_GAL_MOBILEPHONE]); |
|
| 451 | + self::$encoder->endTag(); |
|
| 452 | + } |
|
| 453 | + |
|
| 454 | + self::$encoder->startTag(SYNC_GAL_EMAILADDRESS); |
|
| 455 | + self::$encoder->content((isset($u[SYNC_GAL_EMAILADDRESS])) ? $u[SYNC_GAL_EMAILADDRESS] : ""); |
|
| 456 | + self::$encoder->endTag(); |
|
| 457 | + |
|
| 458 | + if (isset($u[SYNC_GAL_PICTURE])) { |
|
| 459 | + self::$encoder->startTag(SYNC_GAL_PICTURE); |
|
| 460 | + self::$encoder->startTag(SYNC_GAL_STATUS); |
|
| 461 | + self::$encoder->content(SYNC_SEARCHSTATUS_PICTURE_SUCCESS); // FIXME: status code |
|
| 462 | + self::$encoder->endTag(); // SYNC_SEARCH_STATUS |
|
| 463 | + |
|
| 464 | + self::$encoder->startTag(SYNC_GAL_DATA); |
|
| 465 | + self::$encoder->contentStream($u[SYNC_GAL_PICTURE], false, true); |
|
| 466 | + self::$encoder->endTag(); // SYNC_GAL_DATA |
|
| 467 | + self::$encoder->endTag(); // SYNC_GAL_PICTURE |
|
| 468 | + } |
|
| 469 | + |
|
| 470 | + self::$encoder->endTag(); // result |
|
| 471 | + self::$encoder->endTag(); // properties |
|
| 472 | + } |
|
| 473 | + } |
|
| 474 | + } |
|
| 475 | + elseif ($searchname == ISearchProvider::SEARCH_MAILBOX) { |
|
| 476 | + foreach ($rows as $u) { |
|
| 477 | + // TODO: unclear if any clients *require* the folder id where the message is located (it's not available anymore) |
|
| 478 | + // $folderid = self::$deviceManager->GetFolderIdForBackendId($u['folderid']); |
|
| 479 | + |
|
| 480 | + self::$encoder->startTag(SYNC_SEARCH_RESULT); |
|
| 481 | + self::$encoder->startTag(SYNC_FOLDERTYPE); |
|
| 482 | + self::$encoder->content($u['class']); |
|
| 483 | + self::$encoder->endTag(); |
|
| 484 | + self::$encoder->startTag(SYNC_SEARCH_LONGID); |
|
| 485 | + self::$encoder->content($u['longid']); |
|
| 486 | + self::$encoder->endTag(); |
|
| 487 | + // self::$encoder->startTag(SYNC_FOLDERID); |
|
| 488 | + // self::$encoder->content($folderid); |
|
| 489 | + // self::$encoder->endTag(); |
|
| 490 | + |
|
| 491 | + self::$encoder->startTag(SYNC_SEARCH_PROPERTIES); |
|
| 492 | + $message = self::$backend->Fetch(false, $u['longid'], $cpo); |
|
| 493 | + $message->Encode(self::$encoder); |
|
| 494 | + |
|
| 495 | + self::$encoder->endTag(); // result |
|
| 496 | + self::$encoder->endTag(); // properties |
|
| 497 | + } |
|
| 498 | + } |
|
| 499 | + // it seems that android 4 requires range and searchtotal |
|
| 500 | + // or it won't display the search results |
|
| 501 | + if (isset($searchrange)) { |
|
| 502 | + self::$encoder->startTag(SYNC_SEARCH_RANGE); |
|
| 503 | + self::$encoder->content($searchrange); |
|
| 504 | + self::$encoder->endTag(); |
|
| 505 | + } |
|
| 506 | + if (isset($searchtotal) && $searchtotal > 0) { |
|
| 507 | + self::$encoder->startTag(SYNC_SEARCH_TOTAL); |
|
| 508 | + self::$encoder->content($searchtotal); |
|
| 509 | + self::$encoder->endTag(); |
|
| 510 | + } |
|
| 511 | + |
|
| 512 | + self::$encoder->endTag(); // store |
|
| 513 | + self::$encoder->endTag(); // response |
|
| 514 | + } |
|
| 515 | + self::$encoder->endTag(); // search |
|
| 516 | + |
|
| 517 | + return true; |
|
| 518 | + } |
|
| 519 | 519 | } |
@@ -145,8 +145,7 @@ discard block |
||
| 145 | 145 | if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_AND |
| 146 | 146 | return false; |
| 147 | 147 | } |
| 148 | - } |
|
| 149 | - elseif (self::$decoder->getElementStartTag(SYNC_SEARCH_EQUALTO)) { |
|
| 148 | + } elseif (self::$decoder->getElementStartTag(SYNC_SEARCH_EQUALTO)) { |
|
| 150 | 149 | // linkid can be an empty tag as well as have value |
| 151 | 150 | if (self::$decoder->getElementStartTag(SYNC_DOCUMENTLIBRARY_LINKID)) { |
| 152 | 151 | if (($linkId = self::$decoder->getElementContent()) !== false) { |
@@ -346,18 +345,15 @@ discard block |
||
| 346 | 345 | if ($searchname == ISearchProvider::SEARCH_GAL) { |
| 347 | 346 | // get search results from the searchprovider |
| 348 | 347 | $rows = $searchprovider->GetGALSearchResults($searchquery, $searchrange, $searchpicture); |
| 349 | - } |
|
| 350 | - elseif ($searchname == ISearchProvider::SEARCH_MAILBOX) { |
|
| 348 | + } elseif ($searchname == ISearchProvider::SEARCH_MAILBOX) { |
|
| 351 | 349 | $backendFolderId = self::$deviceManager->GetBackendIdForFolderId($cpo->GetSearchFolderid()); |
| 352 | 350 | $cpo->SetSearchFolderid($backendFolderId); |
| 353 | 351 | $rows = $searchprovider->GetMailboxSearchResults($cpo); |
| 354 | 352 | } |
| 355 | - } |
|
| 356 | - catch (StatusException $stex) { |
|
| 353 | + } catch (StatusException $stex) { |
|
| 357 | 354 | $storestatus = $stex->getCode(); |
| 358 | 355 | } |
| 359 | - } |
|
| 360 | - else { |
|
| 356 | + } else { |
|
| 361 | 357 | $rows = ['searchtotal' => 0]; |
| 362 | 358 | $status = SYNC_SEARCHSTATUS_SERVERERROR; |
| 363 | 359 | SLog::Write(LOGLEVEL_WARN, sprintf("Searchtype '%s' is not supported.", $searchname)); |
@@ -471,8 +467,7 @@ discard block |
||
| 471 | 467 | self::$encoder->endTag(); // properties |
| 472 | 468 | } |
| 473 | 469 | } |
| 474 | - } |
|
| 475 | - elseif ($searchname == ISearchProvider::SEARCH_MAILBOX) { |
|
| 470 | + } elseif ($searchname == ISearchProvider::SEARCH_MAILBOX) { |
|
| 476 | 471 | foreach ($rows as $u) { |
| 477 | 472 | // TODO: unclear if any clients *require* the folder id where the message is located (it's not available anymore) |
| 478 | 473 | // $folderid = self::$deviceManager->GetFolderIdForBackendId($u['folderid']); |
@@ -11,138 +11,138 @@ |
||
| 11 | 11 | */ |
| 12 | 12 | |
| 13 | 13 | abstract class RequestProcessor { |
| 14 | - protected static $backend; |
|
| 15 | - protected static $deviceManager; |
|
| 16 | - protected static $topCollector; |
|
| 17 | - protected static $decoder; |
|
| 18 | - protected static $encoder; |
|
| 19 | - protected static $userIsAuthenticated; |
|
| 20 | - protected static $specialHeaders; |
|
| 21 | - protected static $waitTime = 0; |
|
| 22 | - |
|
| 23 | - /** |
|
| 24 | - * Authenticates the remote user |
|
| 25 | - * The sent HTTP authentication information is used to on Backend->Logon(). |
|
| 26 | - * As second step the GET-User verified by Backend->Setup() for permission check |
|
| 27 | - * Request::GetGETUser() is usually the same as the Request::GetAuthUser(). |
|
| 28 | - * If the GETUser is different from the AuthUser, the AuthUser MUST HAVE admin |
|
| 29 | - * permissions on GETUsers data store. Only then the Setup() will be successful. |
|
| 30 | - * This allows the user 'john' to do operations as user 'joe' if he has sufficient privileges. |
|
| 31 | - * |
|
| 32 | - * @throws AuthenticationRequiredException |
|
| 33 | - * |
|
| 34 | - * @return |
|
| 35 | - */ |
|
| 36 | - public static function Authenticate() { |
|
| 37 | - self::$userIsAuthenticated = false; |
|
| 38 | - |
|
| 39 | - // when a certificate is sent, allow authentication only as the certificate owner |
|
| 40 | - if (defined("CERTIFICATE_OWNER_PARAMETER") && isset($_SERVER[CERTIFICATE_OWNER_PARAMETER]) && strtolower($_SERVER[CERTIFICATE_OWNER_PARAMETER]) != strtolower(Request::GetAuthUser())) { |
|
| 41 | - throw new AuthenticationRequiredException(sprintf("Access denied. Access is allowed only for the certificate owner '%s'", $_SERVER[CERTIFICATE_OWNER_PARAMETER])); |
|
| 42 | - } |
|
| 43 | - |
|
| 44 | - if (Request::GetImpersonatedUser() && strcasecmp(Request::GetAuthUser(), Request::GetImpersonatedUser()) !== 0) { |
|
| 45 | - SLog::Write(LOGLEVEL_DEBUG, sprintf("RequestProcessor->Authenticate(): Impersonation active - authenticating: '%s' - impersonating '%s'", Request::GetAuthUser(), Request::GetImpersonatedUser())); |
|
| 46 | - } |
|
| 47 | - |
|
| 48 | - $backend = GSync::GetBackend(); |
|
| 49 | - if ($backend->Logon(Request::GetAuthUser(), Request::GetAuthDomain(), Request::GetAuthPassword()) == false) { |
|
| 50 | - throw new AuthenticationRequiredException("Access denied. Username or password incorrect"); |
|
| 51 | - } |
|
| 52 | - |
|
| 53 | - // mark this request as "authenticated" |
|
| 54 | - self::$userIsAuthenticated = true; |
|
| 55 | - } |
|
| 56 | - |
|
| 57 | - /** |
|
| 58 | - * Indicates if the user was "authenticated". |
|
| 59 | - * |
|
| 60 | - * @return bool |
|
| 61 | - */ |
|
| 62 | - public static function isUserAuthenticated() { |
|
| 63 | - if (!isset(self::$userIsAuthenticated)) { |
|
| 64 | - return false; |
|
| 65 | - } |
|
| 66 | - |
|
| 67 | - return self::$userIsAuthenticated; |
|
| 68 | - } |
|
| 69 | - |
|
| 70 | - /** |
|
| 71 | - * Initialize the RequestProcessor. |
|
| 72 | - * |
|
| 73 | - * @return |
|
| 74 | - */ |
|
| 75 | - public static function Initialize() { |
|
| 76 | - self::$backend = GSync::GetBackend(); |
|
| 77 | - self::$deviceManager = GSync::GetDeviceManager(false); |
|
| 78 | - self::$topCollector = GSync::GetTopCollector(); |
|
| 79 | - |
|
| 80 | - if (!GSync::CommandNeedsPlainInput(Request::GetCommandCode())) { |
|
| 81 | - self::$decoder = new WBXMLDecoder(Request::GetInputStream()); |
|
| 82 | - } |
|
| 83 | - |
|
| 84 | - self::$encoder = new WBXMLEncoder(Request::GetOutputStream(), Request::GetGETAcceptMultipart()); |
|
| 85 | - self::$waitTime = 0; |
|
| 86 | - } |
|
| 87 | - |
|
| 88 | - /** |
|
| 89 | - * Loads the command handler and processes a command sent from the mobile. |
|
| 90 | - * |
|
| 91 | - * @return bool |
|
| 92 | - */ |
|
| 93 | - public static function HandleRequest() { |
|
| 94 | - $handler = GSync::GetRequestHandlerForCommand(Request::GetCommandCode()); |
|
| 95 | - |
|
| 96 | - // if there is an error decoding wbxml, consume remaining data and include it in the WBXMLException |
|
| 97 | - try { |
|
| 98 | - if (!$handler->Handle(Request::GetCommandCode())) { |
|
| 99 | - throw new WBXMLException(sprintf("Unknown error in %s->Handle()", get_class($handler))); |
|
| 100 | - } |
|
| 101 | - } |
|
| 102 | - catch (Exception $ex) { |
|
| 103 | - // Log 10 KB of the WBXML data |
|
| 104 | - SLog::Write(LOGLEVEL_FATAL, "WBXML 10K debug data: " . Request::GetInputAsBase64(10240), false); |
|
| 105 | - |
|
| 106 | - throw $ex; |
|
| 107 | - } |
|
| 108 | - |
|
| 109 | - // also log WBXML in happy case |
|
| 110 | - if (SLog::IsWbxmlDebugEnabled()) { |
|
| 111 | - // Log 4 KB in the happy case |
|
| 112 | - SLog::Write(LOGLEVEL_WBXML, "WBXML-IN : " . Request::GetInputAsBase64(4096), false); |
|
| 113 | - } |
|
| 114 | - |
|
| 115 | - return true; |
|
| 116 | - } |
|
| 117 | - |
|
| 118 | - /** |
|
| 119 | - * Returns any additional headers which should be sent to the mobile. |
|
| 120 | - * |
|
| 121 | - * @return array |
|
| 122 | - */ |
|
| 123 | - public static function GetSpecialHeaders() { |
|
| 124 | - if (!isset(self::$specialHeaders) || !is_array(self::$specialHeaders)) { |
|
| 125 | - return []; |
|
| 126 | - } |
|
| 127 | - |
|
| 128 | - return self::$specialHeaders; |
|
| 129 | - } |
|
| 130 | - |
|
| 131 | - /** |
|
| 132 | - * Returns the amount of seconds RequestProcessor waited e.g. during Ping. |
|
| 133 | - * |
|
| 134 | - * @return int |
|
| 135 | - */ |
|
| 136 | - public static function GetWaitTime() { |
|
| 137 | - return self::$waitTime; |
|
| 138 | - } |
|
| 139 | - |
|
| 140 | - /** |
|
| 141 | - * Handles a command. |
|
| 142 | - * |
|
| 143 | - * @param int $commandCode |
|
| 144 | - * |
|
| 145 | - * @return bool |
|
| 146 | - */ |
|
| 147 | - abstract public function Handle($commandCode); |
|
| 14 | + protected static $backend; |
|
| 15 | + protected static $deviceManager; |
|
| 16 | + protected static $topCollector; |
|
| 17 | + protected static $decoder; |
|
| 18 | + protected static $encoder; |
|
| 19 | + protected static $userIsAuthenticated; |
|
| 20 | + protected static $specialHeaders; |
|
| 21 | + protected static $waitTime = 0; |
|
| 22 | + |
|
| 23 | + /** |
|
| 24 | + * Authenticates the remote user |
|
| 25 | + * The sent HTTP authentication information is used to on Backend->Logon(). |
|
| 26 | + * As second step the GET-User verified by Backend->Setup() for permission check |
|
| 27 | + * Request::GetGETUser() is usually the same as the Request::GetAuthUser(). |
|
| 28 | + * If the GETUser is different from the AuthUser, the AuthUser MUST HAVE admin |
|
| 29 | + * permissions on GETUsers data store. Only then the Setup() will be successful. |
|
| 30 | + * This allows the user 'john' to do operations as user 'joe' if he has sufficient privileges. |
|
| 31 | + * |
|
| 32 | + * @throws AuthenticationRequiredException |
|
| 33 | + * |
|
| 34 | + * @return |
|
| 35 | + */ |
|
| 36 | + public static function Authenticate() { |
|
| 37 | + self::$userIsAuthenticated = false; |
|
| 38 | + |
|
| 39 | + // when a certificate is sent, allow authentication only as the certificate owner |
|
| 40 | + if (defined("CERTIFICATE_OWNER_PARAMETER") && isset($_SERVER[CERTIFICATE_OWNER_PARAMETER]) && strtolower($_SERVER[CERTIFICATE_OWNER_PARAMETER]) != strtolower(Request::GetAuthUser())) { |
|
| 41 | + throw new AuthenticationRequiredException(sprintf("Access denied. Access is allowed only for the certificate owner '%s'", $_SERVER[CERTIFICATE_OWNER_PARAMETER])); |
|
| 42 | + } |
|
| 43 | + |
|
| 44 | + if (Request::GetImpersonatedUser() && strcasecmp(Request::GetAuthUser(), Request::GetImpersonatedUser()) !== 0) { |
|
| 45 | + SLog::Write(LOGLEVEL_DEBUG, sprintf("RequestProcessor->Authenticate(): Impersonation active - authenticating: '%s' - impersonating '%s'", Request::GetAuthUser(), Request::GetImpersonatedUser())); |
|
| 46 | + } |
|
| 47 | + |
|
| 48 | + $backend = GSync::GetBackend(); |
|
| 49 | + if ($backend->Logon(Request::GetAuthUser(), Request::GetAuthDomain(), Request::GetAuthPassword()) == false) { |
|
| 50 | + throw new AuthenticationRequiredException("Access denied. Username or password incorrect"); |
|
| 51 | + } |
|
| 52 | + |
|
| 53 | + // mark this request as "authenticated" |
|
| 54 | + self::$userIsAuthenticated = true; |
|
| 55 | + } |
|
| 56 | + |
|
| 57 | + /** |
|
| 58 | + * Indicates if the user was "authenticated". |
|
| 59 | + * |
|
| 60 | + * @return bool |
|
| 61 | + */ |
|
| 62 | + public static function isUserAuthenticated() { |
|
| 63 | + if (!isset(self::$userIsAuthenticated)) { |
|
| 64 | + return false; |
|
| 65 | + } |
|
| 66 | + |
|
| 67 | + return self::$userIsAuthenticated; |
|
| 68 | + } |
|
| 69 | + |
|
| 70 | + /** |
|
| 71 | + * Initialize the RequestProcessor. |
|
| 72 | + * |
|
| 73 | + * @return |
|
| 74 | + */ |
|
| 75 | + public static function Initialize() { |
|
| 76 | + self::$backend = GSync::GetBackend(); |
|
| 77 | + self::$deviceManager = GSync::GetDeviceManager(false); |
|
| 78 | + self::$topCollector = GSync::GetTopCollector(); |
|
| 79 | + |
|
| 80 | + if (!GSync::CommandNeedsPlainInput(Request::GetCommandCode())) { |
|
| 81 | + self::$decoder = new WBXMLDecoder(Request::GetInputStream()); |
|
| 82 | + } |
|
| 83 | + |
|
| 84 | + self::$encoder = new WBXMLEncoder(Request::GetOutputStream(), Request::GetGETAcceptMultipart()); |
|
| 85 | + self::$waitTime = 0; |
|
| 86 | + } |
|
| 87 | + |
|
| 88 | + /** |
|
| 89 | + * Loads the command handler and processes a command sent from the mobile. |
|
| 90 | + * |
|
| 91 | + * @return bool |
|
| 92 | + */ |
|
| 93 | + public static function HandleRequest() { |
|
| 94 | + $handler = GSync::GetRequestHandlerForCommand(Request::GetCommandCode()); |
|
| 95 | + |
|
| 96 | + // if there is an error decoding wbxml, consume remaining data and include it in the WBXMLException |
|
| 97 | + try { |
|
| 98 | + if (!$handler->Handle(Request::GetCommandCode())) { |
|
| 99 | + throw new WBXMLException(sprintf("Unknown error in %s->Handle()", get_class($handler))); |
|
| 100 | + } |
|
| 101 | + } |
|
| 102 | + catch (Exception $ex) { |
|
| 103 | + // Log 10 KB of the WBXML data |
|
| 104 | + SLog::Write(LOGLEVEL_FATAL, "WBXML 10K debug data: " . Request::GetInputAsBase64(10240), false); |
|
| 105 | + |
|
| 106 | + throw $ex; |
|
| 107 | + } |
|
| 108 | + |
|
| 109 | + // also log WBXML in happy case |
|
| 110 | + if (SLog::IsWbxmlDebugEnabled()) { |
|
| 111 | + // Log 4 KB in the happy case |
|
| 112 | + SLog::Write(LOGLEVEL_WBXML, "WBXML-IN : " . Request::GetInputAsBase64(4096), false); |
|
| 113 | + } |
|
| 114 | + |
|
| 115 | + return true; |
|
| 116 | + } |
|
| 117 | + |
|
| 118 | + /** |
|
| 119 | + * Returns any additional headers which should be sent to the mobile. |
|
| 120 | + * |
|
| 121 | + * @return array |
|
| 122 | + */ |
|
| 123 | + public static function GetSpecialHeaders() { |
|
| 124 | + if (!isset(self::$specialHeaders) || !is_array(self::$specialHeaders)) { |
|
| 125 | + return []; |
|
| 126 | + } |
|
| 127 | + |
|
| 128 | + return self::$specialHeaders; |
|
| 129 | + } |
|
| 130 | + |
|
| 131 | + /** |
|
| 132 | + * Returns the amount of seconds RequestProcessor waited e.g. during Ping. |
|
| 133 | + * |
|
| 134 | + * @return int |
|
| 135 | + */ |
|
| 136 | + public static function GetWaitTime() { |
|
| 137 | + return self::$waitTime; |
|
| 138 | + } |
|
| 139 | + |
|
| 140 | + /** |
|
| 141 | + * Handles a command. |
|
| 142 | + * |
|
| 143 | + * @param int $commandCode |
|
| 144 | + * |
|
| 145 | + * @return bool |
|
| 146 | + */ |
|
| 147 | + abstract public function Handle($commandCode); |
|
| 148 | 148 | } |
@@ -101,7 +101,7 @@ discard block |
||
| 101 | 101 | } |
| 102 | 102 | catch (Exception $ex) { |
| 103 | 103 | // Log 10 KB of the WBXML data |
| 104 | - SLog::Write(LOGLEVEL_FATAL, "WBXML 10K debug data: " . Request::GetInputAsBase64(10240), false); |
|
| 104 | + SLog::Write(LOGLEVEL_FATAL, "WBXML 10K debug data: ".Request::GetInputAsBase64(10240), false); |
|
| 105 | 105 | |
| 106 | 106 | throw $ex; |
| 107 | 107 | } |
@@ -109,7 +109,7 @@ discard block |
||
| 109 | 109 | // also log WBXML in happy case |
| 110 | 110 | if (SLog::IsWbxmlDebugEnabled()) { |
| 111 | 111 | // Log 4 KB in the happy case |
| 112 | - SLog::Write(LOGLEVEL_WBXML, "WBXML-IN : " . Request::GetInputAsBase64(4096), false); |
|
| 112 | + SLog::Write(LOGLEVEL_WBXML, "WBXML-IN : ".Request::GetInputAsBase64(4096), false); |
|
| 113 | 113 | } |
| 114 | 114 | |
| 115 | 115 | return true; |
@@ -98,8 +98,7 @@ |
||
| 98 | 98 | if (!$handler->Handle(Request::GetCommandCode())) { |
| 99 | 99 | throw new WBXMLException(sprintf("Unknown error in %s->Handle()", get_class($handler))); |
| 100 | 100 | } |
| 101 | - } |
|
| 102 | - catch (Exception $ex) { |
|
| 101 | + } catch (Exception $ex) { |
|
| 103 | 102 | // Log 10 KB of the WBXML data |
| 104 | 103 | SLog::Write(LOGLEVEL_FATAL, "WBXML 10K debug data: " . Request::GetInputAsBase64(10240), false); |
| 105 | 104 | |