public function index()
 {
     $tasks = $this->getTasks();
     // Web mode
     if (!Director::is_cli()) {
         $renderer = new DebugView();
         echo $renderer->renderHeader();
         echo $renderer->renderInfo("SilverStripe Development Tools: Tasks", Director::absoluteBaseURL());
         $base = Director::absoluteBaseURL();
         echo "<div class=\"options\">";
         echo "<ul>";
         foreach ($tasks as $task) {
             echo "<li><p>";
             echo "<a href=\"{$base}dev/tasks/" . $task['segment'] . "\">" . $task['title'] . "</a><br />";
             echo "<span class=\"description\">" . $task['description'] . "</span>";
             echo "</p></li>\n";
         }
         echo "</ul></div>";
         echo $renderer->renderFooter();
         // CLI mode
     } else {
         echo "SILVERSTRIPE DEVELOPMENT TOOLS: Tasks\n--------------------------\n\n";
         foreach ($tasks as $task) {
             echo " * {$task['title']}: sake dev/tasks/" . $task['segment'] . "\n";
         }
     }
 }
 public function build($request)
 {
     if (Director::is_cli()) {
         $da = DatabaseAdmin::create();
         return $da->handleRequest($request, $this->model);
     } else {
         $renderer = DebugView::create();
         echo $renderer->renderHeader();
         echo $renderer->renderInfo("Environment Builder", Director::absoluteBaseURL());
         echo "<div class=\"build\">";
         $da = DatabaseAdmin::create();
         $response = $da->handleRequest($request, $this->model);
         echo "</div>";
         echo $renderer->renderFooter();
         return $response;
     }
 }
 /**
  * Change the password
  *
  * @param array $data The user submitted data
  * @return HTTPResponse
  */
 public function doChangePassword(array $data)
 {
     if ($member = Member::currentUser()) {
         // The user was logged in, check the current password
         if (empty($data['OldPassword']) || !$member->checkPassword($data['OldPassword'])->valid()) {
             $this->clearMessage();
             $this->sessionMessage(_t('Member.ERRORPASSWORDNOTMATCH', "Your current password does not match, please try again"), "bad");
             // redirect back to the form, instead of using redirectBack() which could send the user elsewhere.
             return $this->controller->redirect($this->controller->Link('changepassword'));
         }
     }
     if (!$member) {
         if (Session::get('AutoLoginHash')) {
             $member = Member::member_from_autologinhash(Session::get('AutoLoginHash'));
         }
         // The user is not logged in and no valid auto login hash is available
         if (!$member) {
             Session::clear('AutoLoginHash');
             return $this->controller->redirect($this->controller->Link('login'));
         }
     }
     // Check the new password
     if (empty($data['NewPassword1'])) {
         $this->clearMessage();
         $this->sessionMessage(_t('Member.EMPTYNEWPASSWORD', "The new password can't be empty, please try again"), "bad");
         // redirect back to the form, instead of using redirectBack() which could send the user elsewhere.
         return $this->controller->redirect($this->controller->Link('changepassword'));
     } else {
         if ($data['NewPassword1'] == $data['NewPassword2']) {
             $isValid = $member->changePassword($data['NewPassword1']);
             if ($isValid->valid()) {
                 // Clear locked out status
                 $member->LockedOutUntil = null;
                 $member->FailedLoginCount = null;
                 $member->write();
                 if ($member->canLogIn()->valid()) {
                     $member->logIn();
                 }
                 // TODO Add confirmation message to login redirect
                 Session::clear('AutoLoginHash');
                 if (!empty($_REQUEST['BackURL']) && Director::is_site_url($_REQUEST['BackURL'])) {
                     $url = Director::absoluteURL($_REQUEST['BackURL']);
                     return $this->controller->redirect($url);
                 } else {
                     // Redirect to default location - the login form saying "You are logged in as..."
                     $redirectURL = HTTP::setGetVar('BackURL', Director::absoluteBaseURL(), $this->controller->Link('login'));
                     return $this->controller->redirect($redirectURL);
                 }
             } else {
                 $this->clearMessage();
                 $this->sessionMessage(_t('Member.INVALIDNEWPASSWORD', "We couldn't accept that password: {password}", array('password' => nl2br("\n" . Convert::raw2xml($isValid->starredList())))), "bad", false);
                 // redirect back to the form, instead of using redirectBack() which could send the user elsewhere.
                 return $this->controller->redirect($this->controller->Link('changepassword'));
             }
         } else {
             $this->clearMessage();
             $this->sessionMessage(_t('Member.ERRORNEWPASSWORD', "You have entered your new password differently, try again"), "bad");
             // redirect back to the form, instead of using redirectBack() which could send the user elsewhere.
             return $this->controller->redirect($this->controller->Link('changepassword'));
         }
     }
 }
 /**
  * Build the default data, calling requireDefaultRecords on all
  * DataObject classes
  * Should match the $url_handlers rule:
  *		'build/defaults' => 'buildDefaults',
  */
 public function buildDefaults()
 {
     $da = DatabaseAdmin::create();
     $renderer = null;
     if (!Director::is_cli()) {
         $renderer = DebugView::create();
         echo $renderer->renderHeader();
         echo $renderer->renderInfo("Defaults Builder", Director::absoluteBaseURL());
         echo "<div style=\"margin: 0 2em\">";
     }
     $da->buildDefaults();
     if (!Director::is_cli()) {
         echo "</div>";
         echo $renderer->renderFooter();
     }
 }
 /**
  * Gets the combined configuration of all LeafAndMain subclasses required by the client app.
  *
  * @return array
  *
  * WARNING: Experimental API
  */
 public function getCombinedClientConfig()
 {
     $combinedClientConfig = ['sections' => []];
     $cmsClassNames = CMSMenu::get_cms_classes('SilverStripe\\Admin\\LeftAndMain', true, CMSMenu::URL_PRIORITY);
     foreach ($cmsClassNames as $className) {
         $combinedClientConfig['sections'][$className] = Injector::inst()->get($className)->getClientConfig();
     }
     // Pass in base url (absolute and relative)
     $combinedClientConfig['baseUrl'] = Director::baseURL();
     $combinedClientConfig['absoluteBaseUrl'] = Director::absoluteBaseURL();
     $combinedClientConfig['adminUrl'] = AdminRootController::admin_url();
     // Get "global" CSRF token for use in JavaScript
     $token = SecurityToken::inst();
     $combinedClientConfig[$token->getName()] = $token->getValue();
     // Set env
     $combinedClientConfig['environment'] = Director::get_environment_type();
     $combinedClientConfig['debugging'] = $this->config()->client_debugging;
     return Convert::raw2json($combinedClientConfig);
 }
 public function testChangePasswordForLoggedInUsers()
 {
     $goodResponse = $this->doTestLoginForm('*****@*****.**', '1nitialPassword');
     // Change the password
     $this->get('Security/changepassword?BackURL=test/back');
     $changedResponse = $this->doTestChangepasswordForm('1nitialPassword', 'changedPassword');
     $this->assertEquals(302, $changedResponse->getStatusCode());
     $this->assertEquals(Controller::join_links(Director::absoluteBaseURL(), 'test/back'), $changedResponse->getHeader('Location'));
     $this->assertEquals($this->idFromFixture('SilverStripe\\Security\\Member', 'test'), $this->session()->inst_get('loggedInAs'));
     // Check if we can login with the new password
     $goodResponse = $this->doTestLoginForm('*****@*****.**', 'changedPassword');
     $this->assertEquals(302, $goodResponse->getStatusCode());
     $this->assertEquals(Controller::join_links(Director::absoluteBaseURL(), 'test/link'), $goodResponse->getHeader('Location'));
     $this->assertEquals($this->idFromFixture('SilverStripe\\Security\\Member', 'test'), $this->session()->inst_get('loggedInAs'));
 }
 /**
  * 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();
     }
 }
 /**
  * Render HTML header for development views
  *
  * @param HTTPRequest $httpRequest
  * @return string
  */
 public function renderHeader($httpRequest = null)
 {
     $url = htmlentities($_SERVER['REQUEST_METHOD'] . ' ' . $_SERVER['REQUEST_URI'], ENT_COMPAT, 'UTF-8');
     $debugCSS = Controller::join_links(Director::absoluteBaseURL(), FRAMEWORK_DIR, 'client/dist/styles/debug.css');
     $output = '<!DOCTYPE html><html><head><title>' . $url . '</title>';
     $output .= '<link rel="stylesheet" type="text/css" href="' . $debugCSS . '" />';
     $output .= '</head>';
     $output .= '<body>';
     return $output;
 }
 /**
  * Generate the JavaScript that will set TinyMCE's configuration:
  * - Parse all configurations into JSON objects to be used in JavaScript
  * - Includes TinyMCE and configurations using the {@link Requirements} system
  *
  * @return array
  */
 protected function getConfig()
 {
     $settings = $this->getSettings();
     // https://www.tinymce.com/docs/configure/url-handling/#document_base_url
     $settings['document_base_url'] = Director::absoluteBaseURL();
     // https://www.tinymce.com/docs/api/class/tinymce.editormanager/#baseURL
     $tinyMCEBaseURL = Controller::join_links(Director::absoluteBaseURL(), $this->config()->get('base_dir') ?: ADMIN_THIRDPARTY_DIR . '/tinymce');
     $settings['baseURL'] = $tinyMCEBaseURL;
     // map all plugins to absolute urls for loading
     $plugins = array();
     foreach ($this->getPlugins() as $plugin => $path) {
         if (!$path) {
             // Empty paths: Convert to urls in standard base url
             $path = Controller::join_links($tinyMCEBaseURL, "plugins/{$plugin}/plugin.min.js");
         } elseif (!Director::is_absolute_url($path)) {
             // Non-absolute urls are made absolute
             $path = Director::absoluteURL($path);
         }
         $plugins[$plugin] = $path;
     }
     // https://www.tinymce.com/docs/configure/integration-and-setup/#external_plugins
     if ($plugins) {
         $settings['external_plugins'] = $plugins;
     }
     // https://www.tinymce.com/docs/configure/editor-appearance/#groupingtoolbarcontrols
     $buttons = $this->getButtons();
     $settings['toolbar'] = [];
     foreach ($buttons as $rowButtons) {
         $row = implode(' ', $rowButtons);
         if (count($buttons) > 1) {
             $settings['toolbar'][] = $row;
         } else {
             $settings['toolbar'] = $row;
         }
     }
     // https://www.tinymce.com/docs/configure/content-appearance/#content_css
     $settings['content_css'] = $this->getEditorCSS();
     // https://www.tinymce.com/docs/configure/editor-appearance/#theme_url
     $theme = $this->getTheme();
     if (!Director::is_absolute_url($theme)) {
         $theme = Controller::join_links($tinyMCEBaseURL, "themes/{$theme}/theme.min.js");
     }
     $settings['theme_url'] = $theme;
     // Send back
     return $settings;
 }
 public function BaseURL()
 {
     return Director::absoluteBaseURL();
 }
 /**
  * Login in the user and figure out where to redirect the browser.
  *
  * The $data has this format
  * array(
  *   'AuthenticationMethod' => 'MemberAuthenticator',
  *   'Email' => '*****@*****.**',
  *   'Password' => '1nitialPassword',
  *   'BackURL' => 'test/link',
  *   [Optional: 'Remember' => 1 ]
  * )
  *
  * @param array $data
  * @return HTTPResponse
  */
 protected function logInUserAndRedirect($data)
 {
     Session::clear('SessionForms.MemberLoginForm.Email');
     Session::clear('SessionForms.MemberLoginForm.Remember');
     if (Member::currentUser()->isPasswordExpired()) {
         if (isset($_REQUEST['BackURL']) && ($backURL = $_REQUEST['BackURL'])) {
             Session::set('BackURL', $backURL);
         }
         /** @skipUpgrade */
         $cp = ChangePasswordForm::create($this->controller, 'ChangePasswordForm');
         $cp->sessionMessage(_t('Member.PASSWORDEXPIRED', 'Your password has expired. Please choose a new one.'), 'good');
         return $this->controller->redirect('Security/changepassword');
     }
     // Absolute redirection URLs may cause spoofing
     if (!empty($_REQUEST['BackURL'])) {
         $url = $_REQUEST['BackURL'];
         if (Director::is_site_url($url)) {
             $url = Director::absoluteURL($url);
         } else {
             // Spoofing attack, redirect to homepage instead of spoofing url
             $url = Director::absoluteBaseURL();
         }
         return $this->controller->redirect($url);
     }
     // If a default login dest has been set, redirect to that.
     if ($url = Security::config()->default_login_dest) {
         $url = Controller::join_links(Director::absoluteBaseURL(), $url);
         return $this->controller->redirect($url);
     }
     // Redirect the user to the page where they came from
     $member = Member::currentUser();
     if ($member) {
         $firstname = Convert::raw2xml($member->FirstName);
         if (!empty($data['Remember'])) {
             Session::set('SessionForms.MemberLoginForm.Remember', '1');
             $member->logIn(true);
         } else {
             $member->logIn();
         }
         Session::set('Security.Message.message', _t('Member.WELCOMEBACK', "Welcome Back, {firstname}", array('firstname' => $firstname)));
         Session::set("Security.Message.type", "good");
     }
     return Controller::curr()->redirectBack();
 }
 public function testRedirectBackByBackUrl()
 {
     $internalRelativeUrl = Controller::join_links(Director::baseURL(), '/some-url');
     $internalAbsoluteUrl = Controller::join_links(Director::absoluteBaseURL(), '/some-url');
     $response = $this->get('ControllerTest_Controller/redirectbacktest?BackURL=' . urlencode($internalRelativeUrl));
     $this->assertEquals(302, $response->getStatusCode());
     $this->assertEquals($internalAbsoluteUrl, $response->getHeader('Location'), "Redirects on internal relative URLs");
     $internalAbsoluteUrl = Director::absoluteBaseURL() . '/some-url';
     $response = $this->get('ControllerTest_Controller/redirectbacktest?BackURL=' . urlencode($internalAbsoluteUrl));
     $this->assertEquals($internalAbsoluteUrl, $response->getHeader('Location'));
     $this->assertEquals(302, $response->getStatusCode(), "Redirects on internal absolute URLs");
     $externalAbsoluteUrl = 'http://myhost.com/some-url';
     $response = $this->get('ControllerTest_Controller/redirectbacktest?BackURL=' . urlencode($externalAbsoluteUrl));
     $this->assertEquals(200, $response->getStatusCode(), "Doesn't redirect on external URLs");
 }
 public function testGetAbsoluteURL()
 {
     $rootfile = $this->objFromFixture('SilverStripe\\Assets\\File', 'asdf');
     $this->assertEquals(Director::absoluteBaseURL() . 'assets/FileTest/55b443b601/FileTest.txt', $rootfile->getAbsoluteURL());
 }
 /**
  * Return an appropriate base tag for the given template.
  * It will be closed on an XHTML document, and unclosed on an HTML document.
  *
  * @param string $contentGeneratedSoFar The content of the template generated so far; it should contain
  * the DOCTYPE declaration.
  * @return string
  */
 public static function get_base_tag($contentGeneratedSoFar)
 {
     $base = Director::absoluteBaseURL();
     // Is the document XHTML?
     if (preg_match('/<!DOCTYPE[^>]+xhtml/i', $contentGeneratedSoFar)) {
         return "<base href=\"{$base}\" />";
     } else {
         return "<base href=\"{$base}\"><!--[if lte IE 6]></base><![endif]-->";
     }
 }
 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');
 }
 /**
  * Will try to include a GET parameter for an existing URL, preserving existing parameters and
  * fragments. If no URL is given, falls back to $_SERVER['REQUEST_URI']. Uses parse_url() to
  * dissect the URL, and http_build_query() to reconstruct it with the additional parameter.
  * Converts any '&' (ampersand) URL parameter separators to the more XHTML compliant '&amp;'.
  *
  * CAUTION: If the URL is determined to be relative, it is prepended with Director::absoluteBaseURL().
  * This method will always return an absolute URL because Director::makeRelative() can lead to
  * inconsistent results.
  *
  * @param string $varname
  * @param string $varvalue
  * @param string $currentURL Relative or absolute URL.
  * @param string $separator Separator for http_build_query().
  *
  * @return string
  */
 public static function setGetVar($varname, $varvalue, $currentURL = null, $separator = '&amp;')
 {
     $uri = $currentURL ? $currentURL : Director::makeRelative($_SERVER['REQUEST_URI']);
     $isRelative = false;
     // We need absolute URLs for parse_url()
     if (Director::is_relative_url($uri)) {
         $uri = Director::absoluteBaseURL() . $uri;
         $isRelative = true;
     }
     // try to parse uri
     $parts = parse_url($uri);
     if (!$parts) {
         throw new InvalidArgumentException("Can't parse URL: " . $uri);
     }
     // Parse params and add new variable
     $params = array();
     if (isset($parts['query'])) {
         parse_str($parts['query'], $params);
     }
     $params[$varname] = $varvalue;
     // Generate URI segments and formatting
     $scheme = isset($parts['scheme']) ? $parts['scheme'] : 'http';
     $user = isset($parts['user']) && $parts['user'] != '' ? $parts['user'] : '';
     if ($user != '') {
         // format in either user:pass@host.com or user@host.com
         $user .= isset($parts['pass']) && $parts['pass'] != '' ? ':' . $parts['pass'] . '@' : '@';
     }
     $host = isset($parts['host']) ? $parts['host'] : '';
     $port = isset($parts['port']) && $parts['port'] != '' ? ':' . $parts['port'] : '';
     $path = isset($parts['path']) && $parts['path'] != '' ? $parts['path'] : '';
     // handle URL params which are existing / new
     $params = $params ? '?' . http_build_query($params, null, $separator) : '';
     // keep fragments (anchors) intact.
     $fragment = isset($parts['fragment']) && $parts['fragment'] != '' ? '#' . $parts['fragment'] : '';
     // Recompile URI segments
     $newUri = $scheme . '://' . $user . $host . $port . $path . $params . $fragment;
     if ($isRelative) {
         return Director::makeRelative($newUri);
     }
     return $newUri;
 }
 /**
  * Mostly tested by {@link testIsRelativeUrl()},
  * just adding the host name matching aspect here.
  */
 public function testIsSiteUrl()
 {
     $this->assertFalse(Director::is_site_url("http://test.com"));
     $this->assertTrue(Director::is_site_url(Director::absoluteBaseURL()));
     $this->assertFalse(Director::is_site_url("http://test.com?url=" . Director::absoluteBaseURL()));
     $this->assertFalse(Director::is_site_url("http://test.com?url=" . urlencode(Director::absoluteBaseURL())));
     $this->assertFalse(Director::is_site_url("//test.com?url=" . Director::absoluteBaseURL()));
 }