public function postRequest(\SS_HTTPRequest $request, \SS_HTTPResponse $response, \DataModel $model)
 {
     if (defined('PROXY_CACHE_GENERATING') || isset($GLOBALS['__cache_publish']) || strpos($request->getURL(), 'admin/') !== false) {
         return;
     }
     $this->database = Db::getConn();
     $queries = $this->database->queryRecord;
     $dupes = $this->database->getDuplicateQueries();
     $str = "\n<!-- Total queries: " . count($queries) . "-->\n";
     $str .= "\n<!-- Duplicate queries: " . count($dupes) . "-->\n";
     $b = $response->getBody();
     if (strpos($b, '</html>')) {
         if (count($queries) > $this->queryThreshold) {
             // add a floating div with info about the stuff
             $buildQueryList = function ($source, $class) {
                 $html = '';
                 foreach ($source as $sql => $info) {
                     $html .= "\n<p class='{$class}' style='display: none; border-top: 1px dashed #000;'>{$info->count} : {$info->query}</p>\n";
                     if ($info->source) {
                         $html .= "\n<p class='{$class}' style='color: #a00; display: none; '>Last called from {$info->source}</p>\n";
                     }
                 }
                 return $html;
             };
             $html = $buildQueryList($queries, 'debug-query');
             $html .= $buildQueryList($dupes, 'debug-dupe-query');
             $div = '<div id="query-stat-debugger" ' . 'style="position: fixed; bottom: 0; right: 0; border: 2px solid red; background: #fff; ' . 'font-size: 8px; font-family: sans-serif; width: 100px; z-index: 2000; padding: 1em;' . 'overflow: auto; max-height: 500px;">' . '<p id="debug-all-queries-list">Total of ' . count($queries) . ' queries</p>' . '<p id="debug-dupe-queries-list">Total of ' . count($dupes) . ' duplicates</p>' . $html . '<script>' . 'jQuery("#debug-all-queries-list").click(function () {' . 'var elems = jQuery(this).parent().find(".debug-query");' . 'jQuery(this).parent().css("width", "40%");' . 'elems.toggle();' . '}); ' . 'jQuery("#debug-dupe-queries-list").click(function () {' . 'var elems = jQuery(this).parent().find(".debug-dupe-query");' . 'jQuery(this).parent().css("width", "40%");' . 'elems.toggle();' . '}); ' . '' . '' . '</script>' . '</div>';
             $b = str_replace('</body>', "{$div}</body>", $b);
         }
         $b = str_replace('</html>', "{$str}</html>", $b);
         $response->setBody($b);
     }
 }
 public function postRequest(\SS_HTTPRequest $request, \SS_HTTPResponse $response, \DataModel $model)
 {
     if ($this->convertUrls && $response && $response->getStatusCode() == 200) {
         // only convert if we have an HTML content type response
         $body = $response->getBody();
         // find urls inserted in content
         if (strpos($body, 'cdnfileid') > 0 && preg_match_all('/data-cdnfileid="(\\d+)"/', $body, $matches)) {
             $files = CdnImage::get()->filter('ID', $matches[1]);
             $fileIds = array();
             foreach ($files as $file) {
                 $url = $file->getUrl();
                 $filename = $file->Filename;
                 $body = str_replace("src=\"{$filename}\"", "src=\"{$url}\"", $body);
                 $fileIds[] = $file->ID;
             }
             $assets = ContentServiceAsset::get()->filter('SourceID', $matches[1]);
             foreach ($assets as $asset) {
                 $url = $asset->getUrl();
                 $filename = $asset->Filename;
                 // note the extra forward slash here, image_cached inserts it
                 $body = str_replace("src=\"/{$filename}\"", "src=\"{$url}\"", $body);
             }
             $response->setBody($body);
         }
     }
 }
 protected function ok(array $res = null, $use_etag = true)
 {
     $response = new SS_HTTPResponse();
     $response->setStatusCode(200);
     $response->addHeader('Content-Type', 'application/json');
     if (is_null($res)) {
         $res = array();
     }
     $response->setBody(json_encode($res));
     //conditional get Request (etags)
     $request = Controller::curr()->getRequest();
     if ($request->isGET() && $use_etag) {
         $etag = md5($response->getBody());
         $requestETag = $request->getHeader('If-None-Match');
         foreach (array('Expires', 'Cache-Control') as $header) {
             $response->removeHeader($header);
         }
         $lastmod = gmdate('D, d M Y 0:0:0 \\G\\M\\T', time());
         $response->addHeader('Cache-Control', 'max-age=3600');
         $response->addHeader('Last-Modified', $lastmod);
         $response->addHeader('Expires', gmdate('D, d M Y H:m:i \\G\\M\\T', time() + 3600));
         $response->addHeader('ETag', $etag);
         if (!empty($requestETag) && $requestETag == $etag) {
             $response->setStatusCode(304);
             $response->addHeader('ETag', $etag);
             $response->setBody(null);
         }
     }
     return $response;
 }
 /**
  * Filter executed AFTER a request
  *
  * @param SS_HTTPRequest $request Request container object
  * @param SS_HTTPResponse $response Response output object
  * @param DataModel $model Current DataModel
  * @return boolean Whether to continue processing other filters. Null or true will continue processing (optional)
  */
 public function postRequest(SS_HTTPRequest $request, SS_HTTPResponse $response, DataModel $model)
 {
     if (!self::isEnabled()) {
         return true;
     }
     $body = $response->getBody();
     $response->setBody(self::replaceCDN($body));
     return true;
 }
 public function postRequest(\SS_HTTPRequest $request, \SS_HTTPResponse $response, \DataModel $model)
 {
     $time = sprintf('%.3f ms', microtime(true) - $this->start);
     $response->addHeader('X-SilverStripe-Time', $time);
     $b = $response->getBody();
     if (strpos($b, '</html>')) {
         $b = str_replace('</html>', "\n<!-- Generated in {$time} -->\n</html>", $b);
         $response->setBody($b);
     }
 }
 /**
  * Adds Intercom script tags just before the body
  */
 public function postRequest(SS_HTTPRequest $request, SS_HTTPResponse $response, DataModel $model)
 {
     $mime = $response->getHeader('Content-Type');
     if (!$mime || strpos($mime, 'text/html') !== false) {
         $intercomScriptTags = (new intercomScriptTags())->forTemplate();
         if ($intercomScriptTags) {
             $content = $response->getBody();
             $content = preg_replace("/(<\\/body[^>]*>)/i", $intercomScriptTags . "\\1", $content);
             $response->setBody($content);
         }
     }
 }
 /**
  * Filter executed AFTER a request
  *
  * @param SS_HTTPRequest $request   Request container object
  * @param SS_HTTPResponse $response Response output object
  * @param DataModel $model          Current DataModel
  * @return boolean Whether to continue processing other filters. Null or true will continue processing (optional)
  */
 public function postRequest(SS_HTTPRequest $request, SS_HTTPResponse $response, DataModel $model)
 {
     $debugbar = DebugBar::getDebugBar();
     if (!$debugbar) {
         return;
     }
     // All queries have been displayed
     if (DebugBar::getShowQueries()) {
         exit;
     }
     $script = DebugBar::renderDebugBar();
     // If the bar is not renderable, return early
     if (!$script) {
         return;
     }
     // Inject init script into the HTML response
     $body = $response->getBody();
     if (strpos($body, '</body>') !== false) {
         $body = str_replace('</body>', $script . '</body>', $body);
         $response->setBody($body);
     }
     // Ajax support
     if (Director::is_ajax() && !headers_sent()) {
         if (DebugBar::IsAdminUrl() && !DebugBar::config()->enabled_in_admin) {
             return;
         }
         // Skip anything that is not a GET request
         if (!$request->isGET()) {
             return;
         }
         // Always enable in admin because everything is mostly loaded through ajax
         if (DebugBar::config()->ajax || DebugBar::IsAdminUrl()) {
             $headers = $debugbar->getDataAsHeaders();
             // Prevent throwing js errors in case header size is too large
             if (is_array($headers)) {
                 $debugbar->sendDataInHeaders();
             }
         }
     }
 }
Пример #8
0
 /**
  * @return string
  */
 public function getContent()
 {
     return $this->response->getBody();
 }
 /**
  * Assert that a response matches the given parameters
  *
  * @param int $code HTTP code
  * @param string $body Body expected for 200 responses
  * @param SS_HTTPResponse $response
  */
 protected function assertResponseEquals($code, $body, SS_HTTPResponse $response)
 {
     $this->assertEquals($code, $response->getStatusCode());
     if ($code === 200) {
         $this->assertFalse($response->isError());
         $this->assertEquals($body, $response->getBody());
         $this->assertEquals('text/plain', $response->getHeader('Content-Type'));
     } else {
         $this->assertTrue($response->isError());
     }
 }
Пример #10
0
 public function html(SS_HTTPResponse $response)
 {
     $encoding = Config::inst()->get('ContentNegotiator', 'encoding');
     $contentType = Config::inst()->get('ContentNegotiator', '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);
 }
 public function postRequest(SS_HTTPRequest $request, SS_HTTPResponse $response, DataModel $model)
 {
     if (preg_match('/text\\/html/', $response->getHeader('Content-Type'))) {
         $response->setBody($this->SuppressWhitespace($response->getBody()));
     }
 }
 public function applyToResponse($originator, SS_HTTPRequest $request, SS_HTTPResponse $response, DataModel $model)
 {
     $responseHeaders = array();
     $cacheAge = $this->cacheAge;
     $vary = $this->vary;
     // Allow overriding max-age from the object hooked up to the policed controller.
     if ($originator->hasMethod('getCacheAge')) {
         $extendedCacheAge = $originator->getCacheAge($cacheAge);
         if ($extendedCacheAge !== null) {
             $cacheAge = $extendedCacheAge;
         }
     }
     // Same for vary, but probably less useful.
     if ($originator->hasMethod('getVary')) {
         $extendedVary = $originator->getVary($vary);
         if ($extendedVary !== null) {
             $vary = $extendedVary;
         }
     }
     $etag = null;
     if ($cacheAge > 0) {
         // Note: must-revalidate means that the cache must revalidate AFTER the entry has gone stale.
         $responseHeaders["Cache-Control"] = "max-age=" . $cacheAge . ", must-revalidate, no-transform";
         $responseHeaders["Pragma"] = "";
         $responseHeaders['Vary'] = $vary;
         // Find out when the URI was last modified. Allows customisation, but fall back HTTP timestamp collector.
         if ($originator->hasMethod('getModificationTimestamp')) {
             $timestamp = $originator->getModificationTimestamp();
         } else {
             $timestamp = HTTP::$modification_date;
         }
         if ($timestamp) {
             $responseHeaders["Last-Modified"] = self::gmt_date($timestamp);
             $expires = time() + $cacheAge;
             $responseHeaders["Expires"] = self::gmt_date($expires);
         }
         // first etag calculation based on timestamp and cookies ....
         // Chrome ignores Varies when redirecting back (http://code.google.com/p/chromium/issues/detail?id=79758)
         // which means that if you log out, you get redirected back to a page which Chrome then checks against
         // last-modified (which passes, getting a 304)
         // when it shouldn't be trying to use that page at all because it's the "logged in" version.
         // By also using and etag that includes both the modification date and all the varies
         // values which we also check against we can catch this and not return a 304
         $etagParts = array($timestamp, serialize($_COOKIE));
         $etagParts[] = Director::is_https() ? 'https' : 'http';
         if (isset($_SERVER['HTTP_USER_AGENT'])) {
             $etagParts[] = $_SERVER['HTTP_USER_AGENT'];
         }
         if (isset($_SERVER['HTTP_ACCEPT'])) {
             $etagParts[] = $_SERVER['HTTP_ACCEPT'];
         }
         $etag = sha1(implode(':', $etagParts));
         $responseHeaders["ETag"] = $etag;
     }
     // custom calculation os ETag
     if ($originator->hasMethod('getEtag')) {
         $extendedEtag = $originator->getEtag($response->getBody());
         if ($extendedEtag !== null) {
             $etag = $extendedEtag;
             $responseHeaders["ETag"] = $etag;
         }
     }
     // Now that we've generated them, either output them or attach them to the SS_HTTPResponse as appropriate
     foreach ($responseHeaders as $k => $v) {
         $response->addHeader($k, $v);
     }
     // 304 response detection
     /**
      * The HTTP IF_MODIFIED_SINCE request-header, is a header which is sent by most browsers.
      * It contains the modification date provided in the Last-Modified header by the server on the last visit.
      */
     if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
         $ifModifiedSince = strtotime(stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']));
         // As above, only 304 if the last request had all the same varies values
         // (or the etag isn't passed as part of the request - but with chrome it always is)
         $matchesEtag = !isset($_SERVER['HTTP_IF_NONE_MATCH']) || $_SERVER['HTTP_IF_NONE_MATCH'] == $etag;
         if ($ifModifiedSince >= $timestamp && $matchesEtag) {
             ob_clean();
             $response->setStatusCode(304);
             $response->setBody('');
         }
     } else {
         if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag) {
             ob_clean();
             $response->setStatusCode(304);
             $response->setBody('');
         }
     }
 }
Пример #13
0
 /**
  * @param SS_HTTPResponse $r
  * @return SS_HTTPResponse|void
  * @throws SS_HTTPResponse_Exception
  * @throws ValidationException
  * @throws null
  */
 public function handleResolveCategoryChange(SS_HTTPResponse $r)
 {
     if (!Permission::check('ADMIN')) {
         return $this->httpError(403);
     }
     if (!is_numeric($r->param('ID'))) {
         return $this->httpError(500, "Invalid category change id");
     }
     $vars = Convert::json2array($r->getBody());
     if (!isset($vars['approved'])) {
         return $this->httpError(500, "Request body must contain 'approved' 1 or 0");
     }
     $approved = (bool) $vars['approved'];
     $request = SummitCategoryChange::get()->byID($r->param('ID'));
     if (!$request) {
         return $this->httpError(500, "Request " . $r->param('ID') . " does not exist");
     }
     $status = $approved ? SummitCategoryChange::STATUS_APPROVED : SummitCategoryChange::STATUS_REJECTED;
     if ($request->Presentation()->isSelectedByAnyone()) {
         return new SS_HTTPResponse("The presentation has already been selected by chairs.", 500);
     }
     if ($request->Presentation()->CategoryID == $request->NewCategoryID) {
         return new SS_HTTPResponse("The presentation is already in this category.", 200);
     }
     // Make the category change
     $summit = Summit::get_active();
     $category = $summit->Categories()->filter('ID', $request->NewCategoryID)->first();
     if (!$category->exists()) {
         return $this->httpError(500, "Category not found in current summit");
     }
     $oldCat = $request->Presentation()->Category();
     if ($approved) {
         $request->OldCategoryID = $request->Presentation()->CategoryID;
         $request->Presentation()->CategoryID = $request->NewCategoryID;
         $request->Presentation()->write();
         $request->Presentation()->addNotification('{member} approved ' . $request->Reqester()->getName() . '\'s request to move this presentation from ' . $oldCat->Title . ' to ' . $category->Title);
     } else {
         $request->Presentation()->addNotification('{member} rejected ' . $request->Reqester()->getName() . '\'s request to move this presentation from ' . $oldCat->Title . ' to ' . $category->Title);
     }
     $request->AdminApproverID = Member::currentUserID();
     $request->Status = $status;
     $request->ApprovalDate = SS_Datetime::now();
     $request->write();
     $peers = SummitCategoryChange::get()->filter(['PresentationID' => $request->PresentationID, 'NewCategoryID' => $request->NewCategoryID])->exclude(['ID' => $request->ID]);
     foreach ($peers as $p) {
         $p->AdminApproverID = Member::currentUserID();
         $p->Status = SummitCategoryChange::STATUS_APPROVED;
         $p->ApprovalDate = SS_Datetime::now();
         $p->write();
     }
     return $this->ok('change request accepted.');
 }
Пример #14
0
 /**
  * Return an array of errors and their messages from a PayPal response
  *
  * @param SS_HTTPResponse $response
  * @return array
  */
 public function getErrors($response)
 {
     $errorList = array();
     $responseString = $response->getBody();
     $responseArr = $this->parseResponse($response);
     preg_match_all('/L_ERRORCODE\\d+/', $responseString, $errorFields);
     preg_match_all('/L_LONGMESSAGE\\d+/', $responseString, $messageFields);
     if (count($errorFields[0]) != count($messageFields[0])) {
         throw new Exception("PayPal resonse invalid: errors and messages don't match");
     } else {
         for ($i = 0; $i < count($errorFields[0]); $i++) {
             $errorField = $errorFields[0][$i];
             $errorCode = $responseArr[$errorField];
             $messageField = $messageFields[0][$i];
             $errorMessage = $responseArr[$messageField];
             $errorList[$errorCode] = $errorMessage;
         }
     }
     return $errorList;
 }
 public function setResponse(SS_HTTPResponse $response)
 {
     $body = json_encode(array('data' => array('status_code' => $response->getStatusCode(), 'message' => $response->getBody())));
     $this->response = new JsonDataResponse($body, $response->getStatusCode(), $response->getStatusDescription());
 }
 /**
  * @return string
  */
 public function getBody()
 {
     // if the body has been set elsewhere, just pass that through.
     if (empty($this->body)) {
         $data = new StdClass();
         if (!empty($this->events)) {
             $key = self::EVENTS_KEY;
             $data->{$key} = $this->events;
         }
         // add the pull regions, if any
         $pulls = $this->getPulledRegionIDs();
         if (count($pulls) > 0) {
             foreach ($pulls as $regionID) {
                 $this->pushRegion($regionID);
             }
         }
         if (!empty($this->regions)) {
             $key = self::REGIONS_KEY;
             $data->{$key} = $this->regions;
         }
         $this->setBody(json_encode($data));
     }
     return parent::getBody();
 }
Пример #17
0
 protected function ok(array $res = null)
 {
     $response = new SS_HTTPResponse();
     $response->setStatusCode(200);
     $response->addHeader('Content-Type', 'application/json');
     if (is_null($res)) {
         $res = array();
     }
     $response->setBody(json_encode($res));
     //conditional get Request (etags)
     $request = Controller::curr()->getRequest();
     if ($request->isGET()) {
         $etag = md5($response->getBody());
         $requestETag = $request->getHeader('If-None-Match');
         if (!empty($requestETag) && $requestETag == $etag) {
             $response->setStatusCode(304);
             foreach (array('Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified') as $header) {
                 $response->removeHeader($header);
             }
             $response->setBody(null);
         } else {
             $response->addHeader('ETag', $etag);
         }
     }
     return $response;
 }
 public function respondWithError($args)
 {
     // Make args' keys lowercase
     $args = array_combine(array_map('strtolower', array_keys($args)), array_values($args));
     // See if an exception is passed (no default)
     $exception = null;
     if (isset($args['exception'])) {
         $exception = $args['exception'];
     }
     // Get the default exception noun if set
     $exceptionNoun = self::$exception_noun;
     // Add defaults
     $args = array_merge(array('code' => 500, 'description' => null, 'body' => null, 'noun' => $exception && $exceptionNoun ? new $exceptionNoun($exception) : null), $args);
     // Default "response" which we build into. Not returned, because the exception has it's own response
     $response = new SS_HTTPResponse();
     // If there's a formatter
     if ($args['noun'] && ($formatter = RESTFormatter::get_formatter($this->request))) {
         // Format the response. Revert back to default response if we got nothing.
         $response = $formatter->format($args['noun'], array('*'));
         if (!$response) {
             $response = new SS_HTTPResponse();
         }
     } else {
         if ($exception) {
             $exception = $args['exception'];
             $response->setBody($exception->getMessage() . "\n");
             $response->addHeader('Content-Type', 'text/plain');
         }
     }
     // If a specific body was provided, use that
     if ($args['body']) {
         $response->setBody($args['body']);
     }
     // Build an exception with those details
     $e = new SS_HTTPResponse_Exception($response->getBody(), $args['code'], $args['description']);
     $exceptionResponse = $e->getResponse();
     // Add user specified headers
     foreach ($response->getHeaders() as $k => $v) {
         $exceptionResponse->addHeader($k, $v);
     }
     throw $e;
 }