Back to index

d-push  2.0
ping.php
Go to the documentation of this file.
00001 <?php
00002 /***********************************************
00003 * File      :   ping.php
00004 * Project   :   Z-Push
00005 * Descr     :   Provides the PING command
00006 *
00007 * Created   :   16.02.2012
00008 *
00009 * Copyright 2007 - 2012 Zarafa Deutschland GmbH
00010 *
00011 * This program is free software: you can redistribute it and/or modify
00012 * it under the terms of the GNU Affero General Public License, version 3,
00013 * as published by the Free Software Foundation with the following additional
00014 * term according to sec. 7:
00015 *
00016 * According to sec. 7 of the GNU Affero General Public License, version 3,
00017 * the terms of the AGPL are supplemented with the following terms:
00018 *
00019 * "Zarafa" is a registered trademark of Zarafa B.V.
00020 * "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
00021 * The licensing of the Program under the AGPL does not imply a trademark license.
00022 * Therefore any rights, title and interest in our trademarks remain entirely with us.
00023 *
00024 * However, if you propagate an unmodified version of the Program you are
00025 * allowed to use the term "Z-Push" to indicate that you distribute the Program.
00026 * Furthermore you may use our trademarks where it is necessary to indicate
00027 * the intended purpose of a product or service provided you use it in accordance
00028 * with honest practices in industrial or commercial matters.
00029 * If you want to propagate modified versions of the Program under the name "Z-Push",
00030 * you may only do so if you have a written permission by Zarafa Deutschland GmbH
00031 * (to acquire a permission please contact Zarafa at trademark@zarafa.com).
00032 *
00033 * This program is distributed in the hope that it will be useful,
00034 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00035 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00036 * GNU Affero General Public License for more details.
00037 *
00038 * You should have received a copy of the GNU Affero General Public License
00039 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00040 *
00041 * Consult LICENSE file for details
00042 ************************************************/
00043 
00044 class Ping extends RequestProcessor {
00045 
00054     public function Handle($commandCode) {
00055         $interval = (defined('PING_INTERVAL') && PING_INTERVAL > 0) ? PING_INTERVAL : 30;
00056         $pingstatus = false;
00057         $fakechanges = array();
00058         $foundchanges = false;
00059 
00060         // Contains all requested folders (containers)
00061         $sc = new SyncCollections();
00062 
00063         // Load all collections - do load states and check permissions
00064         try {
00065             $sc->LoadAllCollections(true, true, true);
00066         }
00067         catch (StateNotFoundException $snfex) {
00068             $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED;
00069             self::$topCollector->AnnounceInformation("StateNotFoundException: require HierarchySync", true);
00070         }
00071         catch (StateInvalidException $snfex) {
00072             // we do not have a ping status for this, but SyncCollections should have generated fake changes for the folders which are broken
00073             $fakechanges = $sc->GetChangedFolderIds();
00074             $foundchanges = true;
00075 
00076             self::$topCollector->AnnounceInformation("StateInvalidException: force sync", true);
00077         }
00078         catch (StatusException $stex) {
00079             $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED;
00080             self::$topCollector->AnnounceInformation("StatusException: require HierarchySync", true);
00081         }
00082 
00083         ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): reference PolicyKey for PING: %s", $sc->GetReferencePolicyKey()));
00084 
00085         // receive PING initialization data
00086         if(self::$decoder->getElementStartTag(SYNC_PING_PING)) {
00087             self::$topCollector->AnnounceInformation("Processing PING data");
00088             ZLog::Write(LOGLEVEL_DEBUG, "HandlePing(): initialization data received");
00089 
00090             if(self::$decoder->getElementStartTag(SYNC_PING_LIFETIME)) {
00091                 $sc->SetLifetime(self::$decoder->getElementContent());
00092                 self::$decoder->getElementEndTag();
00093             }
00094 
00095             if(($el = self::$decoder->getElementStartTag(SYNC_PING_FOLDERS)) && $el[EN_FLAGS] & EN_FLAGS_CONTENT) {
00096                 // remove PingableFlag from all collections
00097                 foreach ($sc as $folderid => $spa)
00098                     $spa->DelPingableFlag();
00099 
00100                 while(self::$decoder->getElementStartTag(SYNC_PING_FOLDER)) {
00101                     while(1) {
00102                         if(self::$decoder->getElementStartTag(SYNC_PING_SERVERENTRYID)) {
00103                             $folderid = self::$decoder->getElementContent();
00104                             self::$decoder->getElementEndTag();
00105                         }
00106                         if(self::$decoder->getElementStartTag(SYNC_PING_FOLDERTYPE)) {
00107                             $class = self::$decoder->getElementContent();
00108                             self::$decoder->getElementEndTag();
00109                         }
00110 
00111                         $e = self::$decoder->peek();
00112                         if($e[EN_TYPE] == EN_TYPE_ENDTAG) {
00113                             self::$decoder->getElementEndTag();
00114                             break;
00115                         }
00116                     }
00117 
00118                     $spa = $sc->GetCollection($folderid);
00119                     if (! $spa) {
00120                         // The requested collection is not synchronized.
00121                         // check if the HierarchyCache is available, if not, trigger a HierarchySync
00122                         try {
00123                             self::$deviceManager->GetFolderClassFromCacheByID($folderid);
00124                         }
00125                         catch (NoHierarchyCacheAvailableException $nhca) {
00126                             ZLog::Write(LOGLEVEL_INFO, sprintf("HandlePing(): unknown collection '%s', triggering HierarchySync", $folderid));
00127                             $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED;
00128                         }
00129 
00130                         // Trigger a Sync request because then the device will be forced to resync this folder.
00131                         $fakechanges[$folderid] = 1;
00132                         $foundchanges = true;
00133                     }
00134                     else if ($class == $spa->GetContentClass()) {
00135                         $spa->SetPingableFlag(true);
00136                         ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): using saved sync state for '%s' id '%s'", $spa->GetContentClass(), $folderid));
00137                     }
00138 
00139                 }
00140                 if(!self::$decoder->getElementEndTag())
00141                     return false;
00142             }
00143             if(!self::$decoder->getElementEndTag())
00144                 return false;
00145 
00146             // save changed data
00147             foreach ($sc as $folderid => $spa)
00148                 $sc->SaveCollection($spa);
00149         } // END SYNC_PING_PING
00150 
00151         // Check for changes on the default LifeTime, set interval and ONLY on pingable collections
00152         try {
00153             if (empty($fakechanges)) {
00154                 $foundchanges = $sc->CheckForChanges($sc->GetLifetime(), $interval, true);
00155             }
00156         }
00157         catch (StatusException $ste) {
00158             switch($ste->getCode()) {
00159                 case SyncCollections::ERROR_NO_COLLECTIONS:
00160                     $pingstatus = SYNC_PINGSTATUS_FAILINGPARAMS;
00161                     break;
00162                 case SyncCollections::ERROR_WRONG_HIERARCHY:
00163                     $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED;
00164                     self::$deviceManager->AnnounceProcessStatus(false, $pingstatus);
00165                     break;
00166 
00167             }
00168         }
00169 
00170         self::$encoder->StartWBXML();
00171         self::$encoder->startTag(SYNC_PING_PING);
00172         {
00173             self::$encoder->startTag(SYNC_PING_STATUS);
00174             if (isset($pingstatus) && $pingstatus)
00175                 self::$encoder->content($pingstatus);
00176             else
00177                 self::$encoder->content($foundchanges ? SYNC_PINGSTATUS_CHANGES : SYNC_PINGSTATUS_HBEXPIRED);
00178             self::$encoder->endTag();
00179 
00180             if (! $pingstatus) {
00181                 self::$encoder->startTag(SYNC_PING_FOLDERS);
00182 
00183                 if (empty($fakechanges))
00184                     $changes = $sc->GetChangedFolderIds();
00185                 else
00186                     $changes = $fakechanges;
00187 
00188                 foreach ($changes as $folderid => $changecount) {
00189                     if ($changecount > 0) {
00190                         self::$encoder->startTag(SYNC_PING_FOLDER);
00191                         self::$encoder->content($folderid);
00192                         self::$encoder->endTag();
00193                         if (empty($fakechanges))
00194                             self::$topCollector->AnnounceInformation(sprintf("Found change in %s", $sc->GetCollection($folderid)->GetContentClass()), true);
00195                     }
00196                 }
00197                 self::$encoder->endTag();
00198             }
00199         }
00200         self::$encoder->endTag();
00201 
00202         return true;
00203     }
00204 }
00205 ?>