/**
  * Render or return a backtrace from the given scope.
  *
  * @param mixed $returnVal
  * @param bool $ignoreAjax
  * @param array $ignoredFunctions
  * @return mixed
  */
 public static function backtrace($returnVal = false, $ignoreAjax = false, $ignoredFunctions = null)
 {
     $plainText = Director::is_cli() || Director::is_ajax() && !$ignoreAjax;
     $result = self::get_rendered_backtrace(debug_backtrace(), $plainText, $ignoredFunctions);
     if ($returnVal) {
         return $result;
     } else {
         echo $result;
         return null;
     }
 }
 /**
  * Create an instance of an appropriate DebugView object.
  *
  * @return DebugView
  */
 public static function create_debug_view()
 {
     $service = Director::is_cli() || Director::is_ajax() ? 'SilverStripe\\Dev\\CliDebugView' : 'SilverStripe\\Dev\\DebugView';
     return Injector::inst()->get($service);
 }
 /**
  * Register that we've had a permission failure trying to view the given page
  *
  * This will redirect to a login page.
  * If you don't provide a messageSet, a default will be used.
  *
  * @param Controller $controller The controller that you were on to cause the permission
  *                               failure.
  * @param string|array $messageSet The message to show to the user. This
  *                                 can be a string, or a map of different
  *                                 messages for different contexts.
  *                                 If you pass an array, you can use the
  *                                 following keys:
  *                                   - default: The default message
  *                                   - alreadyLoggedIn: The message to
  *                                                      show if the user
  *                                                      is already logged
  *                                                      in and lacks the
  *                                                      permission to
  *                                                      access the item.
  *
  * The alreadyLoggedIn value can contain a '%s' placeholder that will be replaced with a link
  * to log in.
  * @return HTTPResponse
  */
 public static function permissionFailure($controller = null, $messageSet = null)
 {
     self::set_ignore_disallowed_actions(true);
     if (!$controller) {
         $controller = Controller::curr();
     }
     if (Director::is_ajax()) {
         $response = $controller ? $controller->getResponse() : new HTTPResponse();
         $response->setStatusCode(403);
         if (!Member::currentUser()) {
             $response->setBody(_t('ContentController.NOTLOGGEDIN', 'Not logged in'));
             $response->setStatusDescription(_t('ContentController.NOTLOGGEDIN', 'Not logged in'));
             // Tell the CMS to allow re-aunthentication
             if (CMSSecurity::enabled()) {
                 $response->addHeader('X-Reauthenticate', '1');
             }
         }
         return $response;
     }
     // Prepare the messageSet provided
     if (!$messageSet) {
         if ($configMessageSet = static::config()->get('default_message_set')) {
             $messageSet = $configMessageSet;
         } else {
             $messageSet = array('default' => _t('Security.NOTEPAGESECURED', "That page is secured. Enter your credentials below and we will send " . "you right along."), 'alreadyLoggedIn' => _t('Security.ALREADYLOGGEDIN', "You don't have access to this page.  If you have another account that " . "can access that page, you can log in again below.", "%s will be replaced with a link to log in."));
         }
     }
     if (!is_array($messageSet)) {
         $messageSet = array('default' => $messageSet);
     }
     $member = Member::currentUser();
     // Work out the right message to show
     if ($member && $member->exists()) {
         $response = $controller ? $controller->getResponse() : new HTTPResponse();
         $response->setStatusCode(403);
         //If 'alreadyLoggedIn' is not specified in the array, then use the default
         //which should have been specified in the lines above
         if (isset($messageSet['alreadyLoggedIn'])) {
             $message = $messageSet['alreadyLoggedIn'];
         } else {
             $message = $messageSet['default'];
         }
         // Somewhat hackish way to render a login form with an error message.
         $me = new Security();
         $form = $me->LoginForm();
         $form->sessionMessage($message, 'warning');
         Session::set('MemberLoginForm.force_message', 1);
         $loginResponse = $me->login();
         if ($loginResponse instanceof HTTPResponse) {
             return $loginResponse;
         }
         $response->setBody((string) $loginResponse);
         $controller->extend('permissionDenied', $member);
         return $response;
     } else {
         $message = $messageSet['default'];
     }
     Session::set("Security.Message.message", $message);
     Session::set("Security.Message.type", 'warning');
     Session::set("BackURL", $_SERVER['REQUEST_URI']);
     // TODO AccessLogEntry needs an extension to handle permission denied errors
     // Audit logging hook
     $controller->extend('permissionDenied', $member);
     return $controller->redirect(Config::inst()->get('SilverStripe\\Security\\Security', 'login_url') . "?BackURL=" . urlencode($_SERVER['REQUEST_URI']));
 }
 /**
  * Return the appropriate error content for the given status code
  *
  * @param int $statusCode
  * @return string Content in an appropriate format for the current request
  */
 public function output($statusCode)
 {
     // TODO: Refactor into a content-type option
     if (Director::is_ajax()) {
         return $this->getTitle();
     }
     $renderer = Debug::create_debug_view();
     $output = $renderer->renderHeader();
     $output .= $renderer->renderInfo("Website Error", $this->getTitle(), $this->getBody());
     if (Email::config()->admin_email) {
         $mailto = Email::obfuscate(Email::config()->admin_email);
         $output .= $renderer->renderParagraph('Contact an administrator: ' . $mailto . '');
     }
     $output .= $renderer->renderFooter();
     return $output;
 }
 public function testCoreGlobalVariableCalls()
 {
     $this->assertEquals(Director::absoluteBaseURL(), $this->render('{$absoluteBaseURL}'), 'Director::absoluteBaseURL can be called from within template');
     $this->assertEquals(Director::absoluteBaseURL(), $this->render('{$AbsoluteBaseURL}'), 'Upper-case %AbsoluteBaseURL can be called from within template');
     $this->assertEquals(Director::is_ajax(), $this->render('{$isAjax}'), 'All variations of is_ajax result in the correct call');
     $this->assertEquals(Director::is_ajax(), $this->render('{$IsAjax}'), 'All variations of is_ajax result in the correct call');
     $this->assertEquals(Director::is_ajax(), $this->render('{$is_ajax}'), 'All variations of is_ajax result in the correct call');
     $this->assertEquals(Director::is_ajax(), $this->render('{$Is_ajax}'), 'All variations of is_ajax result in the correct call');
     $this->assertEquals(i18n::get_locale(), $this->render('{$i18nLocale}'), 'i18n template functions result correct result');
     $this->assertEquals(i18n::get_locale(), $this->render('{$get_locale}'), 'i18n template functions result correct result');
     $this->assertEquals((string) Member::currentUser(), $this->render('{$CurrentMember}'), 'Member template functions result correct result');
     $this->assertEquals((string) Member::currentUser(), $this->render('{$CurrentUser}'), 'Member template functions result correct result');
     $this->assertEquals((string) Member::currentUser(), $this->render('{$currentMember}'), 'Member template functions result correct result');
     $this->assertEquals((string) Member::currentUser(), $this->render('{$currentUser}'), 'Member template functions result correct result');
     $this->assertEquals(SecurityToken::getSecurityID(), $this->render('{$getSecurityID}'), 'SecurityToken template functions result correct result');
     $this->assertEquals(SecurityToken::getSecurityID(), $this->render('{$SecurityID}'), 'SecurityToken template functions result correct result');
     $this->assertEquals(Permission::check("ADMIN"), (bool) $this->render('{$HasPerm(\'ADMIN\')}'), 'Permissions template functions result correct result');
     $this->assertEquals(Permission::check("ADMIN"), (bool) $this->render('{$hasPerm(\'ADMIN\')}'), 'Permissions template functions result correct result');
 }
    /**
     * Send this HTTPReponse to the browser
     */
    public function output()
    {
        // Attach appropriate X-Include-JavaScript and X-Include-CSS headers
        if (Director::is_ajax()) {
            Requirements::include_in_response($this);
        }
        if (in_array($this->statusCode, self::$redirect_codes) && headers_sent($file, $line)) {
            $url = Director::absoluteURL($this->headers['Location'], true);
            $urlATT = Convert::raw2htmlatt($url);
            $urlJS = Convert::raw2js($url);
            $title = Director::isDev() ? "{$urlATT}... (output started on {$file}, line {$line})" : "{$urlATT}...";
            echo <<<EOT
<p>Redirecting to <a href="{$urlATT}" title="Click this link if your browser does not redirect you">{$title}</a></p>
<meta http-equiv="refresh" content="1; url={$urlATT}" />
<script type="application/javascript">setTimeout(function(){
\twindow.location.href = "{$urlJS}";
}, 50);</script>
EOT;
        } else {
            $line = $file = null;
            if (!headers_sent($file, $line)) {
                header($_SERVER['SERVER_PROTOCOL'] . " {$this->statusCode} " . $this->getStatusDescription());
                foreach ($this->headers as $header => $value) {
                    //etags need to be quoted
                    if (strcasecmp('etag', $header) === 0 && 0 !== strpos($value, '"')) {
                        $value = sprintf('"%s"', $value);
                    }
                    header("{$header}: {$value}", true, $this->statusCode);
                }
            } else {
                // It's critical that these status codes are sent; we need to report a failure if not.
                if ($this->statusCode >= 300) {
                    user_error("Couldn't set response type to {$this->statusCode} because " . "of output on line {$line} of {$file}", E_USER_WARNING);
                }
            }
            // Only show error pages or generic "friendly" errors if the status code signifies
            // an error, and the response doesn't have any body yet that might contain
            // a more specific error description.
            if (Director::isLive() && $this->isError() && !$this->body) {
                $formatter = Injector::inst()->get('FriendlyErrorFormatter');
                echo $formatter->format(array('code' => $this->statusCode));
            } else {
                echo $this->body;
            }
        }
    }
 /**
  * Performs the actual action of adding the object to the ChangeSet, once the ChangeSet ID is known
  *
  * @param DataObject $object The object to add to the ChangeSet
  * @param int $campaignID The ID of the ChangeSet to add $object to
  * @return HTTPResponse
  * @throws HTTPResponse_Exception
  */
 public function addToCampaign($object, $campaignID)
 {
     /** @var ChangeSet $changeSet */
     $changeSet = ChangeSet::get()->byID($campaignID);
     if (!$changeSet) {
         $this->controller->httpError(404, _t('AddToCampaign.ErrorNotFound', 'That {Type} couldn\'t be found', '', ['Type' => 'Campaign']));
         return null;
     }
     if (!$changeSet->canEdit()) {
         $this->controller->httpError(403, _t('AddToCampaign.ErrorCampaignPermissionDenied', 'It seems you don\'t have the necessary permissions to add {ObjectTitle} to {CampaignTitle}', '', ['ObjectTitle' => $object->Title, 'CampaignTitle' => $changeSet->Title]));
         return null;
     }
     $changeSet->addObject($object);
     $request = $this->controller->getRequest();
     $message = _t('AddToCampaign.Success', 'Successfully added {ObjectTitle} to {CampaignTitle}', '', ['ObjectTitle' => $object->Title, 'CampaignTitle' => $changeSet->Title]);
     if ($request->getHeader('X-Formschema-Request')) {
         return $message;
     } elseif (Director::is_ajax()) {
         $response = new HTTPResponse($message, 200);
         $response->addHeader('Content-Type', 'text/plain; charset=utf-8');
         return $response;
     } else {
         return $this->controller->getController()->redirectBack();
     }
 }