/** * Get the right I/O Class and rewrite the content. * * @return $this */ protected function parseResponse() { $strContentType = $this->request->getHeader('Content-Type'); $strContentType = preg_replace("/;.*\$/", "", $strContentType); // Search a engine $objIOEngine = \CtoCommunication\InputOutput\Factory::getEngingeForContentType($strContentType); // Check if we have found one if ($objIOEngine == false) { throw new \RuntimeException("No I/O class found for " . $strContentType); } // Parse response $this->response = $objIOEngine->InputResponse($this->response, $this->objCodifyengine); // Write Debug msg $strDebug = ""; $strDebug .= "Success: "; $strDebug .= $this->response->isSuccess() ? "true" : "false"; $strDebug .= "\n"; if ($this->response->isSplitcontent() == true) { $strDebug .= "Split: " . $this->response->isSplitcontent(); $strDebug .= "\n"; $strDebug .= "Splitinfo: " . "Count - " . $this->response->getSplitcount() . " Name - " . $this->response->getSplitname(); $strDebug .= "\n"; } if ($this->response->getError() != null && is_object($this->response->getError())) { $strDebug .= "Error: " . $this->response->getError()->getMessage(); $strDebug .= "\n"; $strDebug .= "Error RPC: " . $this->response->getError()->getRPC(); $strDebug .= "\n"; $strDebug .= "Error Class: " . $this->response->getError()->getClass(); $strDebug .= "\n"; $strDebug .= "Error Func.: " . $this->response->getError()->getFunction(); $strDebug .= "\n"; } $strDebug .= "Response: " . substr(json_encode($this->response->getResponse()), 0, 2048); $this->objDebug->addDebug("Response Object", $strDebug); return $this; }
/** * Change I/O enginge * * @param string $strName */ public function setIOEngineByAccept($strName = 'text/html') { $this->setIOEngine(\CtoCommunication\InputOutput\Factory::getEngingenameForAccept($strName)); }
/** * Run the communication as client * * @return void */ public function run() { // If we have a ping, just do nothing if (\Input::get("act") == "ping") { // Clean output buffer while (@ob_end_clean()) { } exit; } /* --------------------------------------------------------------------- * Check if we have a old AES or a new AES with IV. * Set codifyengine keys. * Check the connection ID and refresh/delete it. */ // Check if IV was send, when send use the new AES else the old one. try { $this->objCodifyengineBasic = Factory::getEngine("aes"); $this->setCodifyengine(\Input::get("engine")); } catch (\RuntimeException $exc) { \System::log("Try to load the engine for ctoCommunication with error: " . $exc->getMessage(), __FUNCTION__ . " | " . __CLASS__, TL_ERROR); // Clean output buffer while (@ob_end_clean()) { } exit; } // Check if we have a incomming connection for handshake if (in_array(\Input::get("act"), array("CTOCOM_HELLO", "CTOCOM_START_HANDSHAKE", "CTOCOM_CHECK_HANDSHAKE", "CTOCOM_VERSION"))) { $this->objCodifyengine->setKey($GLOBALS['TL_CONFIG']['ctoCom_APIKey']); $this->objCodifyengineBasic->setKey($GLOBALS['TL_CONFIG']['ctoCom_APIKey']); $strCodifyKey = $GLOBALS['TL_CONFIG']['ctoCom_APIKey']; } else { // Use the private key from connection pool if (strlen(\Input::get("con")) != 0) { // Check if we have some data $arrConnections = \Database::getInstance()->prepare("SELECT * FROM tl_ctocom_cache WHERE uid=?")->execute(\Input::get("con"))->fetchAllAssoc(); if (count($arrConnections) == 0) { \System::log(vsprintf("Call from %s with a unknown connection ID.", \Environment::get('ip')), __FUNCTION__ . " | " . __CLASS__, TL_ERROR); // Clean output buffer while (@ob_end_clean()) { } exit; } // Check if time out isn't reached. if ($arrConnections[0]["tstamp"] + $this->intHandshakeTimeout < time()) { \Database::getInstance()->prepare("DELETE FROM tl_ctocom_cache WHERE uid=?")->execute(\Input::get("con")); \System::log(vsprintf("Call from %s with a expired connection ID.", \Environment::get('ip')), __FUNCTION__ . " | " . __CLASS__, TL_ERROR); // Clean output buffer while (@ob_end_clean()) { } exit; } // Reset timestamp \Database::getInstance()->prepare("UPDATE tl_ctocom_cache %s WHERE uid=?")->set(array("tstamp" => time()))->execute(\Input::get("con")); // Set codify key from database $this->objCodifyengineBasic->setKey($arrConnections[0]["shared_secret_key"]); $this->objCodifyengine->setKey($arrConnections[0]["shared_secret_key"]); $strCodifyKey = $arrConnections[0]["shared_secret_key"]; } else { \System::log(vsprintf("Call from %s without a connection ID.", \Environment::get('ip')), __FUNCTION__ . " | " . __CLASS__, TL_ERROR); // Clean output buffer while (@ob_end_clean()) { } exit; } } /* --------------------------------------------------------------------- * Check the API key. * Check if the API Key was send. * Check if the API key contains the RPC Call and the API Key from this * Contao Version. */ // Check if a API-Key was send if (strlen(\Input::get("apikey")) == 0) { \System::log(vsprintf("Call from %s without a API Key.", \Environment::get('ip')), __FUNCTION__ . " | " . __CLASS__, TL_ERROR); // Clean output buffer while (@ob_end_clean()) { } exit; } // Check RPC Call from get and the RPC Call from API-Key $mixVar = $this->objCodifyengineBasic->Decrypt(base64_decode(\Input::get("apikey", true))); $mixVar = trimsplit("@\\|@", $mixVar); $strApiKey = $mixVar[1]; $strAction = $mixVar[0]; if ($strAction != \Input::get("act")) { \System::log(vsprintf("Error Api Key from %s. Request action: %s | Key action: %s | Api: %s", array(\Environment::get('ip'), \Input::get("act"), $strAction, $strApiKey)), __FUNCTION__ . " | " . __CLASS__, TL_ERROR); // Clean output buffer while (@ob_end_clean()) { } exit; } if ($GLOBALS['TL_CONFIG']['ctoCom_APIKey'] != $strApiKey) { \System::log(vsprintf("Call from %s with a wrong API Key: %s", array(\Environment::get('ip'), \Input::get("apikey"))), __FUNCTION__ . " | " . __CLASS__, TL_ERROR); // Clean output buffer while (@ob_end_clean()) { } exit; } /* --------------------------------------------------------------------- * Check language settings */ if (empty($GLOBALS['TL_LANGUAGE'])) { $GLOBALS['TL_LANGUAGE'] = "en"; } /* --------------------------------------------------------------------- * Set I/O System */ if (strlen(\Input::get("format")) != 0) { if (\CtoCommunication\InputOutput\Factory::engineExist(\Input::get("format"))) { $this->setIOEngine(\Input::get("format")); } else { $this->setIOEngine(); $this->objError = new Error(); $this->objError->setLanguage("unknown_io"); $this->objError->setID(10); $this->objError->setObject(""); $this->objError->setMessage("No I/O Interface found for accept."); $this->objError->setRPC(""); $this->objError->setClass(""); $this->objError->setFunction(""); $this->generateOutput(); exit; } } else { $strAccept = $_SERVER['HTTP_ACCEPT']; $strAccept = preg_replace("/;q=\\d\\.\\d/", "", $strAccept); $arrAccept = trimsplit(",", $strAccept); $strIOEngine = false; foreach ($arrAccept as $key => $value) { $strIOEngine = \CtoCommunication\InputOutput\Factory::getEngingenameForAccept($value); if ($strIOEngine !== false) { break; } } if ($strIOEngine === false) { $this->objIOEngine = \CtoCommunication\InputOutput\Factory::getEngine('default'); $this->objError = new Error(); $this->objError->setLanguage("unknown_io"); $this->objError->setID(10); $this->objError->setObject(""); $this->objError->setMessage("No I/O Interface found for accept: {$strAccept}"); $this->objError->setRPC(""); $this->objError->setClass(""); $this->objError->setFunction(""); $this->generateOutput(); exit; } else { $this->setIOEngine($strIOEngine); } } /* --------------------------------------------------------------------- * Run RPC-Check function */ // Check if act is set $mixRPCCall = \Input::get("act"); if (strlen($mixRPCCall) == 0) { $this->objError = new Error(); $this->objError->setLanguage("rpc_missing"); $this->objError->setID(1); $this->objError->setObject(""); $this->objError->setMessage("Missing RPC Call"); $this->objError->setRPC($mixRPCCall); $this->objError->setClass(""); $this->objError->setFunction(""); $this->generateOutput(); exit; } if (!array_key_exists($mixRPCCall, $this->arrRpcList)) { $this->objError = new Error(); $this->objError->setLanguage("rpc_unknown"); $this->objError->setID(1); $this->objError->setObject(""); $this->objError->setMessage("Unknown RPC Call"); $this->objError->setRPC($mixRPCCall); $this->objError->setClass(""); $this->objError->setFunction(""); $this->generateOutput(); exit; } /* --------------------------------------------------------------------- * Build a list with parameter from the POST */ $arrParameter = array(); if ($this->arrRpcList[$mixRPCCall]["parameter"] != false && is_array($this->arrRpcList[$mixRPCCall]["parameter"])) { switch ($this->arrRpcList[$mixRPCCall]["typ"]) { // Decode post case "POST": // Decode each post $arrPostValues = array(); foreach ($_POST as $key => $value) { if (version_compare('3.2.16', VERSION . '.' . BUILD, '<=') && version_compare('3.3.0', VERSION . '.' . BUILD, '>') || version_compare('3.3.7', VERSION . '.' . BUILD, '<=')) { // Get the raw data. $mixPost = \Input::postUnsafeRaw($key); } else { // Get the raw data for older contao versions. $mixPost = \Input::postRaw($key); } $mixPost = $this->objIOEngine->InputPost($mixPost, $this->objCodifyengine); $arrPostValues[$key] = $mixPost; \Input::setPost($key, $mixPost); } // Check if all post are set foreach ($this->arrRpcList[$mixRPCCall]["parameter"] as $value) { $arrPostKey = array_keys($arrPostValues); if (!in_array($value, $arrPostKey)) { $arrParameter[$value] = null; } else { // Get the raw data. $arrParameter[$value] = $arrPostValues[$value]; } } unset($arrPostValues); break; default: break; } } /* --------------------------------------------------------------------- * Call function */ try { $strClassname = $this->arrRpcList[$mixRPCCall]["class"]; if (!class_exists($strClassname)) { $this->objError = new Error(); $this->objError->setLanguage("rpc_class_not_exists"); $this->objError->setID(4); $this->objError->setObject($value); $this->objError->setMessage("The choosen class didn`t exists."); $this->objError->setRPC($mixRPCCall); $this->objError->setClass($this->arrRpcList[$mixRPCCall]["class"]); $this->objError->setFunction($this->arrRpcList[$mixRPCCall]["function"]); $this->generateOutput(); exit; } $objReflection = new \ReflectionClass($strClassname); if ($objReflection->hasMethod("getInstance")) { $object = call_user_func_array(array($this->arrRpcList[$mixRPCCall]["class"], "getInstance"), array()); $this->mixOutput = call_user_func_array(array($object, $this->arrRpcList[$mixRPCCall]["function"]), $arrParameter); } else { $object = new $this->arrRpcList[$mixRPCCall]["class"](); $this->mixOutput = call_user_func_array(array($object, $this->arrRpcList[$mixRPCCall]["function"]), $arrParameter); } } catch (\Exception $exc) { $this->objError = new Error(); $this->objError->setLanguage("rpc_unknown_exception"); $this->objError->setID(3); $this->objError->setObject(""); $this->objError->setMessage($exc->getMessage()); $this->objError->setRPC($mixRPCCall); $this->objError->setClass($this->arrRpcList[$mixRPCCall]["class"]); $this->objError->setFunction($this->arrRpcList[$mixRPCCall]["function"]); $this->objError->setException($exc); \System::log(vsprintf("RPC Exception: %s | %s", array($exc->getMessage(), nl2br($exc->getTraceAsString()))), __CLASS__ . " | " . __FUNCTION__, TL_ERROR); $this->generateOutput(); exit; } $this->generateOutput(); exit; }