source: trunk/zpush/index.php @ 7589

Revision 7589, 13.0 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      :   index.php
4* Project   :   Z-Push
5* Descr     :   This is the entry point
6*               through which all requests
7*               are processed.
8*
9* Created   :   01.10.2007
10*
11* Copyright 2007 - 2012 Zarafa Deutschland GmbH
12*
13* This program is free software: you can redistribute it and/or modify
14* it under the terms of the GNU Affero General Public License, version 3,
15* as published by the Free Software Foundation with the following additional
16* term according to sec. 7:
17*
18* According to sec. 7 of the GNU Affero General Public License, version 3,
19* the terms of the AGPL are supplemented with the following terms:
20*
21* "Zarafa" is a registered trademark of Zarafa B.V.
22* "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
23* The licensing of the Program under the AGPL does not imply a trademark license.
24* Therefore any rights, title and interest in our trademarks remain entirely with us.
25*
26* However, if you propagate an unmodified version of the Program you are
27* allowed to use the term "Z-Push" to indicate that you distribute the Program.
28* Furthermore you may use our trademarks where it is necessary to indicate
29* the intended purpose of a product or service provided you use it in accordance
30* with honest practices in industrial or commercial matters.
31* If you want to propagate modified versions of the Program under the name "Z-Push",
32* you may only do so if you have a written permission by Zarafa Deutschland GmbH
33* (to acquire a permission please contact Zarafa at trademark@zarafa.com).
34*
35* This program is distributed in the hope that it will be useful,
36* but WITHOUT ANY WARRANTY; without even the implied warranty of
37* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38* GNU Affero General Public License for more details.
39*
40* You should have received a copy of the GNU Affero General Public License
41* along with this program.  If not, see <http://www.gnu.org/licenses/>.
42*
43* Consult LICENSE file for details
44************************************************/
45
46ob_start(null, 1048576);
47
48// ignore user abortions because this can lead to weird errors - see ZP-239
49ignore_user_abort(true);
50
51include_once('lib/exceptions/exceptions.php');
52include_once('lib/utils/utils.php');
53include_once('lib/utils/compat.php');
54include_once('lib/utils/timezoneutil.php');
55include_once('lib/core/zpushdefs.php');
56include_once('lib/core/stateobject.php');
57include_once('lib/core/interprocessdata.php');
58include_once('lib/core/pingtracking.php');
59include_once('lib/core/topcollector.php');
60include_once('lib/core/loopdetection.php');
61include_once('lib/core/asdevice.php');
62include_once('lib/core/statemanager.php');
63include_once('lib/core/devicemanager.php');
64include_once('lib/core/zpush.php');
65include_once('lib/core/zlog.php');
66include_once('lib/core/paddingfilter.php');
67include_once('lib/interface/ibackend.php');
68include_once('lib/interface/ichanges.php');
69include_once('lib/interface/iexportchanges.php');
70include_once('lib/interface/iimportchanges.php');
71include_once('lib/interface/isearchprovider.php');
72include_once('lib/interface/istatemachine.php');
73include_once('lib/core/streamer.php');
74include_once('lib/core/streamimporter.php');
75include_once('lib/core/synccollections.php');
76include_once('lib/core/hierarchycache.php');
77include_once('lib/core/changesmemorywrapper.php');
78include_once('lib/core/syncparameters.php');
79include_once('lib/core/bodypreference.php');
80include_once('lib/core/contentparameters.php');
81include_once('lib/wbxml/wbxmldefs.php');
82include_once('lib/wbxml/wbxmldecoder.php');
83include_once('lib/wbxml/wbxmlencoder.php');
84include_once('lib/syncobjects/syncobject.php');
85include_once('lib/syncobjects/syncbasebody.php');
86include_once('lib/syncobjects/syncbaseattachment.php');
87include_once('lib/syncobjects/syncmailflags.php');
88include_once('lib/syncobjects/syncrecurrence.php');
89include_once('lib/syncobjects/syncappointment.php');
90include_once('lib/syncobjects/syncappointmentexception.php');
91include_once('lib/syncobjects/syncattachment.php');
92include_once('lib/syncobjects/syncattendee.php');
93include_once('lib/syncobjects/syncmeetingrequestrecurrence.php');
94include_once('lib/syncobjects/syncmeetingrequest.php');
95include_once('lib/syncobjects/syncmail.php');
96include_once('lib/syncobjects/syncnote.php');
97include_once('lib/syncobjects/synccontact.php');
98include_once('lib/syncobjects/syncfolder.php');
99include_once('lib/syncobjects/syncprovisioning.php');
100include_once('lib/syncobjects/synctaskrecurrence.php');
101include_once('lib/syncobjects/synctask.php');
102include_once('lib/syncobjects/syncoofmessage.php');
103include_once('lib/syncobjects/syncoof.php');
104include_once('lib/syncobjects/syncuserinformation.php');
105include_once('lib/syncobjects/syncdeviceinformation.php');
106include_once('lib/syncobjects/syncdevicepassword.php');
107include_once('lib/syncobjects/syncitemoperationsattachment.php');
108include_once('lib/syncobjects/syncsendmail.php');
109include_once('lib/syncobjects/syncsendmailsource.php');
110include_once('lib/default/backend.php');
111include_once('lib/default/searchprovider.php');
112include_once('lib/request/request.php');
113include_once('lib/request/requestprocessor.php');
114
115include_once('config.php');
116include_once('version.php');
117
118
119    // Attempt to set maximum execution time
120    ini_set('max_execution_time', SCRIPT_TIMEOUT);
121    set_time_limit(SCRIPT_TIMEOUT);
122
123    try {
124        // check config & initialize the basics
125        ZPush::CheckConfig();
126        Request::Initialize();
127        ZLog::Initialize();
128
129        ZLog::Write(LOGLEVEL_DEBUG,"-------- Start");
130        ZLog::Write(LOGLEVEL_INFO,
131                    sprintf("Version='%s' method='%s' from='%s' cmd='%s' getUser='%s' devId='%s' devType='%s'",
132                                    @constant('ZPUSH_VERSION'), Request::GetMethod(), Request::GetRemoteAddr(),
133                                    Request::GetCommand(), Request::GetGETUser(), Request::GetDeviceID(), Request::GetDeviceType()));
134
135        // Stop here if this is an OPTIONS request
136        if (Request::IsMethodOPTIONS())
137            throw new NoPostRequestException("Options request", NoPostRequestException::OPTIONS_REQUEST);
138
139        ZPush::CheckAdvancedConfig();
140
141        // Process request headers and look for AS headers
142        Request::ProcessHeaders();
143
144        // Check required GET parameters
145        if(Request::IsMethodPOST() && (Request::GetCommandCode() === false || !Request::GetGETUser() || !Request::GetDeviceID() || !Request::GetDeviceType()))
146            throw new FatalException("Requested the Z-Push URL without the required GET parameters");
147
148        // Load the backend
149        $backend = ZPush::GetBackend();
150
151        // always request the authorization header
152        if (! Request::AuthenticationInfo())
153            throw new AuthenticationRequiredException("Access denied. Please send authorisation information");
154
155        // check the provisioning information
156        if (PROVISIONING === true && Request::IsMethodPOST() && ZPush::CommandNeedsProvisioning(Request::GetCommandCode()) &&
157            ((Request::WasPolicyKeySent() && Request::GetPolicyKey() == 0) || ZPush::GetDeviceManager()->ProvisioningRequired(Request::GetPolicyKey())) &&
158            (LOOSE_PROVISIONING === false ||
159            (LOOSE_PROVISIONING === true && Request::WasPolicyKeySent())))
160            //TODO for AS 14 send a wbxml response
161            throw new ProvisioningRequiredException();
162
163        // most commands require an authenticated user
164        if (ZPush::CommandNeedsAuthentication(Request::GetCommandCode()))
165            RequestProcessor::Authenticate();
166
167        // Do the actual processing of the request
168        if (Request::IsMethodGET())
169            throw new NoPostRequestException("This is the Z-Push location and can only be accessed by Microsoft ActiveSync-capable devices", NoPostRequestException::GET_REQUEST);
170
171        // Do the actual request
172        header(ZPush::GetServerHeader());
173
174        // announce the supported AS versions (if not already sent to device)
175        if (ZPush::GetDeviceManager()->AnnounceASVersion()) {
176            $versions = ZPush::GetSupportedProtocolVersions(true);
177            ZLog::Write(LOGLEVEL_INFO, sprintf("Announcing latest AS version to device: %s", $versions));
178            header("X-MS-RP: ". $versions);
179        }
180
181        RequestProcessor::Initialize();
182        if(!RequestProcessor::HandleRequest())
183            throw new WBXMLException(ZLog::GetWBXMLDebugInfo());
184
185        // eventually the RequestProcessor wants to send other headers to the mobile
186        foreach (RequestProcessor::GetSpecialHeaders() as $header)
187            header($header);
188
189        // stream the data
190        $len = ob_get_length();
191        $data = ob_get_contents();
192        ob_end_clean();
193
194        // log amount of data transferred
195        // TODO check $len when streaming more data (e.g. Attachments), as the data will be send chunked
196        ZPush::GetDeviceManager()->SentData($len);
197
198        // Unfortunately, even though Z-Push can stream the data to the client
199        // with a chunked encoding, using chunked encoding breaks the progress bar
200        // on the PDA. So the data is de-chunk here, written a content-length header and
201        // data send as a 'normal' packet. If the output packet exceeds 1MB (see ob_start)
202        // then it will be sent as a chunked packet anyway because PHP will have to flush
203        // the buffer.
204        if(!headers_sent())
205            header("Content-Length: $len");
206
207        // send vnd.ms-sync.wbxml content type header if there is no content
208        // otherwise text/html content type is added which might break some devices
209        if ($len == 0)
210            header("Content-Type: application/vnd.ms-sync.wbxml");
211
212        print $data;
213
214        // destruct backend after all data is on the stream
215        $backend->Logoff();
216    }
217
218    catch (NoPostRequestException $nopostex) {
219        if ($nopostex->getCode() == NoPostRequestException::OPTIONS_REQUEST) {
220            header(ZPush::GetServerHeader());
221            header(ZPush::GetSupportedProtocolVersions());
222            header(ZPush::GetSupportedCommands());
223            ZLog::Write(LOGLEVEL_INFO, $nopostex->getMessage());
224        }
225        else if ($nopostex->getCode() == NoPostRequestException::GET_REQUEST) {
226            if (Request::GetUserAgent())
227                ZLog::Write(LOGLEVEL_INFO, sprintf("User-agent: '%s'", Request::GetUserAgent()));
228            if (!headers_sent() && $nopostex->showLegalNotice())
229                ZPush::PrintZPushLegal('GET not supported', $nopostex->getMessage());
230        }
231    }
232
233    catch (Exception $ex) {
234        if (Request::GetUserAgent())
235            ZLog::Write(LOGLEVEL_INFO, sprintf("User-agent: '%s'", Request::GetUserAgent()));
236        $exclass = get_class($ex);
237
238        if(!headers_sent()) {
239            if ($ex instanceof ZPushException) {
240                header('HTTP/1.1 '. $ex->getHTTPCodeString());
241                foreach ($ex->getHTTPHeaders() as $h)
242                    header($h);
243            }
244            // something really unexpected happened!
245            else
246                header('HTTP/1.1 500 Internal Server Error');
247        }
248        else
249            ZLog::Write(LOGLEVEL_FATAL, "Exception: ($exclass) - headers were already sent. Message: ". $ex->getMessage());
250
251        if ($ex instanceof AuthenticationRequiredException) {
252            ZPush::PrintZPushLegal($exclass, sprintf('<pre>%s</pre>',$ex->getMessage()));
253
254            // log the failed login attemt e.g. for fail2ban
255            if (defined('LOGAUTHFAIL') && LOGAUTHFAIL != false)
256                ZLog::Write(LOGLEVEL_WARN, sprintf("IP: %s failed to authenticate user '%s'",  Request::GetRemoteAddr(), Request::GetAuthUser()? Request::GetAuthUser(): Request::GetGETUser() ));
257        }
258
259        // This could be a WBXML problem.. try to get the complete request
260        else if ($ex instanceof WBXMLException) {
261            ZLog::Write(LOGLEVEL_FATAL, "Request could not be processed correctly due to a WBXMLException. Please report this.");
262        }
263
264        // Try to output some kind of error information. This is only possible if
265        // the output had not started yet. If it has started already, we can't show the user the error, and
266        // the device will give its own (useless) error message.
267        else if (!($ex instanceof ZPushException) || $ex->showLegalNotice()) {
268            $cmdinfo = (Request::GetCommand())? sprintf(" processing command <i>%s</i>", Request::GetCommand()): "";
269            $extrace = $ex->getTrace();
270            $trace = (!empty($extrace))? "\n\nTrace:\n". print_r($extrace,1):"";
271            ZPush::PrintZPushLegal($exclass . $cmdinfo, sprintf('<pre>%s</pre>',$ex->getMessage() . $trace));
272        }
273
274        // Announce exception to process loop detection
275        if (ZPush::GetDeviceManager(false))
276            ZPush::GetDeviceManager()->AnnounceProcessException($ex);
277
278        // Announce exception if the TopCollector if available
279        ZPush::GetTopCollector()->AnnounceInformation(get_class($ex), true);
280    }
281
282    // save device data if the DeviceManager is available
283    if (ZPush::GetDeviceManager(false))
284        ZPush::GetDeviceManager()->Save();
285
286    // end gracefully
287    ZLog::Write(LOGLEVEL_DEBUG, '-------- End');
288?>
Note: See TracBrowser for help on using the repository browser.