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 '&'. * * 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 = '&') { $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())); }