[4898] | 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 called. |
---|
| 8 | * |
---|
| 9 | * Created : 01.10.2007 |
---|
| 10 | * |
---|
| 11 | * Zarafa Deutschland GmbH, www.zarafaserver.de |
---|
| 12 | * This file is distributed under GPL v2. |
---|
| 13 | * Consult LICENSE file for details |
---|
| 14 | ************************************************/ |
---|
| 15 | |
---|
| 16 | ob_start(false, 1048576); |
---|
| 17 | |
---|
| 18 | include_once('zpushdefs.php'); |
---|
| 19 | include_once("config.php"); |
---|
| 20 | include_once("proto.php"); |
---|
| 21 | include_once("request.php"); |
---|
| 22 | include_once("debug.php"); |
---|
| 23 | include_once("compat.php"); |
---|
| 24 | include_once("version.php"); |
---|
| 25 | |
---|
| 26 | // Attempt to set maximum execution time |
---|
| 27 | ini_set('max_execution_time', SCRIPT_TIMEOUT); |
---|
| 28 | set_time_limit(SCRIPT_TIMEOUT); |
---|
| 29 | |
---|
| 30 | debugLog("Start"); |
---|
| 31 | debugLog("Z-Push version: $zpush_version"); |
---|
| 32 | debugLog("Client IP: ". $_SERVER['REMOTE_ADDR']); |
---|
| 33 | |
---|
| 34 | $input = fopen("php://input", "r"); |
---|
| 35 | $output = fopen("php://output", "w+"); |
---|
| 36 | |
---|
| 37 | // The script must always be called with authorisation info |
---|
| 38 | if(!isset($_SERVER['PHP_AUTH_PW'])) { |
---|
| 39 | header("WWW-Authenticate: Basic realm=\"ZPush\""); |
---|
| 40 | header("HTTP/1.1 401 Unauthorized"); |
---|
| 41 | print("Access denied. Please send authorisation information"); |
---|
| 42 | debugLog("Access denied: no password sent."); |
---|
| 43 | debugLog("end"); |
---|
| 44 | debugLog("--------"); |
---|
| 45 | return; |
---|
| 46 | } |
---|
| 47 | |
---|
| 48 | // split username & domain if received as one |
---|
| 49 | $pos = strrpos($_SERVER['PHP_AUTH_USER'], '\\'); |
---|
| 50 | if($pos === false){ |
---|
| 51 | $auth_user = $_SERVER['PHP_AUTH_USER']; |
---|
| 52 | $auth_domain = ''; |
---|
| 53 | }else{ |
---|
| 54 | $auth_domain = substr($_SERVER['PHP_AUTH_USER'],0,$pos); |
---|
| 55 | $auth_user = substr($_SERVER['PHP_AUTH_USER'],$pos+1); |
---|
| 56 | } |
---|
| 57 | $auth_pw = $_SERVER['PHP_AUTH_PW']; |
---|
| 58 | |
---|
| 59 | $cmd = $user = $devid = $devtype = ""; |
---|
| 60 | |
---|
| 61 | // Parse the standard GET parameters |
---|
| 62 | if(isset($_GET["Cmd"])) |
---|
| 63 | $cmd = $_GET["Cmd"]; |
---|
| 64 | if(isset($_GET["User"])) |
---|
| 65 | $user = $_GET["User"]; |
---|
| 66 | if(isset($_GET["DeviceId"])) |
---|
| 67 | $devid = $_GET["DeviceId"]; |
---|
| 68 | if(isset($_GET["DeviceType"])) |
---|
| 69 | $devtype = $_GET["DeviceType"]; |
---|
| 70 | |
---|
| 71 | // The GET parameters are required |
---|
| 72 | if($_SERVER["REQUEST_METHOD"] == "POST") { |
---|
| 73 | if(!isset($user) || !isset($devid) || !isset($devtype)) { |
---|
| 74 | print("Your device requested the Z-Push URL without the required GET parameters"); |
---|
| 75 | return; |
---|
| 76 | } |
---|
| 77 | } |
---|
| 78 | |
---|
| 79 | // Get the request headers so we can see the versions |
---|
| 80 | $requestheaders = apache_request_headers(); |
---|
| 81 | if (isset($requestheaders["Ms-Asprotocolversion"])) $requestheaders["MS-ASProtocolVersion"] = $requestheaders["Ms-Asprotocolversion"]; |
---|
| 82 | if(isset($requestheaders["MS-ASProtocolVersion"])) { |
---|
| 83 | global $protocolversion; |
---|
| 84 | |
---|
| 85 | $protocolversion = $requestheaders["MS-ASProtocolVersion"]; |
---|
| 86 | debugLog("Client supports version " . $protocolversion); |
---|
| 87 | } else { |
---|
| 88 | global $protocolversion; |
---|
| 89 | |
---|
| 90 | $protocolversion = "1.0"; |
---|
| 91 | } |
---|
| 92 | |
---|
| 93 | if (isset($requestheaders["X-Ms-Policykey"])) $requestheaders["X-MS-PolicyKey"] = $requestheaders["X-Ms-Policykey"]; |
---|
| 94 | if (isset($requestheaders["X-MS-PolicyKey"])) { |
---|
| 95 | global $policykey; |
---|
| 96 | $policykey = $requestheaders["X-MS-PolicyKey"]; |
---|
| 97 | |
---|
| 98 | } else { |
---|
| 99 | global $policykey; |
---|
| 100 | $policykey = 0; |
---|
| 101 | } |
---|
| 102 | |
---|
| 103 | //get user agent |
---|
| 104 | if (isset($requestheaders["User-Agent"])) { |
---|
| 105 | global $useragent; |
---|
| 106 | $useragent = $requestheaders["User-Agent"]; |
---|
| 107 | } else { |
---|
| 108 | global $useragent; |
---|
| 109 | $useragent = "unknown"; |
---|
| 110 | } |
---|
| 111 | |
---|
| 112 | // Load our backend driver |
---|
| 113 | $backend_dir = opendir(BASE_PATH . "/backend"); |
---|
| 114 | while($entry = readdir($backend_dir)) { |
---|
| 115 | if(substr($entry,0,1) == "." || substr($entry,-3) != "php") |
---|
| 116 | continue; |
---|
| 117 | |
---|
| 118 | if (!function_exists("mapi_logon") && ($entry == "ics.php")) |
---|
| 119 | continue; |
---|
| 120 | |
---|
| 121 | include_once(BASE_PATH . "/backend/" . $entry); |
---|
| 122 | } |
---|
| 123 | |
---|
| 124 | // Initialize our backend |
---|
| 125 | $backend = new $BACKEND_PROVIDER(); |
---|
| 126 | |
---|
| 127 | if($backend->Logon($auth_user, $auth_domain, $auth_pw) == false) { |
---|
| 128 | header("HTTP/1.1 401 Unauthorized"); |
---|
| 129 | header("WWW-Authenticate: Basic realm=\"ZPush\""); |
---|
| 130 | print("Access denied. Username or password incorrect."); |
---|
| 131 | debugLog("Access denied: backend logon failed."); |
---|
| 132 | debugLog("end"); |
---|
| 133 | debugLog("--------"); |
---|
| 134 | return; |
---|
| 135 | } |
---|
| 136 | |
---|
| 137 | // $user is usually the same as the PHP_AUTH_USER. This allows you to sync the 'john' account if you |
---|
| 138 | // have sufficient privileges as user 'joe'. |
---|
| 139 | if($backend->Setup($user, $devid, $protocolversion) == false) { |
---|
| 140 | header("HTTP/1.1 401 Unauthorized"); |
---|
| 141 | header("WWW-Authenticate: Basic realm=\"ZPush\""); |
---|
| 142 | print("Access denied or user '$user' unknown."); |
---|
| 143 | debugLog("Access denied: backend setup failed."); |
---|
| 144 | debugLog("end"); |
---|
| 145 | debugLog("--------"); |
---|
| 146 | return; |
---|
| 147 | } |
---|
| 148 | |
---|
| 149 | // check policy header |
---|
| 150 | if (PROVISIONING === true && $_SERVER["REQUEST_METHOD"] != 'OPTIONS' && $cmd != 'Ping' && $cmd != 'Provision' && |
---|
| 151 | $backend->CheckPolicy($policykey, $devid) != SYNC_PROVISION_STATUS_SUCCESS && |
---|
| 152 | (LOOSE_PROVISIONING === false || |
---|
| 153 | (LOOSE_PROVISIONING === true && isset($requestheaders["X-MS-PolicyKey"])))) { |
---|
| 154 | |
---|
| 155 | header("HTTP/1.1 449 Retry after sending a PROVISION command"); |
---|
| 156 | header("MS-Server-ActiveSync: 6.5.7638.1"); |
---|
| 157 | header("MS-ASProtocolVersions: 1.0,2.0,2.1,2.5"); |
---|
| 158 | header("MS-ASProtocolCommands: Sync,SendMail,SmartForward,SmartReply,GetAttachment,GetHierarchy,CreateCollection,DeleteCollection,MoveCollection,FolderSync,FolderCreate,FolderDelete,FolderUpdate,MoveItems,GetItemEstimate,MeetingResponse,Provision,ResolveRecipients,ValidateCert,Search,Ping"); |
---|
| 159 | header("Cache-Control: private"); |
---|
| 160 | debugLog("POST cmd $cmd denied: Retry after sending a PROVISION command"); |
---|
| 161 | debugLog("end"); |
---|
| 162 | debugLog("--------"); |
---|
| 163 | return; |
---|
| 164 | } |
---|
| 165 | |
---|
| 166 | // Do the actual request |
---|
| 167 | switch($_SERVER["REQUEST_METHOD"]) { |
---|
| 168 | case 'OPTIONS': |
---|
| 169 | header("MS-Server-ActiveSync: 6.5.7638.1"); |
---|
| 170 | header("MS-ASProtocolVersions: 1.0,2.0,2.1,2.5"); |
---|
| 171 | header("MS-ASProtocolCommands: Sync,SendMail,SmartForward,SmartReply,GetAttachment,GetHierarchy,CreateCollection,DeleteCollection,MoveCollection,FolderSync,FolderCreate,FolderDelete,FolderUpdate,MoveItems,GetItemEstimate,MeetingResponse,ResolveRecipients,ValidateCert,Provision,Search,Ping"); |
---|
| 172 | debugLog("Options request"); |
---|
| 173 | break; |
---|
| 174 | case 'POST': |
---|
| 175 | header("MS-Server-ActiveSync: 6.5.7638.1"); |
---|
| 176 | debugLog("POST cmd: $cmd"); |
---|
| 177 | // Do the actual request |
---|
| 178 | if(!HandleRequest($backend, $cmd, $devid, $protocolversion)) { |
---|
| 179 | // Request failed. Try to output some kind of error information. We can only do this if |
---|
| 180 | // output had not started yet. If it has started already, we can't show the user the error, and |
---|
| 181 | // the device will give its own (useless) error message. |
---|
| 182 | if(!headers_sent()) { |
---|
| 183 | header("Content-type: text/html"); |
---|
| 184 | print("<BODY>\n"); |
---|
| 185 | print("<h3>Error</h3><p>\n"); |
---|
| 186 | print("There was a problem processing the <i>$cmd</i> command from your PDA.\n"); |
---|
| 187 | print("<p>Here is the debug output:<p><pre>\n"); |
---|
| 188 | print(getDebugInfo()); |
---|
| 189 | print("</pre>\n"); |
---|
| 190 | print("</BODY>\n"); |
---|
| 191 | } |
---|
| 192 | } |
---|
| 193 | break; |
---|
| 194 | case 'GET': |
---|
| 195 | header("Content-type: text/html"); |
---|
| 196 | print("<BODY>\n"); |
---|
| 197 | print("<h3>GET not supported</h3><p>\n"); |
---|
| 198 | print("This is the z-push location and can only be accessed by Microsoft ActiveSync-capable devices."); |
---|
| 199 | print("</BODY>\n"); |
---|
| 200 | break; |
---|
| 201 | } |
---|
| 202 | |
---|
| 203 | |
---|
| 204 | $len = ob_get_length(); |
---|
| 205 | $data = ob_get_contents(); |
---|
| 206 | |
---|
| 207 | ob_end_clean(); |
---|
| 208 | |
---|
| 209 | // Unfortunately, even though zpush can stream the data to the client |
---|
| 210 | // with a chunked encoding, using chunked encoding also breaks the progress bar |
---|
| 211 | // on the PDA. So we de-chunk here and just output a content-length header and |
---|
| 212 | // send it as a 'normal' packet. If the output packet exceeds 1MB (see ob_start) |
---|
| 213 | // then it will be sent as a chunked packet anyway because PHP will have to flush |
---|
| 214 | // the buffer. |
---|
| 215 | |
---|
| 216 | header("Content-Length: $len"); |
---|
| 217 | print $data; |
---|
| 218 | |
---|
| 219 | // destruct backend after all data is on the stream |
---|
| 220 | $backend->Logoff(); |
---|
| 221 | |
---|
| 222 | debugLog("end"); |
---|
| 223 | debugLog("--------"); |
---|
| 224 | ?> |
---|