/**
     * Redirects the user to the external login page
     *
     * @return HTTPResponse
     */
    protected function redirectToExternalLogin()
    {
        $loginURL = Security::create()->Link('login');
        $loginURLATT = Convert::raw2att($loginURL);
        $loginURLJS = Convert::raw2js($loginURL);
        $message = _t('CMSSecurity.INVALIDUSER', '<p>Invalid user. <a target="_top" href="{link}">Please re-authenticate here</a> to continue.</p>', 'Message displayed to user if their session cannot be restored', array('link' => $loginURLATT));
        $response = $this->getResponse();
        $response->setStatusCode(200);
        $response->setBody(<<<PHP
<!DOCTYPE html>
<html><body>
{$message}
<script type="application/javascript">
setTimeout(function(){top.location.href = "{$loginURLJS}";}, 0);
</script>
</body></html>
PHP
);
        $this->setResponse($response);
        return $response;
    }
 /**
  * Gets javascript string literal value
  *
  * @return string
  */
 public function JS()
 {
     return Convert::raw2js($this->RAW());
 }
    public function schema($request)
    {
        // TODO Hardcoding schema until we can get GridField to generate a schema dynamically
        $treeClassJS = Convert::raw2js($this->config()->tree_class);
        $adminURL = Convert::raw2js(AdminRootController::admin_url());
        $json = <<<JSON
{
\t"id": "{$adminURL}campaigns\\/schema\\/EditForm",
\t"schema": {
\t\t"name": "EditForm",
\t\t"id": "Form_EditForm",
\t\t"action": "schema",
\t\t"method": "GET",
\t\t"attributes": {
\t\t\t"id": "Form_EditForm",
\t\t\t"action": "{$adminURL}campaigns\\/EditForm",
\t\t\t"method": "POST",
\t\t\t"enctype": "multipart\\/form-data",
\t\t\t"target": null
\t\t},
\t\t"data": [],
\t\t"fields": [{
\t\t\t"name": "ID",
\t\t\t"id": "Form_EditForm_ID",
\t\t\t"type": "Hidden",
\t\t\t"component": null,
\t\t\t"holderId": null,
\t\t\t"title": false,
\t\t\t"source": null,
\t\t\t"extraClass": "hidden form-group--no-label",
\t\t\t"description": null,
\t\t\t"rightTitle": null,
\t\t\t"leftTitle": null,
\t\t\t"readOnly": false,
\t\t\t"disabled": false,
\t\t\t"customValidationMessage": "",
\t\t\t"attributes": [],
\t\t\t"data": []
\t\t}, {
\t\t\t"name": "ChangeSets",
\t\t\t"id": "Form_EditForm_ChangeSets",
\t\t\t"type": "Custom",
\t\t\t"component": "GridField",
\t\t\t"holderId": null,
\t\t\t"title": "Campaigns",
\t\t\t"source": null,
\t\t\t"extraClass": null,
\t\t\t"description": null,
\t\t\t"rightTitle": null,
\t\t\t"leftTitle": null,
\t\t\t"readOnly": false,
\t\t\t"disabled": false,
\t\t\t"customValidationMessage": "",
\t\t\t"attributes": [],
\t\t\t"data": {
\t\t\t\t"recordType": "{$treeClassJS}",
\t\t\t\t"collectionReadEndpoint": {
\t\t\t\t\t"url": "{$adminURL}campaigns\\/sets",
\t\t\t\t\t"method": "GET"
\t\t\t\t},
\t\t\t\t"itemReadEndpoint": {
\t\t\t\t\t"url": "{$adminURL}campaigns\\/set\\/:id",
\t\t\t\t\t"method": "GET"
\t\t\t\t},
\t\t\t\t"itemUpdateEndpoint": {
\t\t\t\t\t"url": "{$adminURL}campaigns\\/set\\/:id",
\t\t\t\t\t"method": "PUT"
\t\t\t\t},
\t\t\t\t"itemCreateEndpoint": {
\t\t\t\t\t"url": "{$adminURL}campaigns\\/set\\/:id",
\t\t\t\t\t"method": "POST"
\t\t\t\t},
\t\t\t\t"itemDeleteEndpoint": {
\t\t\t\t\t"url": "{$adminURL}campaigns\\/set\\/:id",
\t\t\t\t\t"method": "DELETE"
\t\t\t\t},
\t\t\t\t"editFormSchemaEndpoint": "{$adminURL}campaigns\\/schema\\/DetailEditForm",
\t\t\t\t"columns": [
\t\t\t\t\t{"name": "Title", "field": "Name"},
\t\t\t\t\t{"name": "Changes", "field": "ChangesCount"},
\t\t\t\t\t{"name": "Description", "field": "Description"}
\t\t\t\t]
\t\t\t}
\t\t}, {
\t\t\t"name": "SecurityID",
\t\t\t"id": "Form_EditForm_SecurityID",
\t\t\t"type": "Hidden",
\t\t\t"component": null,
\t\t\t"holderId": null,
\t\t\t"title": "Security ID",
\t\t\t"source": null,
\t\t\t"extraClass": "hidden",
\t\t\t"description": null,
\t\t\t"rightTitle": null,
\t\t\t"leftTitle": null,
\t\t\t"readOnly": false,
\t\t\t"disabled": false,
\t\t\t"customValidationMessage": "",
\t\t\t"attributes": [],
\t\t\t"data": []
\t\t}],
\t\t"actions": []
\t}
}
JSON;
        $formName = $request->param('ID');
        if ($formName == 'EditForm') {
            $response = $this->getResponse();
            $response->addHeader('Content-Type', 'application/json');
            $response->setBody($json);
            return $response;
        } else {
            return parent::schema($request);
        }
    }
    /**
     * 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;
            }
        }
    }
    /**
     * Redirect the user to the change password form.
     *
     * @return HTTPResponse
     */
    protected function redirectToChangePassword()
    {
        // Since this form is loaded via an iframe, this redirect must be performed via javascript
        $changePasswordForm = new ChangePasswordForm($this->controller, 'SilverStripe\\Security\\ChangePasswordForm');
        $changePasswordForm->sessionMessage(_t('Member.PASSWORDEXPIRED', 'Your password has expired. Please choose a new one.'), 'good');
        // Get redirect url
        $changePasswordURL = $this->getExternalLink('changepassword');
        if ($backURL = $this->controller->getRequest()->requestVar('BackURL')) {
            Session::set('BackURL', $backURL);
            $changePasswordURL = Controller::join_links($changePasswordURL, '?BackURL=' . urlencode($backURL));
        }
        $changePasswordURLATT = Convert::raw2att($changePasswordURL);
        $changePasswordURLJS = Convert::raw2js($changePasswordURL);
        $message = _t('CMSMemberLoginForm.PASSWORDEXPIRED', '<p>Your password has expired. <a target="_top" href="{link}">Please choose a new one.</a></p>', 'Message displayed to user if their session cannot be restored', array('link' => $changePasswordURLATT));
        // Redirect to change password page
        $this->controller->getResponse()->setStatusCode(200);
        $this->controller->getResponse()->setBody(<<<PHP
<!DOCTYPE html>
<html><body>
{$message}
<script type="application/javascript">
setTimeout(function(){top.location.href = "{$changePasswordURLJS}";}, 0);
</script>
</body></html>
PHP
);
        return $this->controller->getResponse();
    }
 /**
  * Tests {@link Convert::raw2js()}
  */
 public function testRaw2JS()
 {
     // Test attempt to break out of string
     $this->assertEquals('\\"; window.location=\\"http://www.google.com', Convert::raw2js('"; window.location="http://www.google.com'));
     $this->assertEquals('\\\'; window.location=\\\'http://www.google.com', Convert::raw2js('\'; window.location=\'http://www.google.com'));
     // Test attempt to close script tag
     $this->assertEquals('\\"; \\x3c/script\\x3e\\x3ch1\\x3eHa \\x26amp; Ha\\x3c/h1\\x3e\\x3cscript\\x3e', Convert::raw2js('"; </script><h1>Ha &amp; Ha</h1><script>'));
     // Test newlines are properly escaped
     $this->assertEquals('New\\nLine\\rReturn', Convert::raw2js("New\nLine\rReturn"));
     // Check escape of slashes
     $this->assertEquals('\\\\\\"\\x3eClick here', Convert::raw2js('\\">Click here'));
 }