/** * Call system.listMethods() * * @param array $method * @return array array(method, method, method...) */ public function fetchSMD() { $request = new Zend_Json_Server_Request(); $request->setVersion('2.0'); $request->setId(1); $this->_smd = new Zend_Json_Client_SMD(); $this->_client->doRequest($request, $this->_smd); }
/** * Start a JSON-RPC server, passing the handler class. * @param string $service_class */ public function service($service_class) { $request = new Zend_Json_Server_Request(); $request->setOptions(array("method" => $this->_request->getParam("method"), "id" => $this->_request->getParam("id"), "params" => $this->_request->getParam("params"))); $server = new Zend_Json_Server(); $server->setClass($service_class); $server->handle($request); exit; }
/** * handle request * * @return void */ public function handle() { try { Tinebase_Core::initFramework(); $exception = FALSE; } catch (Exception $exception) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' initFramework exception: ' . $exception); } // handle all kind of session exceptions as 'Not Authorised' if ($exception instanceof Zend_Session_Exception) { $exception = new Tinebase_Exception_AccessDenied('Not Authorised', 401); // expire session cookie for client Zend_Session::expireSessionCookie(); } } $server = new Zend_Json_Server(); $server->setAutoEmitResponse(false); $server->setAutoHandleExceptions(false); //$server->setUseNamedParams(true); $json = file_get_contents('php://input'); 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($server, $request, $exception) : $this->_handle($server, $request); } else { if (Tinebase_Core::isLogLevel(Zend_Log::NOTICE)) { Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . ' Got empty request options: skip request.'); } $response[] = NULL; } } echo $isBatchedRequest ? '[' . implode(',', $response) . ']' : $response[0]; }
/** * Returns an instance of the native request object * * @return mixed */ public function getNativeRequest() { $method = $this->getMethod(); $params = $this->getParams(); switch ($this->getRequestFormat()) { case 'local': $request = false; $request = $this; break; case 'xmlrpc': $request = new Zend_XmlRpc_Request($method, $params); break; case 'jsonrpc': $request = new Zend_Json_Server_Request(); $request->setMethod($method); $request->setParams($params); $request->setId('1'); $request->setVersion('2.0'); break; } return $request; }
/** * JSON-RPC entrance. * * @return Void */ public function apiAction() { Zend_Registry::set('CMS', true); /** * Prepare the server. Zend_Json_Server cannot work with batched requests natively, * so that's taken care of customly here. Therefore, autoEmitResponse is set to false * so the server doesn't print the response directly. */ $server = new Zend_Json_Server(); $server->setClass('Garp_Content_Manager_Proxy'); $server->setAutoEmitResponse(false); if ($this->getRequest()->isPost()) { $post = $this->_getJsonRpcRequest(); $batch = false; $responses = array(); $requests = Zend_Json::decode($post, Zend_Json::TYPE_ARRAY); /** * Check if this was a batch request. In that case the array is a plain array of * arrays. If not, there will be a 'jsonrpc' key in the root of the array. */ $batch = !array_key_exists('jsonrpc', $requests); if (!$batch) { $requests = array($requests); } foreach ($requests as $i => $request) { $request = $this->_reformJsonRpcRequest($request); $requestJson = Zend_Json::encode($request); $requestObj = new Zend_Json_Server_Request(); $requestObj->loadJson($requestJson); $server->setRequest($requestObj); /** * Note; response gets returned by reference, resulting in a $responses array * containing all the same items. * That's why clone is used here. */ $response = clone $server->handle(); $responses[] = $response; } $response = $batch ? '[' . implode(',', $responses) . ']' : $responses[0]; } else { $response = $server->getServiceMap(); } $this->_helper->layout->setLayout('json'); // filter out escaped slashes, because they're annoying and not necessary. $response = str_replace('\\/', '/', $response); $this->view->response = $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]; }
/** * Send an JSON-RPC request to the service (for a specific method) * * @param string $method Name of the method we want to call * @param array $params Array of parameters for the method * @return mixed * @throws Zend_Json_Client_FaultException */ public function call($method, $params = array()) { if (!$this->skipSystemLookup() && !empty($method)) { $signature = $this->getIntrospector()->getMethodSignature($method); foreach ($params as $key => $param) { if (is_int($key)) { // positional parameters // can't validate them continue; } $keyFound = false; foreach ($signature["parameters"] as $parameter) { if ($parameter['name'] == "{$key}") { $keyFound = true; } } if ($keyFound !== true) { throw new Zend_Json_Client_FaultException("named parameter {$key} not found in SMD"); } } } $request = new Zend_Json_Server_Request(); $request->setVersion('2.0'); $request->setId(1); $request->setMethod($method); $request->setParams($params); $this->doRequest($request); if ($this->_lastResponse->isError()) { $fault = $this->_lastResponse->getError(); /** * Exception thrown when an JSON-RPC fault is returned * @see Zend_Json_Client_FaultException */ require_once 'Zend/Json/Client/FaultException.php'; throw new Zend_Json_Client_FaultException($fault->getMessage(), $fault->getCode()); } return $this->_lastResponse->getResult(); }