/** * @param array $record * @return bool */ protected function write(array $record) { ini_set('display_errors', 0); // TODO: This coupling isn't ideal // See https://github.com/silverstripe/silverstripe-framework/issues/4484 if (Controller::has_curr()) { $response = Controller::curr()->getResponse(); } else { $response = new HTTPResponse(); } // If headers have been sent then these won't be used, and may throw errors that we wont' want to see. if (!headers_sent()) { $response->setStatusCode($this->statusCode); $response->addHeader("Content-Type", $this->contentType); } else { // To supress errors aboot errors $response->setStatusCode(200); } $response->setBody($record['formatted']); $response->output(); return false === $this->bubble; }
/** * Create a response with the given error code * * @param int $code * @return HTTPResponse */ protected function createErrorResponse($code) { $response = new HTTPResponse('', $code); // Show message in dev if (!Director::isLive()) { $response->setBody($response->getStatusDescription()); } return $response; }
/** * Require basic authentication. Will request a username and password if none is given. * * Used by {@link Controller::init()}. * * @throws HTTPResponse_Exception * * @param string $realm * @param string|array $permissionCode Optional * @param boolean $tryUsingSessionLogin If true, then the method with authenticate against the * session log-in if those credentials are disabled. * @return Member|bool $member */ public static function requireLogin($realm, $permissionCode = null, $tryUsingSessionLogin = true) { $isRunningTests = class_exists('SilverStripe\\Dev\\SapphireTest', false) && SapphireTest::is_running_test(); if (!Security::database_is_ready() || Director::is_cli() && !$isRunningTests) { return true; } /* * Enable HTTP Basic authentication workaround for PHP running in CGI mode with Apache * Depending on server configuration the auth header may be in HTTP_AUTHORIZATION or * REDIRECT_HTTP_AUTHORIZATION * * The follow rewrite rule must be in the sites .htaccess file to enable this workaround * RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] */ $authHeader = isset($_SERVER['HTTP_AUTHORIZATION']) ? $_SERVER['HTTP_AUTHORIZATION'] : (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) ? $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] : null); $matches = array(); if ($authHeader && preg_match('/Basic\\s+(.*)$/i', $authHeader, $matches)) { list($name, $password) = explode(':', base64_decode($matches[1])); $_SERVER['PHP_AUTH_USER'] = strip_tags($name); $_SERVER['PHP_AUTH_PW'] = strip_tags($password); } $member = null; if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) { $member = MemberAuthenticator::authenticate(array('Email' => $_SERVER['PHP_AUTH_USER'], 'Password' => $_SERVER['PHP_AUTH_PW']), null); } if (!$member && $tryUsingSessionLogin) { $member = Member::currentUser(); } // If we've failed the authentication mechanism, then show the login form if (!$member) { $response = new HTTPResponse(null, 401); $response->addHeader('WWW-Authenticate', "Basic realm=\"{$realm}\""); if (isset($_SERVER['PHP_AUTH_USER'])) { $response->setBody(_t('BasicAuth.ERRORNOTREC', "That username / password isn't recognised")); } else { $response->setBody(_t('BasicAuth.ENTERINFO', "Please enter a username and password.")); } // Exception is caught by RequestHandler->handleRequest() and will halt further execution $e = new HTTPResponse_Exception(null, 401); $e->setResponse($response); throw $e; } if ($permissionCode && !Permission::checkMember($member->ID, $permissionCode)) { $response = new HTTPResponse(null, 401); $response->addHeader('WWW-Authenticate', "Basic realm=\"{$realm}\""); if (isset($_SERVER['PHP_AUTH_USER'])) { $response->setBody(_t('BasicAuth.ERRORNOTADMIN', "That user is not an administrator.")); } // Exception is caught by RequestHandler->handleRequest() and will halt further execution $e = new HTTPResponse_Exception(null, 401); $e->setResponse($response); throw $e; } return $member; }
/** * Process the given URL, creating the appropriate controller and executing it. * * Request processing is handled as follows: * - Director::direct() creates a new HTTPResponse object and passes this to * Director::handleRequest(). * - Director::handleRequest($request) checks each of the Director rules and identifies a controller * to handle this request. * - Controller::handleRequest($request) is then called. This will find a rule to handle the URL, * and call the rule handling method. * - RequestHandler::handleRequest($request) is recursively called whenever a rule handling method * returns a RequestHandler object. * * In addition to request processing, Director will manage the session, and perform the output of * the actual response to the browser. * * @uses handleRequest() rule-lookup logic is handled by this. * @uses Controller::handleRequest() This handles the page logic for a Director::direct() call. * @param string $url * @param DataModel $model * @throws HTTPResponse_Exception */ public static function direct($url, DataModel $model) { // Validate $_FILES array before merging it with $_POST foreach ($_FILES as $k => $v) { if (is_array($v['tmp_name'])) { $v = ArrayLib::array_values_recursive($v['tmp_name']); foreach ($v as $tmpFile) { if ($tmpFile && !is_uploaded_file($tmpFile)) { user_error("File upload '{$k}' doesn't appear to be a valid upload", E_USER_ERROR); } } } else { if ($v['tmp_name'] && !is_uploaded_file($v['tmp_name'])) { user_error("File upload '{$k}' doesn't appear to be a valid upload", E_USER_ERROR); } } } $req = new HTTPRequest(isset($_SERVER['X-HTTP-Method-Override']) ? $_SERVER['X-HTTP-Method-Override'] : $_SERVER['REQUEST_METHOD'], $url, $_GET, ArrayLib::array_merge_recursive((array) $_POST, (array) $_FILES), @file_get_contents('php://input')); $headers = self::extract_request_headers($_SERVER); foreach ($headers as $header => $value) { $req->addHeader($header, $value); } // Initiate an empty session - doesn't initialize an actual PHP session until saved (see below) $session = Session::create(isset($_SESSION) ? $_SESSION : array()); // Only resume a session if its not started already, and a session identifier exists if (!isset($_SESSION) && Session::request_contains_session_id()) { $session->inst_start(); } $output = RequestProcessor::singleton()->preRequest($req, $session, $model); if ($output === false) { // @TODO Need to NOT proceed with the request in an elegant manner throw new HTTPResponse_Exception(_t('Director.INVALID_REQUEST', 'Invalid request'), 400); } $result = Director::handleRequest($req, $session, $model); // Save session data. Note that inst_save() will start/resume the session if required. $session->inst_save(); // Return code for a redirection request if (is_string($result) && substr($result, 0, 9) == 'redirect:') { $url = substr($result, 9); if (Director::is_cli()) { // on cli, follow SilverStripe redirects automatically Director::direct(str_replace(Director::absoluteBaseURL(), '', $url), DataModel::inst()); return; } else { $response = new HTTPResponse(); $response->redirect($url); $res = RequestProcessor::singleton()->postRequest($req, $response, $model); if ($res !== false) { $response->output(); } } // Handle a controller } elseif ($result) { if ($result instanceof HTTPResponse) { $response = $result; } else { $response = new HTTPResponse(); $response->setBody($result); } $res = RequestProcessor::singleton()->postRequest($req, $response, $model); if ($res !== false) { $response->output(); } else { // @TODO Proper response here. throw new HTTPResponse_Exception("Invalid response"); } //$controllerObj->getSession()->inst_save(); } }
/** * REST endpoint to get a list of campaigns. * * @return HTTPResponse */ public function readCampaigns() { $response = new HTTPResponse(); $response->addHeader('Content-Type', 'application/json'); $hal = $this->getListResource(); $response->setBody(Convert::array2json($hal)); return $response; }
/** * Performs the following replacements: * - Check user defined content type and use it, if it's empty use the text/html. * - If find a XML header replaces it and existing doctypes with HTML4.01 Strict. * - Replaces self-closing tags like <img /> with unclosed solitary tags like <img>. * - Replaces all occurrences of "application/xhtml+xml" with "text/html" in the template. * - Removes "xmlns" attributes and any <?xml> Pragmas. * * @param HTTPResponse $response */ public function html(HTTPResponse $response) { $encoding = $this->config()->get('encoding'); $contentType = $this->config()->get('content_type'); if (empty($contentType)) { $response->addHeader("Content-Type", "text/html; charset=" . $encoding); } else { $response->addHeader("Content-Type", $contentType . "; charset=" . $encoding); } $response->addHeader("Vary", "Accept"); $content = $response->getBody(); $hasXMLHeader = substr($content, 0, 5) == '<' . '?xml'; // Fix base tag $content = preg_replace('/<base href="([^"]*)" \\/>/', '<base href="$1"><!--[if lte IE 6]></base><![endif]-->', $content); $content = preg_replace("#<\\?xml[^>]+\\?>\n?#", '', $content); $content = str_replace(array('/>', 'xml:lang', 'application/xhtml+xml'), array('>', 'lang', 'text/html'), $content); // Only replace the doctype in templates with the xml header if ($hasXMLHeader) { $content = preg_replace('/<!DOCTYPE[^>]+>/', '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">', $content); } $content = preg_replace('/<html xmlns="[^"]+"/', '<html ', $content); $response->setBody($content); }
/** * @param HTTPRequest $request * * @return HTTPResponse */ public function apiSearch(HTTPRequest $request) { $params = $request->getVars(); $list = $this->getList($params); $response = new HTTPResponse(); $response->addHeader('Content-Type', 'application/json'); $response->setBody(json_encode(["files" => array_map(function ($file) { return $this->getObjectFromData($file); }, $list->toArray()), "count" => $list->count()])); return $response; }