Example #1
0
 /**
  *	Handle Request
  *	Called on Each controller until request is handled
  *	@param \Touchbase\Control\HTTPRequest &$request
  *	@param \Touchbase\Control\HTTPResponse &$response
  *	@return mixed $result
  */
 public function handleRequest(HTTPRequest &$request, HTTPResponse &$response)
 {
     $handlerClass = "{$this}";
     while ($handlerClass != __CLASS__) {
         $getClassUrlHandler = get_class_vars($handlerClass);
         $urlHandlers = $getClassUrlHandler['urlHandlers'];
         if (!empty($urlHandlers)) {
             foreach ($urlHandlers as $rule => $action) {
                 if (is_numeric($rule)) {
                     $rule = $action;
                     $action = $this->defaultAction;
                 }
                 //\pre_r("Testing '$rule' with '".$request->remaining()."' on '$this'");
                 if ($params = $request->match($rule)) {
                     //\pre_r("Rule '$rule' matched to action '$action' on '$this'");
                     if ($action[0] == "\$") {
                         $action = $params[substr($action, 1)];
                     }
                     if (!$action) {
                         user_error("Action not set; using default action method name 'index'", E_USER_NOTICE);
                         $action = 'index';
                     } else {
                         if (!is_string($action)) {
                             user_error("Non-string method name: " . var_export($action, true), E_USER_ERROR);
                         }
                     }
                     if (!$this->hasMethod($action) || !$this->isEnabled() || !$this->application()->isEnabled()) {
                         return $this->throwHTTPError(404, "Action '{$action}' isn't available on class {$this}");
                     }
                     if (!$this->isAllowed() || !$this->application()->isAllowed() || !$this->checkAccessAction($action)) {
                         return $this->throwHTTPError(403, "Action '{$action}' isn't allowed on class {$this}");
                     }
                     if (!$request->allParsed()) {
                         return $this->throwHTTPError(404, "I can't handle sub-URLs of a {$this} object");
                     }
                     //Set Controller Vars and Call Action
                     $this->setParams($request->urlParams());
                     //Call Controller Init
                     $this->init();
                     if (!$this->baseInitCalled) {
                         user_error("init() method on class '{$this}' doesn't call Controller::init(). Make sure that you have parent::init() included.", E_USER_WARNING);
                     }
                     return $this->{$action}($request);
                 }
             }
         }
         //Update $handlerClass
         $handlerClass = get_parent_class($handlerClass);
     }
     //Nothing matches.
     return $this;
 }
 /**
  *	Handle Request
  *	@param HTTPRequest &$request
  *	@param HTTPResponse &$response
  *	@return string
  */
 public function handleRequest(HTTPRequest &$request, HTTPResponse &$response)
 {
     //Pass through to Controller
     try {
         $response = new WebpageResponse($this);
         if ($request->isPost()) {
             $validation = Validation::create();
             $this->validatePostRequest($request, $response, $validation);
         }
         $body = parent::handleRequest($request, $response);
     } catch (\Exception $e) {
         if (!$e instanceof HTTPResponseException) {
             error_log(print_r($e, true));
             $e = new HTTPResponseException($e->getMessage(), 500);
             $e->response()->setHeader('Content-Type', 'text/plain');
         }
         $body = $this->handleException($e);
         //If handleException returns a redirect. Follow it.
         if ($body instanceof \Touchbase\Control\HTTPResponse) {
             //TODO: Should we always return the response?
             if ($body->hasFinished()) {
                 return $response = $body;
             }
         }
         $response->setBody($body);
         $response->setStatusCode($e->getCode(), $e->getMessage());
     }
     if ($this->request()->isMainRequest()) {
         $applicationTitles = [];
         $application = $this->application;
         while ($application != null) {
             if (isset($application::$name)) {
                 $applicationTitles[] = $application::$name;
             }
             $application = $application->application;
         }
         $this->response()->assets()->pushTitle(array_reverse($applicationTitles));
         if (isset(static::$name)) {
             $this->response()->assets()->pushTitle(static::$name);
         }
     }
     return $body;
 }
Example #3
0
 /**
  *	Handle Request
  *	This method will attempt to load a real resource located on the server if one exists.
  *	@param \Touchbase\Control\HTTPRequest $request
  *	@param \Touchbase\Control\HTTPResponse &$response
  *	@return mixed
  */
 private static function handleRequest(HTTPRequest $request, HTTPResponse &$response)
 {
     //TopSite Preview
     if (isset($_SERVER["HTTP_X_PURPOSE"]) && $_SERVER["HTTP_X_PURPOSE"] == "preview") {
         $assetFile = File::create([BASE_PATH, 'public_html', 'preview.html']);
         //Favicon
     } else {
         if ($request->urlSegment() == "favicon") {
             $assetFile = File::create([BASE_PATH, 'public_html', 'favicon.ico']);
             if (!$assetFile->exists()) {
                 //Write an empty favicon if one doesn't exist
                 $assetFile->write(base64_decode("iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAFklEQVR42mNkoBAwjhowasCoAcPFAAAmmAARm5JBWgAAAABJRU5ErkJggg=="));
             }
             //Asset Map
         } else {
             $assetFilePath = static::pathForAssetMap($request->urlSegment());
             if ($assetFilePath) {
                 $assetFile = File::create([BASE_PATH, $assetFilePath, implode("/", $request->urlSegments(1)) . '.' . $request->extension()]);
             }
         }
     }
     if (isset($assetFile)) {
         $supportedAssets = ["css" => "text/css; charset=utf-8", "js" => "text/javascript; charset=utf-8", "htc" => "text/x-component", "png" => "image/png", "jpg" => "image/jpg", "gif" => "image/gif", "svg" => "image/svg+xml", "ico" => "image/x-icon", "otf" => "application/font-otf", "eot" => "application/vnd.ms-fontobject", "ttf" => "application/font-ttf", "woff" => "application/font-woff", "woff2" => "application/font-woff2", "apk" => "application/vnd.android.package-archive", "ipa" => "application/octet-stream"];
         if ($assetFile->exists() && array_key_exists($assetFile->ext(), $supportedAssets)) {
             session_cache_limiter(false);
             $response->addHeader("Content-Type", $supportedAssets[$assetFile->ext()]);
             $response->addHeader("Content-Disposition", "attachment; filename=" . $assetFile->name);
             $response->addHeader('Content-Length', $assetFile->size());
             //TODO: Should be done in response setBody!
             if (php_sapi_name() != 'cli-server' && static::config("assets")->get("x_sendfile", false)) {
                 $response->addHeader("X-Sendfile", $assetFile->path);
             } else {
                 $response->setBody($assetFile->read());
             }
             return true;
         }
     }
     return false;
 }
 /**
  *	Validate Post Request
  *	This method adds default validation to input fields based on the served HTML.
  *	If any errors are found, the redirect will be made on the response object with the errors.
  *	@param \Touchbase\Control\HTTPRequest $request
  *	@param \Touchbase\Control\HTTPResponse &$response
  *	@param \Touchbase\Utils\Validation &$validation
  *	@return VOID
  */
 protected function validatePostRequest($request, &$response, &$validation)
 {
     if (!$request->isMainRequest()) {
         return;
     }
     $formNameToken = $request->_VAR("tb_form_token");
     $formName = substr($formNameToken, 0, strrpos($formNameToken, "_"));
     if (isset($formNameToken) && ($form = SessionStore::get($formNameToken, false))) {
         SessionStore::consume($formName, $formNameToken);
         $data = $request->_VARS();
         libxml_use_internal_errors(true);
         $dom = new \DOMDocument();
         $dom->loadHtml(gzinflate(base64_decode($form)), LIBXML_NOWARNING | LIBXML_NOERROR);
         if ($dom->documentElement->getAttribute("novalidate")) {
             return;
         }
         $formValidation = Validation::create($formName);
         $privateFields = [];
         foreach (["input", "textarea", "select"] as $tag) {
             foreach ($dom->getElementsByTagName($tag) as $input) {
                 if ($input->hasAttributes() && ($inputName = $input->getAttribute("name"))) {
                     $inputType = $input->getAttribute("type");
                     $inputValidation = Validation::create($inputName);
                     if ($inputType === "password") {
                         $privateFields[] = $inputName;
                     }
                     $inputValidation->type($inputType);
                     if ($inputType === "file" && $input->hasAttribute("accept")) {
                         $validTypes = explode(",", $input->getAttribute("accept"));
                         //File Extentions
                         $fileExt = array_filter($validTypes, function ($value) {
                             return strpos($value, ".") === 0;
                         });
                         if (!empty($fileExt)) {
                             $inputValidation->addRule(function ($value) use($fileExt) {
                                 $name = $value['name'];
                                 if (is_array($name)) {
                                     foreach ($name as $nme) {
                                         if (!in_array(pathinfo($nme, PATHINFO_EXTENSION), $fileExt)) {
                                             return false;
                                         }
                                     }
                                     return true;
                                 }
                                 return in_array(pathinfo($name, PATHINFO_EXTENSION), $fileExt);
                             }, "A file uploaded did not have the correct extension");
                         }
                         //Mime Types
                         $validTypes = array_diff($validTypes, $fileExt);
                         $implicitFileMime = array_filter($validTypes, function ($value) {
                             return strpos($value, "/*") !== false;
                         });
                         if (!empty($implicitFileMime)) {
                             $inputValidation->addRule(function ($value) use($implicitFileMime) {
                                 $tmpName = $value['tmp_name'];
                                 if (is_array($tmpName)) {
                                     foreach ($tmpName as $tmp) {
                                         $mime = strstr(File::create($tmp)->mime(), "/", true) . "/*";
                                         if (!in_array($mime, $implicitFileMime)) {
                                             return false;
                                         }
                                     }
                                     return true;
                                 }
                                 $mime = strstr(File::create($tmpName)->mime(), "/", true) . "/*";
                                 return in_array($mime, $implicitFileMime);
                             }, "A file uploaded did not have the correct mime type");
                         }
                         $validTypes = array_diff($validTypes, $implicitFileMime);
                         $fileMime = array_filter($validTypes, function ($value) {
                             return strpos($value, "/") !== false;
                         });
                         if (!empty($fileMime)) {
                             $inputValidation->addRule(function ($value) use($fileMime) {
                                 $tmpName = $value['tmp_name'];
                                 if (is_array($tmpName)) {
                                     foreach ($tmpName as $tmp) {
                                         if (!in_array(File::create($tmp)->mime(), $fileMime)) {
                                             return false;
                                         }
                                     }
                                     return true;
                                 }
                                 return in_array(File::create($tmpName)->mime(), $fileMime);
                             }, "A file uploaded did not have the correct mime type");
                         }
                     }
                     if ($input->hasAttribute("required")) {
                         $errorMessage = null;
                         if ($placeholder = $input->getAttribute("placeholder")) {
                             $errorMessage = sprintf("Please complete the `%s` field", $placeholder);
                         }
                         $inputValidation->required($errorMessage);
                     }
                     if ($input->hasAttribute("readonly")) {
                         $inputValidation->readonly($input->getAttribute("value"));
                     }
                     if ($input->hasAttribute("disabled")) {
                         $inputValidation->disabled();
                     }
                     if ($minLength = $input->getAttribute("minlength")) {
                         $inputValidation->minLength($minLength);
                     }
                     if ($maxLength = $input->getAttribute("maxlength")) {
                         $inputValidation->maxLength($maxLength);
                     }
                     if (in_array($inputType, ["number", "range", "date", "datetime", "datetime-local", "month", "time", "week"])) {
                         if ($min = $input->getAttribute("min")) {
                             $inputValidation->min($min, $inputType);
                         }
                         if ($max = $input->getAttribute("max")) {
                             $inputValidation->max($max, $inputType);
                         }
                     }
                     if ($pattern = $input->getAttribute("pattern")) {
                         $inputValidation->pattern($pattern);
                     }
                     if (count($inputValidation)) {
                         $validation->addRule($formValidation->addRule($inputValidation));
                     }
                 }
             }
         }
         if (!$validation->validate($data)) {
             $response->withData(array_diff_key($data, array_flip($privateFields)));
             $response->redirect(-1)->withErrors($validation->errors, $formName);
         }
     } else {
         $response->redirect(-1)->withErrors(["Session timed out, please try again."], $formName);
     }
 }