source: trunk/zpush/lib/request/ping.php @ 7589

Revision 7589, 8.8 KB checked in by douglas, 11 years ago (diff)

Ticket #3209 - Integrar módulo de sincronização Z-push ao Expresso

Line 
1<?php
2/***********************************************
3* File      :   ping.php
4* Project   :   Z-Push
5* Descr     :   Provides the PING command
6*
7* Created   :   16.02.2012
8*
9* Copyright 2007 - 2012 Zarafa Deutschland GmbH
10*
11* This program is free software: you can redistribute it and/or modify
12* it under the terms of the GNU Affero General Public License, version 3,
13* as published by the Free Software Foundation with the following additional
14* term according to sec. 7:
15*
16* According to sec. 7 of the GNU Affero General Public License, version 3,
17* the terms of the AGPL are supplemented with the following terms:
18*
19* "Zarafa" is a registered trademark of Zarafa B.V.
20* "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
21* The licensing of the Program under the AGPL does not imply a trademark license.
22* Therefore any rights, title and interest in our trademarks remain entirely with us.
23*
24* However, if you propagate an unmodified version of the Program you are
25* allowed to use the term "Z-Push" to indicate that you distribute the Program.
26* Furthermore you may use our trademarks where it is necessary to indicate
27* the intended purpose of a product or service provided you use it in accordance
28* with honest practices in industrial or commercial matters.
29* If you want to propagate modified versions of the Program under the name "Z-Push",
30* you may only do so if you have a written permission by Zarafa Deutschland GmbH
31* (to acquire a permission please contact Zarafa at trademark@zarafa.com).
32*
33* This program is distributed in the hope that it will be useful,
34* but WITHOUT ANY WARRANTY; without even the implied warranty of
35* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36* GNU Affero General Public License for more details.
37*
38* You should have received a copy of the GNU Affero General Public License
39* along with this program.  If not, see <http://www.gnu.org/licenses/>.
40*
41* Consult LICENSE file for details
42************************************************/
43
44class Ping extends RequestProcessor {
45
46    /**
47     * Handles the Ping command
48     *
49     * @param int       $commandCode
50     *
51     * @access public
52     * @return boolean
53     */
54    public function Handle($commandCode) {
55        $interval = (defined('PING_INTERVAL') && PING_INTERVAL > 0) ? PING_INTERVAL : 30;
56        $pingstatus = false;
57        $fakechanges = array();
58        $foundchanges = false;
59
60        // Contains all requested folders (containers)
61        $sc = new SyncCollections();
62
63        // Load all collections - do load states and check permissions
64        try {
65            $sc->LoadAllCollections(true, true, true);
66        }
67        catch (StateNotFoundException $snfex) {
68            $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED;
69            self::$topCollector->AnnounceInformation("StateNotFoundException: require HierarchySync", true);
70        }
71        catch (StateInvalidException $snfex) {
72            // we do not have a ping status for this, but SyncCollections should have generated fake changes for the folders which are broken
73            $fakechanges = $sc->GetChangedFolderIds();
74            $foundchanges = true;
75
76            self::$topCollector->AnnounceInformation("StateInvalidException: force sync", true);
77        }
78        catch (StatusException $stex) {
79            $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED;
80            self::$topCollector->AnnounceInformation("StatusException: require HierarchySync", true);
81        }
82
83        ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): reference PolicyKey for PING: %s", $sc->GetReferencePolicyKey()));
84
85        // receive PING initialization data
86        if(self::$decoder->getElementStartTag(SYNC_PING_PING)) {
87            self::$topCollector->AnnounceInformation("Processing PING data");
88            ZLog::Write(LOGLEVEL_DEBUG, "HandlePing(): initialization data received");
89
90            if(self::$decoder->getElementStartTag(SYNC_PING_LIFETIME)) {
91                $sc->SetLifetime(self::$decoder->getElementContent());
92                self::$decoder->getElementEndTag();
93            }
94
95            if(($el = self::$decoder->getElementStartTag(SYNC_PING_FOLDERS)) && $el[EN_FLAGS] & EN_FLAGS_CONTENT) {
96                // remove PingableFlag from all collections
97                foreach ($sc as $folderid => $spa)
98                    $spa->DelPingableFlag();
99
100                while(self::$decoder->getElementStartTag(SYNC_PING_FOLDER)) {
101                    while(1) {
102                        if(self::$decoder->getElementStartTag(SYNC_PING_SERVERENTRYID)) {
103                            $folderid = self::$decoder->getElementContent();
104                            self::$decoder->getElementEndTag();
105                        }
106                        if(self::$decoder->getElementStartTag(SYNC_PING_FOLDERTYPE)) {
107                            $class = self::$decoder->getElementContent();
108                            self::$decoder->getElementEndTag();
109                        }
110
111                        $e = self::$decoder->peek();
112                        if($e[EN_TYPE] == EN_TYPE_ENDTAG) {
113                            self::$decoder->getElementEndTag();
114                            break;
115                        }
116                    }
117
118                    $spa = $sc->GetCollection($folderid);
119                    if (! $spa) {
120                        // The requested collection is not synchronized.
121                        // check if the HierarchyCache is available, if not, trigger a HierarchySync
122                        try {
123                            self::$deviceManager->GetFolderClassFromCacheByID($folderid);
124                        }
125                        catch (NoHierarchyCacheAvailableException $nhca) {
126                            ZLog::Write(LOGLEVEL_INFO, sprintf("HandlePing(): unknown collection '%s', triggering HierarchySync", $folderid));
127                            $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED;
128                        }
129
130                        // Trigger a Sync request because then the device will be forced to resync this folder.
131                        $fakechanges[$folderid] = 1;
132                        $foundchanges = true;
133                    }
134                    else if ($class == $spa->GetContentClass()) {
135                        $spa->SetPingableFlag(true);
136                        ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): using saved sync state for '%s' id '%s'", $spa->GetContentClass(), $folderid));
137                    }
138
139                }
140                if(!self::$decoder->getElementEndTag())
141                    return false;
142            }
143            if(!self::$decoder->getElementEndTag())
144                return false;
145
146            // save changed data
147            foreach ($sc as $folderid => $spa)
148                $sc->SaveCollection($spa);
149        } // END SYNC_PING_PING
150
151        // Check for changes on the default LifeTime, set interval and ONLY on pingable collections
152        try {
153            if (empty($fakechanges)) {
154                $foundchanges = $sc->CheckForChanges($sc->GetLifetime(), $interval, true);
155            }
156        }
157        catch (StatusException $ste) {
158            switch($ste->getCode()) {
159                case SyncCollections::ERROR_NO_COLLECTIONS:
160                    $pingstatus = SYNC_PINGSTATUS_FAILINGPARAMS;
161                    break;
162                case SyncCollections::ERROR_WRONG_HIERARCHY:
163                    $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED;
164                    self::$deviceManager->AnnounceProcessStatus(false, $pingstatus);
165                    break;
166
167            }
168        }
169
170        self::$encoder->StartWBXML();
171        self::$encoder->startTag(SYNC_PING_PING);
172        {
173            self::$encoder->startTag(SYNC_PING_STATUS);
174            if (isset($pingstatus) && $pingstatus)
175                self::$encoder->content($pingstatus);
176            else
177                self::$encoder->content($foundchanges ? SYNC_PINGSTATUS_CHANGES : SYNC_PINGSTATUS_HBEXPIRED);
178            self::$encoder->endTag();
179
180            if (! $pingstatus) {
181                self::$encoder->startTag(SYNC_PING_FOLDERS);
182
183                if (empty($fakechanges))
184                    $changes = $sc->GetChangedFolderIds();
185                else
186                    $changes = $fakechanges;
187
188                foreach ($changes as $folderid => $changecount) {
189                    if ($changecount > 0) {
190                        self::$encoder->startTag(SYNC_PING_FOLDER);
191                        self::$encoder->content($folderid);
192                        self::$encoder->endTag();
193                        if (empty($fakechanges))
194                            self::$topCollector->AnnounceInformation(sprintf("Found change in %s", $sc->GetCollection($folderid)->GetContentClass()), true);
195                    }
196                }
197                self::$encoder->endTag();
198            }
199        }
200        self::$encoder->endTag();
201
202        return true;
203    }
204}
205?>
Note: See TracBrowser for help on using the repository browser.