public function placeOrder(SS_HTTPRequest $request) { $eventbrite_event_header = $request->getHeader('X-Eventbrite-Event'); if (!$eventbrite_event_header) { return $this->httpError(403); } if ($eventbrite_event_header !== 'order.placed') { return $this->httpError(403); } if (!$this->isJson()) { return $this->httpError(403); } $json_request = $this->getJsonRequest(); if (!isset($json_request['config']) || !isset($json_request['api_url'])) { return $this->httpError(403); } $config = $json_request['config']; if (!isset($config['action']) || $config['action'] !== 'order.placed') { return $this->httpError(403); } $current_local_url = Controller::join_links(Director::absoluteBaseURL(), $request->getURL()); if (!isset($config['endpoint_url']) || $config['endpoint_url'] !== $current_local_url) { return $this->httpError(403); } try { $this->manager->registerEvent('ORDER_PLACED', $json_request['api_url']); } catch (Exception $ex) { SS_Log::log($ex->getMessage(), SS_Log::ERR); return $this->httpError(500); } return true; }
/** * Out of the box, the handler "CurrentForm" value, which will return the rendered form. * Non-Ajax calls will redirect back. * * @param SS_HTTPRequest $request * @param array $extraCallbacks List of anonymous functions or callables returning either a string * or SS_HTTPResponse, keyed by their fragment identifier. The 'default' key can * be used as a fallback for non-ajax responses. * @param array $fragmentOverride Change the response fragments. * @return SS_HTTPResponse */ public function respond(SS_HTTPRequest $request, $extraCallbacks = array()) { // Prepare the default options and combine with the others $callbacks = array_merge($this->callbacks, $extraCallbacks); $response = $this->getResponse(); $responseParts = array(); if (isset($this->fragmentOverride)) { $fragments = $this->fragmentOverride; } elseif ($fragmentStr = $request->getHeader('X-Pjax')) { $fragments = explode(',', $fragmentStr); } else { if ($request->isAjax()) { throw new SS_HTTPResponse_Exception("Ajax requests to this URL require an X-Pjax header.", 400); } $response->setBody(call_user_func($callbacks['default'])); return $response; } // Execute the fragment callbacks and build the response. foreach ($fragments as $fragment) { if (isset($callbacks[$fragment])) { $res = call_user_func($callbacks[$fragment]); $responseParts[$fragment] = $res ? (string) $res : $res; } else { throw new SS_HTTPResponse_Exception("X-Pjax = '{$fragment}' not supported for this URL.", 400); } } $response->setBody(Convert::raw2json($responseParts)); $response->addHeader('Content-Type', 'text/json'); return $response; }
protected function getToken(SS_HTTPRequest $request) { $token = $request->requestVar('token'); if (!$token) { $token = $request->getHeader('X-Auth-Token'); } return $token; }
/** * Looks first for the X-Pull-Regions header and then for a __regions__ get/post var. * @return array */ protected function getPulledRegionIDs() { if (!$this->request) { return array(); } $header = $this->request->getHeader(self::PULL_HEADER); if (!empty($header)) { return explode(',', $header); } $param = $this->request->requestVar(self::PULL_PARAM); if (!empty($param)) { return explode(',', $param); } return array(); }
/** * Determins if the given request is from a bot * * Google ranks sites with the same content on different URLs lower. * This makes the site deliver single pages to bots * * @link http://www.beautifulcoding.com/snippets/178/a-simple-php-bot-checker-are-you-human/ * @return boolean */ public static function isRequsetBot(\SS_HTTPRequest $request) { $bots = Config::inst()->get('AllInOnePage', 'Bots'); $result = $request->getVar("mockBot") == "true"; if (!$result) { foreach ($bots as $spider) { //If the spider text is found in the current user agent, then return true if (stripos($request->getHeader("User-Agent"), $spider) !== false) { $result = true; } } } // echo '<pre class="debug"> "$result"' . PHP_EOL . print_r($result ? "yes" : "no", true) . PHP_EOL . '</pre>'; return $result || $request->getVar("mockBot") == "true"; }
/** * @param \SS_HTTPRequest $request * @return \Heystack\Ecommerce\Locale\Interfaces\CountryInterface|null */ public function getCountryForRequest(\SS_HTTPRequest $request) { $location = false; if ($this->isAllowedUserAgent($request->getHeader('User-Agent'))) { $ip = static::parseIP($request->getIP()); if (!$ip) { return null; } $fp = fopen(sprintf('https://geoip.maxmind.com/a?l=%s&i=%s', $this->key, $ip), 'r', null, stream_context_create(['https' => ['timeout' => $this->timeout]])); if (is_resource($fp)) { $location = stream_get_contents($fp); fclose($fp); } } return $location ? $this->localeService->getCountry(new Identifier($location)) : null; }
/** * Verify whether the given user/request has a valid HMAC header * * HMAC should be calculated as a concatenation of * * service name * method called * gmdate in format YmdH * * So an example before hashing would be * * product-getPrice-20130225 * * The key used for signing should come from the user's "AuthPrivateKey" field * * The validator will accept an hour either side of 'now' * * @param type $user * @param SS_HTTPRequest $request * @return boolean */ public function validateHmac($user, SS_HTTPRequest $request) { $service = $request->param('Service'); $method = $request->param('Method'); $hmac = $request->getHeader('X-Silverstripe-Hmac'); $key = $user->AuthPrivateKey; if (!strlen($key)) { return false; } $times = array(gmdate('YmdH', strtotime('-1 hour')), gmdate('YmdH'), gmdate('YmdH', strtotime('+1 hour'))); foreach ($times as $time) { $message = $this->generateHmac(array($service, $method, $time), $key); if ($message == $hmac) { return true; } } return false; }
/** * Redirect back. Uses either the HTTP_REFERER or a manually set request-variable called * _REDIRECT_BACK_URL. * This variable is needed in scenarios where not HTTP-Referer is sent ( * e.g when calling a page by location.href in IE). * If none of the two variables is available, it will redirect to the base * URL (see {@link Director::baseURL()}). * @uses redirect() */ function redirectBack() { if ($this->request->requestVar('_REDIRECT_BACK_URL')) { $url = $this->request->requestVar('_REDIRECT_BACK_URL'); } else { if ($this->request->getHeader('Referer')) { $url = $this->request->getHeader('Referer'); } else { $url = Director::baseURL(); } } // absolute redirection URLs not located on this site may cause phishing if (Director::is_site_url($url)) { return $this->redirect($url); } else { return false; } }
/** * Out of the box, the handler "CurrentForm" value, which will return the rendered form. * Non-Ajax calls will redirect back. * * @param SS_HTTPRequest $request * @param array $extraCallbacks List of anonymous functions or callables returning either a string * or SS_HTTPResponse, keyed by their fragment identifier. The 'default' key can * be used as a fallback for non-ajax responses. * @return SS_HTTPResponse */ public function respond(SS_HTTPRequest $request, $extraCallbacks = array()) { // Prepare the default options and combine with the others $callbacks = array_merge( array_change_key_case($this->callbacks, CASE_LOWER), array_change_key_case($extraCallbacks, CASE_LOWER) ); if($fragment = $request->getHeader('X-Pjax')) { $fragment = strtolower($fragment); if(isset($callbacks[$fragment])) { return call_user_func($callbacks[$fragment]); } else { throw new SS_HTTPResponse_Exception("X-Pjax = '$fragment' not supported for this URL.", 400); } } else { if($request->isAjax()) throw new SS_HTTPResponse_Exception("Ajax requests to this URL require an X-Pjax header.", 400); return call_user_func($callbacks['default']); } }
/** * Handle incoming webhook * * @link https://developers.sparkpost.com/api/#/reference/webhooks/create-a-webhook * @link https://www.sparkpost.com/blog/webhooks-beyond-the-basics/ * @link https://support.sparkpost.com/customer/portal/articles/1976204-webhook-event-reference * @param SS_HTTPRequest $req */ public function incoming(SS_HTTPRequest $req) { // Each webhook batch contains the header X-MessageSystems-Batch-ID, // which is useful for auditing and prevention of processing duplicate batches. $batchId = $req->getHeader('X-MessageSystems-Batch-ID'); $json = file_get_contents('php://input'); // By default, return a valid response $response = $this->getResponse(); $response->setStatusCode(200); $response->setBody('NO DATA'); if (!$json) { return $response; } $payload = json_decode($json, JSON_OBJECT_AS_ARRAY); try { $this->processPayload($payload, $batchId); } catch (Exception $ex) { // Maybe processing payload will create exceptions, but we // catch them to send a proper response to the API } $response->setBody('OK'); return $response; }
public function preRequest(SS_HTTPRequest $request, Session $session, DataModel $model) { $headerName = Config::inst()->get('ApiKeyRequestFilter', 'header_name'); if ($key = $request->getHeader($headerName)) { try { $matchingKey = MemberApiKey::findByKey($key); } catch (LogicException $e) { } if ($matchingKey) { // Log-in can't have session injected, we need to to push $session into the global state $controller = new Controller(); $controller->setSession($session); $controller->pushCurrent(); $matchingKey->Member()->logIn(); // Undo our global state manipulation $controller->popCurrent(); $matchingKey->markUsed(); } else { throw new SS_HTTPResponse_Exception("Bad X-API-Key", 400); } } return true; }
/** * Returns the token from the request. * * Silverstripe doesn't include Authorization header in its requests. We should check it, because we can use the * mechanism in the tests. * @param \SS_HTTPRequest $request * @return String the token * @throws \Exception */ public static function get_token($request) { // try to get the token from request object $tokenStrFromHeader = $request->getHeader('Authorization'); $tokenStrFromVar = $request->requestVar('access_token'); if (!empty($tokenStrFromHeader)) { // string must have format: type token return explode(' ', $tokenStrFromHeader)[1]; } else { if (!empty($tokenStrFromVar)) { // try variables return $tokenStrFromVar; } else { if (function_exists('getallheaders')) { // get all headers from apache server $headers = getallheaders(); if (isset($headers['Authorization'])) { return explode(' ', $headers['Authorization'])[1]; } } } } throw new \Exception("Token can't be read or was not specified"); }
/** * This is the action that gets executed when a GridField_AlterAction gets clicked. * * @param array $data * @return string */ public function gridFieldAlterAction($data, $form, SS_HTTPRequest $request) { $html = ''; $data = $request->requestVars(); $fieldData = @$data[$this->getName()]; // Update state from client $state = $this->getState(false); if(isset($fieldData['GridState'])) $state->setValue($fieldData['GridState']); // Try to execute alter action foreach($data as $k => $v) { if(preg_match('/^action_gridFieldAlterAction\?StateID=(.*)/', $k, $matches)) { $id = $matches[1]; $stateChange = Session::get($id); $actionName = $stateChange['actionName']; $args = isset($stateChange['args']) ? $stateChange['args'] : array(); $html = $this->handleAction($actionName, $args, $data); // A field can optionally return its own HTML if($html) return $html; } } switch($request->getHeader('X-Pjax')) { case 'CurrentField': return $this->FieldHolder(); break; case 'CurrentForm': return $form->forTemplate(); break; default: return $form->forTemplate(); break; } }
/** * @param array $data * @param Form $form * @param SS_HTTPRequest $request * @return HTML|HTMLText|mixed */ public function gridFieldAlterAction($data, $form, SS_HTTPRequest $request) { $data = $request->requestVars(); $stateHash = $this->getStateHash(); // Check if we have encountered a reset action. We need to clear the state here before // the other components start accessing it. foreach ($data as $dataKey => $dataValue) { if (preg_match('/^action_gridFieldAlterAction\\?StateID=(.*)/', $dataKey, $matches)) { $stateChange = Session::get($matches[1]); $actionName = $stateChange['actionName']; if ($actionName === 'ResetState') { Session::set($stateHash, null); $this->state = new GridState($this); } } } foreach ($data as $dataKey => $dataValue) { if (preg_match('/^action_gridFieldAlterAction\\?StateID=(.*)/', $dataKey, $matches)) { $stateChange = Session::get($matches[1]); $actionName = $stateChange['actionName']; $arguments = array(); if (isset($stateChange['args'])) { $arguments = $stateChange['args']; } $html = $this->handleAlterAction($actionName, $arguments, $data); if ($html) { return $html; } } } // The state is stored in the session so that we can access it on the next page load $this->setStateHash($this->state->Value()); if ($request->getHeader('X-Pjax') === 'CurrentField') { return $this->FieldHolder(); } return $form->forTemplate(); }
/** * REST endpoint to get a campaign. * * @param SS_HTTPRequest $request * * @return SS_HTTPResponse */ public function readCampaign(SS_HTTPRequest $request) { $response = new SS_HTTPResponse(); if ($request->getHeader('Accept') == 'text/json') { $response->addHeader('Content-Type', 'application/json'); if (!$request->param('Name')) { return new SS_HTTPResponse(null, 400); } /** @var ChangeSet $changeSet */ $changeSet = ChangeSet::get()->byID($request->param('ID')); if (!$changeSet) { return new SS_HTTPResponse(null, 404); } if (!$changeSet->canView()) { return new SS_HTTPResponse(null, 403); } $body = Convert::raw2json($this->getChangeSetResource($changeSet)); return (new SS_HTTPResponse($body, 200))->addHeader('Content-Type', 'application/json'); } else { return $this->index($request); } }
/** * Checks if a request to the API is authenticated * Gets API Token from HTTP Request and return Auth result * * @param SS_HTTPRequest $request HTTP API request * @return true|RESTfulAPI_Error True if token is valid OR RESTfulAPI_Error with details */ public function authenticate(SS_HTTPRequest $request) { //get the token $token = $request->getHeader($this->tokenConfig['header']); if (!$token) { $token = $request->requestVar($this->tokenConfig['queryVar']); } if ($token) { //check token validity return $this->validateAPIToken($token); } else { //no token, bad news return new RESTfulAPI_Error(403, 'Token invalid.', array('message' => 'Token invalid.', 'code' => self::AUTH_CODE_TOKEN_INVALID)); } }
/** * Action - Get the latest deploy log * * @return string */ public function transferlog(SS_HTTPRequest $request) { $params = $request->params(); $transfer = DNDataTransfer::get()->byId($params['Identifier']); if (!$transfer || !$transfer->ID) { throw new SS_HTTPResponse_Exception('Transfer not found', 404); } if (!$transfer->canView()) { return Security::permissionFailure(); } $environment = $transfer->Environment(); $project = $environment->Project(); if ($project->Name != $params['Project']) { throw new LogicException("Project in URL doesn't match this deploy"); } $log = $transfer->log(); if ($log->exists()) { $content = $log->content(); } else { $content = 'Waiting for action to start'; } $sendJSON = strpos($request->getHeader('Accept'), 'application/json') !== false || $request->getExtension() == 'json'; $content = preg_replace('/(?:(?:\\r\\n|\\r|\\n)\\s*){2}/s', "\n", $content); if ($sendJSON) { $this->response->addHeader("Content-type", "application/json"); return json_encode(array('status' => $transfer->ResqueStatus(), 'content' => $content)); } else { $this->response->addHeader("Content-type", "text/plain"); return $content; } }
/** * This is the action that gets executed when a GridField_AlterAction gets clicked. * * @param array $data * @param Form $form * @param SS_HTTPRequest $request * * @return string */ public function gridFieldAlterAction($data, $form, SS_HTTPRequest $request) { $data = $request->requestVars(); $name = $this->getName(); $fieldData = null; if (isset($data[$name])) { $fieldData = $data[$name]; } $state = $this->getState(false); if (isset($fieldData['GridState'])) { $state->setValue($fieldData['GridState']); } foreach ($data as $dataKey => $dataValue) { if (preg_match('/^action_gridFieldAlterAction\\?StateID=(.*)/', $dataKey, $matches)) { $stateChange = Session::get($matches[1]); $actionName = $stateChange['actionName']; $arguments = array(); if (isset($stateChange['args'])) { $arguments = $stateChange['args']; } $html = $this->handleAlterAction($actionName, $arguments, $data); if ($html) { return $html; } } } if ($request->getHeader('X-Pjax') === 'CurrentField') { return $this->FieldHolder(); } return $form->forTemplate(); }
/** * Get's the previous URL that lead up to the current request. * * NOTE: Honestly, this should be built into SS_HTTPRequest, but we can't depend on that right now... so instead, * this is being copied verbatim from Controller (in the framework). * * @param SS_HTTPRequest $request * @return string */ protected function getBackURL(SS_HTTPRequest $request) { // Initialize a sane default (basically redirects to root admin URL). $controller = $this->getToplevelController(); $url = method_exists($this->requestHandler, "Link") ? $this->requestHandler->Link() : $controller->Link(); // Try to parse out a back URL using standard framework technique. if ($request->requestVar('BackURL')) { $url = $request->requestVar('BackURL'); } else { if ($request->isAjax() && $request->getHeader('X-Backurl')) { $url = $request->getHeader('X-Backurl'); } else { if ($request->getHeader('Referer')) { $url = $request->getHeader('Referer'); } } } return $url; }
public function index(SS_HTTPRequest $request) { // only send meta tags if ($request->getHeader("Prefer-Html-Meta-Tags")) { return $this->buildOnlyMetaTagsResponse($this->MetaTags()); } Requirements::javascript("summit/javascript/schedule/schedule-page.js"); return $this->getViewer('index')->process($this); }