protected function init()
 {
     parent::init();
     if (!Director::is_cli() && !Permission::check('ADMIN')) {
         Security::permissionFailure();
     }
 }
 protected function init()
 {
     parent::init();
     // Unless called from the command line, all CliControllers need ADMIN privileges
     if (!Director::is_cli() && !Permission::check("ADMIN")) {
         Security::permissionFailure();
     }
 }
 /**
  * Require basic authentication.  Will request a username and password if none is given.
  *
  * Used by {@link Controller::init()}.
  *
  * @throws HTTPResponse_Exception
  *
  * @param string $realm
  * @param string|array $permissionCode Optional
  * @param boolean $tryUsingSessionLogin If true, then the method with authenticate against the
  *  session log-in if those credentials are disabled.
  * @return Member|bool $member
  */
 public static function requireLogin($realm, $permissionCode = null, $tryUsingSessionLogin = true)
 {
     $isRunningTests = class_exists('SilverStripe\\Dev\\SapphireTest', false) && SapphireTest::is_running_test();
     if (!Security::database_is_ready() || Director::is_cli() && !$isRunningTests) {
         return true;
     }
     /*
      * Enable HTTP Basic authentication workaround for PHP running in CGI mode with Apache
      * Depending on server configuration the auth header may be in HTTP_AUTHORIZATION or
      * REDIRECT_HTTP_AUTHORIZATION
      *
      * The follow rewrite rule must be in the sites .htaccess file to enable this workaround
      * RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
      */
     $authHeader = isset($_SERVER['HTTP_AUTHORIZATION']) ? $_SERVER['HTTP_AUTHORIZATION'] : (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) ? $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] : null);
     $matches = array();
     if ($authHeader && preg_match('/Basic\\s+(.*)$/i', $authHeader, $matches)) {
         list($name, $password) = explode(':', base64_decode($matches[1]));
         $_SERVER['PHP_AUTH_USER'] = strip_tags($name);
         $_SERVER['PHP_AUTH_PW'] = strip_tags($password);
     }
     $member = null;
     if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
         $member = MemberAuthenticator::authenticate(array('Email' => $_SERVER['PHP_AUTH_USER'], 'Password' => $_SERVER['PHP_AUTH_PW']), null);
     }
     if (!$member && $tryUsingSessionLogin) {
         $member = Member::currentUser();
     }
     // If we've failed the authentication mechanism, then show the login form
     if (!$member) {
         $response = new HTTPResponse(null, 401);
         $response->addHeader('WWW-Authenticate', "Basic realm=\"{$realm}\"");
         if (isset($_SERVER['PHP_AUTH_USER'])) {
             $response->setBody(_t('BasicAuth.ERRORNOTREC', "That username / password isn't recognised"));
         } else {
             $response->setBody(_t('BasicAuth.ENTERINFO', "Please enter a username and password."));
         }
         // Exception is caught by RequestHandler->handleRequest() and will halt further execution
         $e = new HTTPResponse_Exception(null, 401);
         $e->setResponse($response);
         throw $e;
     }
     if ($permissionCode && !Permission::checkMember($member->ID, $permissionCode)) {
         $response = new HTTPResponse(null, 401);
         $response->addHeader('WWW-Authenticate', "Basic realm=\"{$realm}\"");
         if (isset($_SERVER['PHP_AUTH_USER'])) {
             $response->setBody(_t('BasicAuth.ERRORNOTADMIN', "That user is not an administrator."));
         }
         // Exception is caught by RequestHandler->handleRequest() and will halt further execution
         $e = new HTTPResponse_Exception(null, 401);
         $e->setResponse($response);
         throw $e;
     }
     return $member;
 }
 /**
  * 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;
     }
 }
 public function run($request)
 {
     if (!Permission::check('ADMIN') && !Director::is_cli()) {
         $response = Security::permissionFailure();
         if ($response) {
             $response->output();
         }
         die;
     }
     SapphireTest::delete_all_temp_dbs();
 }
 public function index()
 {
     if (!Director::is_cli()) {
         return "The SilverStripe Interactive Command-line doesn't work in a web browser." . " Use 'sake interactive' from the command-line to run.";
     }
     /* Try using PHP_Shell if it exists */
     @(include 'php-shell-cmd.php');
     /* Fall back to our simpler interface */
     if (empty($__shell)) {
         set_error_handler(array($this, 'error_handler'));
         echo "SilverStripe Interactive Command-line (REPL interface). Type help for hints.\n\n";
         while (true) {
             echo CLI::text("?> ", "cyan");
             echo CLI::start_colour("yellow");
             $command = trim(fgets(STDIN, 4096));
             echo CLI::end_colour();
             if ($command == 'help' || $command == '?') {
                 print "help or ? to exit\n";
                 print "quit or \\q to exit\n";
                 print "install PHP_Shell for a more advanced interface with" . " auto-completion and readline support\n\n";
                 continue;
             }
             if ($command == 'quit' || $command == '\\q') {
                 break;
             }
             // Simple command processing
             if (substr($command, -1) == ';') {
                 $command = substr($command, 0, -1);
             }
             $is_print = preg_match('/^\\s*print/i', $command);
             $is_return = preg_match('/^\\s*return/i', $command);
             if (!$is_print && !$is_return) {
                 $command = "return ({$command})";
             }
             $command .= ";";
             try {
                 $result = eval($command);
                 if (!$is_print) {
                     print_r($result);
                 }
                 echo "\n";
             } catch (Exception $__repl_exception) {
                 echo CLI::start_colour("red");
                 printf('%s (code: %d) got thrown' . PHP_EOL, get_class($__repl_exception), $__repl_exception->getCode());
                 print $__repl_exception;
                 echo "\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;
     }
 }
 protected function getAndCheckForError($url)
 {
     $this->logInWithPermission('ADMIN');
     if (Director::is_cli()) {
         // when in CLI the admin controller throws exceptions
         ob_start();
         try {
             $this->get($url);
         } catch (Exception $e) {
             ob_end_clean();
             return true;
         }
         ob_end_clean();
         return false;
     } else {
         // when in http the admin controller sets a response header
         ob_start();
         $resp = $this->get($url);
         ob_end_clean();
         return $resp->isError();
     }
 }
 /**
  * Updates the database schema, creating tables & fields as necessary.
  *
  * @param boolean $quiet Don't show messages
  * @param boolean $populate Populate the database, as well as setting up its schema
  * @param bool $testMode
  */
 public function doBuild($quiet = false, $populate = true, $testMode = false)
 {
     if ($quiet) {
         DB::quiet();
     } else {
         $conn = DB::get_conn();
         // Assumes database class is like "MySQLDatabase" or "MSSQLDatabase" (suffixed with "Database")
         $dbType = substr(get_class($conn), 0, -8);
         $dbVersion = $conn->getVersion();
         $databaseName = method_exists($conn, 'currentDatabase') ? $conn->getSelectedDatabase() : "";
         if (Director::is_cli()) {
             echo sprintf("\n\nBuilding database %s using %s %s\n\n", $databaseName, $dbType, $dbVersion);
         } else {
             echo sprintf("<h2>Building database %s using %s %s</h2>", $databaseName, $dbType, $dbVersion);
         }
     }
     // Set up the initial database
     if (!DB::is_active()) {
         if (!$quiet) {
             echo '<p><b>Creating database</b></p>';
         }
         // Load parameters from existing configuration
         global $databaseConfig;
         if (empty($databaseConfig) && empty($_REQUEST['db'])) {
             user_error("No database configuration available", E_USER_ERROR);
         }
         $parameters = !empty($databaseConfig) ? $databaseConfig : $_REQUEST['db'];
         // Check database name is given
         if (empty($parameters['database'])) {
             user_error("No database name given; please give a value for \$databaseConfig['database']", E_USER_ERROR);
         }
         $database = $parameters['database'];
         // Establish connection and create database in two steps
         unset($parameters['database']);
         DB::connect($parameters);
         DB::create_database($database);
     }
     // Build the database.  Most of the hard work is handled by DataObject
     $dataClasses = ClassInfo::subclassesFor('SilverStripe\\ORM\\DataObject');
     array_shift($dataClasses);
     if (!$quiet) {
         if (Director::is_cli()) {
             echo "\nCREATING DATABASE TABLES\n\n";
         } else {
             echo "\n<p><b>Creating database tables</b></p>\n\n";
         }
     }
     // Initiate schema update
     $dbSchema = DB::get_schema();
     $dbSchema->schemaUpdate(function () use($dataClasses, $testMode, $quiet) {
         foreach ($dataClasses as $dataClass) {
             // Check if class exists before trying to instantiate - this sidesteps any manifest weirdness
             if (!class_exists($dataClass)) {
                 continue;
             }
             // Check if this class should be excluded as per testing conventions
             $SNG = singleton($dataClass);
             if (!$testMode && $SNG instanceof TestOnly) {
                 continue;
             }
             // Log data
             if (!$quiet) {
                 if (Director::is_cli()) {
                     echo " * {$dataClass}\n";
                 } else {
                     echo "<li>{$dataClass}</li>\n";
                 }
             }
             // Instruct the class to apply its schema to the database
             $SNG->requireTable();
         }
     });
     ClassInfo::reset_db_cache();
     if ($populate) {
         if (!$quiet) {
             if (Director::is_cli()) {
                 echo "\nCREATING DATABASE RECORDS\n\n";
             } else {
                 echo "\n<p><b>Creating database records</b></p>\n\n";
             }
         }
         foreach ($dataClasses as $dataClass) {
             // Check if class exists before trying to instantiate - this sidesteps any manifest weirdness
             // Test_ indicates that it's the data class is part of testing system
             if (strpos($dataClass, 'Test_') === false && class_exists($dataClass)) {
                 if (!$quiet) {
                     if (Director::is_cli()) {
                         echo " * {$dataClass}\n";
                     } else {
                         echo "<li>{$dataClass}</li>\n";
                     }
                 }
                 singleton($dataClass)->requireDefaultRecords();
             }
         }
         // Remap obsolete class names
         $schema = DataObject::getSchema();
         foreach ($this->config()->classname_value_remapping as $oldClassName => $newClassName) {
             $baseDataClass = $schema->baseDataClass($newClassName);
             $badRecordCount = DataObject::get($baseDataClass)->filter(["ClassName" => $oldClassName])->count();
             if ($badRecordCount > 0) {
                 if (Director::is_cli()) {
                     echo " * Correcting {$badRecordCount} obsolete classname values for {$newClassName}\n";
                 } else {
                     echo "<li>Correcting {$badRecordCount} obsolete classname values for {$newClassName}</li>\n";
                 }
                 $table = $schema->baseDataTable($baseDataClass);
                 DB::prepared_query("UPDATE \"{$table}\" SET \"ClassName\" = ? WHERE \"ClassName\" = ?", [$newClassName, $oldClassName]);
             }
         }
     }
     touch(TEMP_FOLDER . '/database-last-generated-' . str_replace(array('\\', '/', ':'), '.', Director::baseFolder()));
     if (isset($_REQUEST['from_installer'])) {
         echo "OK";
     }
     if (!$quiet) {
         echo Director::is_cli() ? "\n Database build completed!\n\n" : "<p>Database build completed!</p>";
     }
     ClassInfo::reset_db_cache();
 }
 public static function delete_all_temp_dbs()
 {
     $prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_';
     foreach (DB::get_schema()->databaseList() as $dbName) {
         if (preg_match(sprintf('/^%stmpdb[0-9]+$/', $prefix), $dbName)) {
             DB::get_schema()->dropDatabase($dbName);
             if (Director::is_cli()) {
                 echo "Dropped database \"{$dbName}\"" . PHP_EOL;
             } else {
                 echo "<li>Dropped database \"{$dbName}\"</li>" . PHP_EOL;
             }
             flush();
         }
     }
 }
 /**
  * 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);
 }
 /**
  * Returns the domain part of the URL 'http://www.mysite.com'. Returns FALSE is this environment
  * variable isn't set.
  *
  * @return bool|string
  */
 public static function protocolAndHost()
 {
     $alternate = Config::inst()->get('SilverStripe\\Control\\Director', 'alternate_base_url');
     if ($alternate) {
         if (preg_match('/^(http[^:]*:\\/\\/[^\\/]+)(\\/|$)/', $alternate, $matches)) {
             return $matches[1];
         }
     }
     if (isset($_SERVER['HTTP_HOST'])) {
         return Director::protocol() . $_SERVER['HTTP_HOST'];
     } else {
         global $_FILE_TO_URL_MAPPING;
         if (Director::is_cli() && isset($_FILE_TO_URL_MAPPING)) {
             $errorSuggestion = '  You probably want to define ' . 'an entry in $_FILE_TO_URL_MAPPING that covers "' . Director::baseFolder() . '"';
         } elseif (Director::is_cli()) {
             $errorSuggestion = '  You probably want to define $_FILE_TO_URL_MAPPING in ' . 'your _ss_environment.php as instructed on the "sake" page of the doc.silverstripe.com wiki';
         } else {
             $errorSuggestion = "";
         }
         user_error("Director::protocolAndHost() lacks sufficient information - HTTP_HOST not set." . $errorSuggestion, E_USER_WARNING);
         return false;
     }
 }
 /**
  * Show a message about database alteration
  *
  * @param string $message to display
  * @param string $type one of [created|changed|repaired|obsolete|deleted|error]
  */
 public function alterationMessage($message, $type = "")
 {
     if (!$this->supressOutput) {
         if (Director::is_cli()) {
             switch ($type) {
                 case "created":
                 case "changed":
                 case "repaired":
                     $sign = "+";
                     break;
                 case "obsolete":
                 case "deleted":
                     $sign = '-';
                     break;
                 case "notice":
                     $sign = '*';
                     break;
                 case "error":
                     $sign = "!";
                     break;
                 default:
                     $sign = " ";
             }
             $message = strip_tags($message);
             echo "  {$sign} {$message}\n";
         } else {
             switch ($type) {
                 case "created":
                     $color = "green";
                     break;
                 case "obsolete":
                     $color = "red";
                     break;
                 case "notice":
                     $color = "orange";
                     break;
                 case "error":
                     $color = "red";
                     break;
                 case "deleted":
                     $color = "red";
                     break;
                 case "changed":
                     $color = "blue";
                     break;
                 case "repaired":
                     $color = "blue";
                     break;
                 default:
                     $color = "";
             }
             echo "<li style=\"color: {$color}\">{$message}</li>";
         }
     }
 }
 /**
  * Regenerate the session_id.
  * This wrapper is here to make it easier to disable calls to session_regenerate_id(), should you need to.
  * They have caused problems in certain
  * quirky problems (such as using the Windmill 0.3.6 proxy).
  */
 public static function session_regenerate_id()
 {
     if (!self::config()->session_regenerate_id) {
         return;
     }
     // This can be called via CLI during testing.
     if (Director::is_cli()) {
         return;
     }
     $file = '';
     $line = '';
     // @ is to supress win32 warnings/notices when session wasn't cleaned up properly
     // There's nothing we can do about this, because it's an operating system function!
     if (!headers_sent($file, $line)) {
         @session_regenerate_id(true);
     }
 }
 /**
  * Choose the stage the site is currently on.
  *
  * If $_GET['stage'] is set, then it will use that stage, and store it in
  * the session.
  *
  * if $_GET['archiveDate'] is set, it will use that date, and store it in
  * the session.
  *
  * If neither of these are set, it checks the session, otherwise the stage
  * is set to 'Live'.
  */
 public static function choose_site_stage()
 {
     // Check any pre-existing session mode
     $preexistingMode = Session::get('readingMode');
     // Determine the reading mode
     if (isset($_GET['stage'])) {
         $stage = ucfirst(strtolower($_GET['stage']));
         if (!in_array($stage, array(static::DRAFT, static::LIVE))) {
             $stage = static::LIVE;
         }
         $mode = 'Stage.' . $stage;
     } elseif (isset($_GET['archiveDate']) && strtotime($_GET['archiveDate'])) {
         $mode = 'Archive.' . $_GET['archiveDate'];
     } elseif ($preexistingMode) {
         $mode = $preexistingMode;
     } else {
         $mode = static::DEFAULT_MODE;
     }
     // Save reading mode
     Versioned::set_reading_mode($mode);
     // Try not to store the mode in the session if not needed
     if ($preexistingMode && $preexistingMode !== $mode || !$preexistingMode && $mode !== static::DEFAULT_MODE) {
         Session::set('readingMode', $mode);
     }
     if (!headers_sent() && !Director::is_cli()) {
         if (Versioned::get_stage() == 'Live') {
             // clear the cookie if it's set
             if (Cookie::get('bypassStaticCache')) {
                 Cookie::force_expiry('bypassStaticCache', null, null, false, true);
             }
         } else {
             // set the cookie if it's cleared
             if (!Cookie::get('bypassStaticCache')) {
                 Cookie::set('bypassStaticCache', '1', 0, null, null, false, true);
             }
         }
     }
 }
 /**
  * @return array Array of associative arrays for each task (Keys: 'class', 'title', 'description')
  */
 protected function getTasks()
 {
     $availableTasks = array();
     $taskClasses = ClassInfo::subclassesFor('SilverStripe\\Dev\\BuildTask');
     // remove the base class
     array_shift($taskClasses);
     foreach ($taskClasses as $class) {
         if (!$this->taskEnabled($class)) {
             continue;
         }
         $singleton = BuildTask::singleton($class);
         $desc = Director::is_cli() ? Convert::html2raw($singleton->getDescription()) : $singleton->getDescription();
         $availableTasks[] = array('class' => $class, 'title' => $singleton->getTitle(), 'segment' => $singleton->config()->segment ?: str_replace('\\', '-', $class), 'description' => $desc);
     }
     return $availableTasks;
 }
 /**
  * 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();
     }
 }
Example #18
0
 /**
  * Set an alternative database in a browser cookie,
  * with the cookie lifetime set to the browser session.
  * This is useful for integration testing on temporary databases.
  *
  * There is a strict naming convention for temporary databases to avoid abuse:
  * <prefix> (default: 'ss_') + tmpdb + <7 digits>
  * As an additional security measure, temporary databases will
  * be ignored in "live" mode.
  *
  * Note that the database will be set on the next request.
  * Set it to null to revert to the main database.
  * @param string $name
  */
 public static function set_alternative_database_name($name = null)
 {
     // Skip if CLI
     if (Director::is_cli()) {
         return;
     }
     if ($name) {
         if (!self::valid_alternative_database_name($name)) {
             throw new InvalidArgumentException(sprintf('Invalid alternative database name: "%s"', $name));
         }
         $key = Config::inst()->get('SilverStripe\\Security\\Security', 'token');
         if (!$key) {
             throw new LogicException('"Security.token" not found, run "sake dev/generatesecuretoken"');
         }
         if (!function_exists('mcrypt_encrypt')) {
             throw new LogicException('DB::set_alternative_database_name() requires the mcrypt PHP extension');
         }
         $key = md5($key);
         // Ensure key is correct length for chosen cypher
         $ivSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB);
         $iv = mcrypt_create_iv($ivSize);
         $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $name, MCRYPT_MODE_CFB, $iv);
         // Set to browser session lifetime, and restricted to HTTP access only
         Cookie::set("alternativeDatabaseName", base64_encode($encrypted), 0, null, null, false, true);
         Cookie::set("alternativeDatabaseNameIv", base64_encode($iv), 0, null, null, false, true);
     } else {
         Cookie::force_expiry("alternativeDatabaseName", null, null, false, true);
         Cookie::force_expiry("alternativeDatabaseNameIv", null, null, false, true);
     }
 }