/** * (non-PHPdoc) * @see Tinebase_Server_Interface::handle() */ public function handle(\Zend\Http\Request $request = null, $body = null) { Tinebase_Session_Abstract::setSessionEnabled('TINE20SETUPSESSID'); if (Tinebase_Session::sessionExists()) { Setup_Core::startSetupSession(); } Setup_Core::initFramework(); if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' is http request. method: ' . $this->getRequestMethod()); } $server = new Tinebase_Http_Server(); $server->setClass('Setup_Frontend_Http', 'Setup'); $server->setClass('Tinebase_Frontend_Http', 'Tinebase'); // needed for fetching translation in DEVELOPMENT mode if (empty($_REQUEST['method'])) { $_REQUEST['method'] = 'Setup.mainScreen'; } $server->handle($_REQUEST); }
/** * (non-PHPdoc) * @see Tinebase_Server_Interface::handle() */ public function handle(\Zend\Http\Request $request = null, $body = null) { try { // init server and request first $server = new Zend_Json_Server(); $server->setClass('Setup_Frontend_Json', 'Setup'); $server->setClass('Tinebase_Frontend_Json', 'Tinebase'); $server->setAutoHandleExceptions(false); $server->setAutoEmitResponse(false); $request = new Zend_Json_Server_Request_Http(); if (Tinebase_Session::sessionExists()) { Setup_Core::startSetupSession(); } Setup_Core::initFramework(); $method = $request->getMethod(); $jsonKey = isset($_SERVER['HTTP_X_TINE20_JSONKEY']) ? $_SERVER['HTTP_X_TINE20_JSONKEY'] : ''; Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' is JSON request. method: ' . $method); $anonymnousMethods = array('Setup.getAllRegistryData', 'Setup.login', 'Tinebase.getAvailableTranslations', 'Tinebase.getTranslations', 'Tinebase.setLocale'); if (!Setup_Core::configFileExists()) { $anonymnousMethods = array_merge($anonymnousMethods, array('Setup.envCheck')); } // check json key for all methods but some exceptions if (!in_array($method, $anonymnousMethods) && Setup_Core::configFileExists() && (empty($jsonKey) || $jsonKey != Setup_Core::get('jsonKey') || !Setup_Core::isRegistered(Setup_Core::USER))) { if (!Setup_Core::isRegistered(Setup_Core::USER)) { Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Attempt to request a privileged Json-API method without authorisation from "' . $_SERVER['REMOTE_ADDR'] . '". (session timeout?)'); throw new Tinebase_Exception_AccessDenied('Not Authorised', 401); } else { Setup_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' Fatal: got wrong json key! (' . $jsonKey . ') Possible CSRF attempt!' . ' affected account: ' . print_r(Setup_Core::getUser(), true) . ' request: ' . print_r($_REQUEST, true)); throw new Tinebase_Exception_AccessDenied('Not Authorised', 401); } } $response = $server->handle($request); } catch (Exception $exception) { $response = $this->_handleException($request, $exception); } echo $response; }
/** * (non-PHPdoc) * @see Tinebase_Server_Interface::handle() */ public function handle(\Zend\Http\Request $request = null, $body = null) { $this->_request = $request instanceof \Zend\Http\Request ? $request : Tinebase_Core::get(Tinebase_Core::REQUEST); $this->_body = $body !== null ? $body : fopen('php://input', 'r'); $request = $request instanceof \Zend\Http\Request ? $request : new \Zend\Http\PhpEnvironment\Request(); // only for debugging //Tinebase_Core::getLogger()->DEBUG(__METHOD__ . '::' . __LINE__ . " raw request: " . $request->__toString()); // handle CORS requests if ($request->getHeaders()->has('ORIGIN') && !$request->getHeaders()->has('X-FORWARDED-HOST')) { /** * First the client sends a preflight request * * METHOD: OPTIONS * Access-Control-Request-Headers:x-requested-with, content-type * Access-Control-Request-Method:POST * Origin:http://other.site * Referer:http://other.site/example.html * User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36 * * We have to respond with * * Access-Control-Allow-Credentials:true * Access-Control-Allow-Headers:x-requested-with, x-tine20-request-type, content-type, x-tine20-jsonkey * Access-Control-Allow-Methods:POST * Access-Control-Allow-Origin:http://other.site * * Then the client sends the standard JSON request with two additional headers * * METHOD: POST * Origin:http://other.site * Referer:http://other.site/example.html * Standard-JSON-Rquest-Headers... * * We have to add two additional headers to our standard response * * Access-Control-Allow-Credentials:true * Access-Control-Allow-Origin:http://other.site */ $origin = $request->getHeaders('ORIGIN')->getFieldValue(); $uri = \Zend\Uri\UriFactory::factory($origin); if (in_array($uri->getScheme(), array('http', 'https'))) { $allowedOrigins = array_merge((array) Tinebase_Core::getConfig()->get(Tinebase_Config::ALLOWEDJSONORIGINS, array()), array($this->_request->getServer('SERVER_NAME'))); if (in_array($uri->getHost(), $allowedOrigins)) { // this headers have to be sent, for any CORS'ed JSON request header('Access-Control-Allow-Origin: ' . $origin); header('Access-Control-Allow-Credentials: true'); } // check for CORS preflight request if ($request->getMethod() == \Zend\Http\Request::METHOD_OPTIONS && $request->getHeaders()->has('ACCESS-CONTROL-REQUEST-METHOD')) { $this->_methods = array('handleCors'); if (in_array($uri->getHost(), $allowedOrigins)) { header('Access-Control-Allow-Methods: POST'); header('Access-Control-Allow-Headers: x-requested-with, x-tine20-request-type, content-type, x-tine20-jsonkey'); header('Access-Control-Max-Age: 3600'); // cache result of OPTIONS request for 1 hour } else { Tinebase_Core::getLogger()->WARN(__METHOD__ . '::' . __LINE__ . " unhandled CORS preflight request from {$origin}"); Tinebase_Core::getLogger()->INFO(__METHOD__ . '::' . __LINE__ . " you may want to set \"'allowedJsonOrigins' => array('{$uri->getHost()}'),\" to config.inc.php"); Tinebase_Core::getLogger()->DEBUG(__METHOD__ . '::' . __LINE__ . " allowed origins: " . print_r($allowedOrigins, TRUE)); } // stop further processing => is OPTIONS request return; } } } $exception = false; if (Tinebase_Session::sessionExists()) { try { Tinebase_Core::startCoreSession(); } catch (Zend_Session_Exception $zse) { $exception = new Tinebase_Exception_AccessDenied('Not Authorised', 401); // expire session cookie for client Tinebase_Session::expireSessionCookie(); } } if ($exception === false) { try { Tinebase_Core::initFramework(); } catch (Exception $exception) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' initFramework exception: ' . $exception); } } } $json = $request->getContent(); $json = Tinebase_Core::filterInputForDatabase($json); if (substr($json, 0, 1) == '[') { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' batched request'); } $isBatchedRequest = true; $requests = Zend_Json::decode($json); } else { $isBatchedRequest = false; $requests = array(Zend_Json::decode($json)); } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { $_requests = $requests; foreach (array('password', 'oldPassword', 'newPassword') as $field) { if (isset($requests[0]["params"][$field])) { $_requests[0]["params"][$field] = "*******"; } } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' is JSON request. rawdata: ' . print_r($_requests, true)); } } $response = array(); foreach ($requests as $requestOptions) { if ($requestOptions !== NULL) { $request = new Zend_Json_Server_Request(); $request->setOptions($requestOptions); $response[] = $exception ? $this->_handleException($request, $exception) : $this->_handle($request); } else { if (Tinebase_Core::isLogLevel(Zend_Log::NOTICE)) { Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . ' Got empty request options: skip request.'); } $response[] = NULL; } } if (!headers_sent()) { header('Content-type: application/json'); } echo $isBatchedRequest ? '[' . implode(',', $response) . ']' : $response[0]; }
/** * (non-PHPdoc) * @see Tinebase_Server_Interface::handle() */ public function handle(\Zend\Http\Request $request = null, $body = null) { $this->_request = $request instanceof \Zend\Http\Request ? $request : Tinebase_Core::get(Tinebase_Core::REQUEST); $this->_body = $body !== null ? $body : fopen('php://input', 'r'); $server = new Tinebase_Http_Server(); $server->setClass('Tinebase_Frontend_Http', 'Tinebase'); $server->setClass('Filemanager_Frontend_Download', 'Download'); try { if (Tinebase_Session::sessionExists()) { try { Tinebase_Core::startCoreSession(); } catch (Zend_Session_Exception $zse) { // expire session cookie for client Tinebase_Session::expireSessionCookie(); } } Tinebase_Core::initFramework(); if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) { Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Is HTTP request. method: ' . $this->getRequestMethod()); } if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' REQUEST: ' . print_r($_REQUEST, TRUE)); } // register additional HTTP apis only available for authorised users if (Tinebase_Session::isStarted() && Zend_Auth::getInstance()->hasIdentity()) { if (empty($_REQUEST['method'])) { $_REQUEST['method'] = 'Tinebase.mainScreen'; } $applicationParts = explode('.', $this->getRequestMethod()); $applicationName = ucfirst($applicationParts[0]); if (Tinebase_Core::getUser() && Tinebase_Core::getUser()->hasRight($applicationName, Tinebase_Acl_Rights_Abstract::RUN)) { try { $server->setClass($applicationName . '_Frontend_Http', $applicationName); } catch (Exception $e) { Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . " Failed to add HTTP API for application '{$applicationName}' Exception: \n" . $e); } } } else { if (empty($_REQUEST['method'])) { $_REQUEST['method'] = 'Tinebase.login'; } // sessionId got send by client, but we don't use sessions for non authenticated users if (Tinebase_Session::sessionExists()) { // expire session cookie on client Tinebase_Session::expireSessionCookie(); } } $this->_method = $this->getRequestMethod(); $server->handle($_REQUEST); } catch (Zend_Json_Server_Exception $zjse) { // invalid method requested or not authenticated, etc. Tinebase_Exception::log($zjse); Tinebase_Core::getLogger()->INFO(__METHOD__ . '::' . __LINE__ . ' Attempt to request a privileged Http-API method without valid session from "' . $_SERVER['REMOTE_ADDR']); header('HTTP/1.0 403 Forbidden'); exit; } catch (Exception $exception) { Tinebase_Exception::log($exception, false); try { $setupController = Setup_Controller::getInstance(); if ($setupController->setupRequired()) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Setup required'); } $this->_method = 'Tinebase.setupRequired'; } else { if (preg_match('/download|export/', $this->_method)) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Server error during download/export - exit with 500'); } header('HTTP/1.0 500 Internal Server Error'); exit; } else { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Show mainscreen with setup exception'); } $this->_method = 'Tinebase.exception'; } } $server->handle(array('method' => $this->_method)); } catch (Exception $e) { header('HTTP/1.0 503 Service Unavailable'); die('Service Unavailable'); } } }