/**
  * Output file to the browser.
  * For performance reasons, we avoid SS_HTTPResponse and just output the contents instead.
  */
 public function sendFile($file)
 {
     $path = $file->getFullPath();
     if (SapphireTest::is_running_test()) {
         return file_get_contents($path);
     }
     header('Content-Description: File Transfer');
     // Quotes needed to retain spaces (http://kb.mozillazine.org/Filenames_with_spaces_are_truncated_upon_download)
     header('Content-Disposition: inline; filename="' . basename($path) . '"');
     header('Content-Length: ' . $file->getAbsoluteSize());
     header('Content-Type: ' . HTTP::get_mime_type($file->getRelativePath()));
     header('Content-Transfer-Encoding: binary');
     // Fixes IE6,7,8 file downloads over HTTPS bug (http://support.microsoft.com/kb/812935)
     header('Pragma: ');
     if ($this->config()->min_download_bandwidth) {
         // Allow the download to last long enough to allow full download with min_download_bandwidth connection.
         increase_time_limit_to((int) (filesize($path) / ($this->config()->min_download_bandwidth * 1024)));
     } else {
         // Remove the timelimit.
         increase_time_limit_to(0);
     }
     // Clear PHP buffer, otherwise the script will try to allocate memory for entire file.
     while (ob_get_level() > 0) {
         ob_end_flush();
     }
     // Prevent blocking of the session file by PHP. Without this the user can't visit another page of the same
     // website during download (see http://konrness.com/php5/how-to-prevent-blocking-php-requests/)
     session_write_close();
     readfile($path);
     die;
 }
 /**
  * Output file to the browser.
  * For performance reasons, we avoid SS_HTTPResponse and just output the contents instead.
  */
 public function sendFile($file)
 {
     $reader = $file->reader();
     if (!$reader || !$reader->isReadable()) {
         return;
     }
     if (class_exists('SapphireTest', false) && SapphireTest::is_running_test()) {
         return $reader->read();
     }
     $type = HTTP::get_mime_type($file->Filename);
     $disposition = strpos($type, 'image') !== false ? 'inline' : 'attachment';
     header('Content-Description: File Transfer');
     // Quotes needed to retain spaces (http://kb.mozillazine.org/Filenames_with_spaces_are_truncated_upon_download)
     header(sprintf('Content-Disposition: %s; filename="%s"', $disposition, basename($file->Filename)));
     header('Content-Length: ' . $file->FileSize);
     header('Content-Type: ' . $type);
     header('Content-Transfer-Encoding: binary');
     // Ensure we enforce no-cache headers consistently, so that files accesses aren't cached by CDN/edge networks
     header('Pragma: no-cache');
     header('Cache-Control: private, no-cache, no-store');
     increase_time_limit_to(0);
     // Clear PHP buffer, otherwise the script will try to allocate memory for entire file.
     while (ob_get_level() > 0) {
         ob_end_flush();
     }
     // Prevent blocking of the session file by PHP. Without this the user can't visit another page of the same
     // website during download (see http://konrness.com/php5/how-to-prevent-blocking-php-requests/)
     session_write_close();
     echo $reader->read();
     die;
 }
 /**
  * Run through the rules for this validator checking against
  * the temporary file set by {@link setTmpFile()} to see if
  * the file is deemed valid or not.
  * 
  * @return boolean
  */
 public function validate()
 {
     // we don't validate for empty upload fields yet
     if (!isset($this->tmpFile['name']) || empty($this->tmpFile['name'])) {
         return true;
     }
     $isRunningTests = class_exists('SapphireTest', false) && SapphireTest::is_running_test();
     //needed to allow XHR uploads
     /*if(isset($this->tmpFile['tmp_name']) && !is_uploaded_file($this->tmpFile['tmp_name']) && !$isRunningTests) {
     			$this->errors[] = _t('File.NOVALIDUPLOAD', 'File is not a valid upload');
     			return false;
     		}*/
     $pathInfo = pathinfo($this->tmpFile['name']);
     // filesize validation
     if (!$this->isValidSize()) {
         $ext = isset($pathInfo['extension']) ? $pathInfo['extension'] : '';
         $arg = File::format_size($this->getAllowedMaxFileSize($ext));
         $this->errors[] = sprintf(_t('File.TOOLARGE', 'Filesize is too large, maximum %s allowed.', PR_MEDIUM, 'Argument 1: Filesize (e.g. 1MB)'), $arg);
         return false;
     }
     // extension validation
     if (!$this->isValidExtension()) {
         $this->errors[] = sprintf(_t('File.INVALIDEXTENSION', 'Extension is not allowed (valid: %s)', PR_MEDIUM, 'Argument 1: Comma-separated list of valid extensions'), wordwrap(implode(', ', $this->allowedExtensions)));
         return false;
     }
     return true;
 }
 public function preRequest(SS_HTTPRequest $request, Session $session, DataModel $model)
 {
     // Bootstrap session so that Session::get() accesses the right instance
     $dummyController = new Controller();
     $dummyController->setSession($session);
     $dummyController->setRequest($request);
     $dummyController->pushCurrent();
     // Block non-authenticated users from setting the stage mode
     if (!Versioned::can_choose_site_stage($request)) {
         $permissionMessage = sprintf(_t("ContentController.DRAFT_SITE_ACCESS_RESTRICTION", 'You must log in with your CMS password in order to view the draft or archived content. ' . '<a href="%s">Click here to go back to the published site.</a>'), Controller::join_links(Director::baseURL(), $request->getURL(), "?stage=Live"));
         // Force output since RequestFilter::preRequest doesn't support response overriding
         $response = Security::permissionFailure($dummyController, $permissionMessage);
         $session->inst_save();
         $dummyController->popCurrent();
         // Prevent output in testing
         if (class_exists('SapphireTest', false) && SapphireTest::is_running_test()) {
             throw new SS_HTTPResponse_Exception($response);
         }
         $response->output();
         die;
     }
     Versioned::choose_site_stage();
     $dummyController->popCurrent();
     return true;
 }
 /**
  * Start a new instance of this class.
  * @param string $url The URL to parse for links
  */
 function __construct($url)
 {
     $this->url = $url;
     if (class_exists('SapphireTest', false) && SapphireTest::is_running_test()) {
         $this->showMessages = false;
     }
 }
 function init()
 {
     parent::init();
     $canAccess = Director::isDev() || Director::is_cli() && !SapphireTest::is_running_test() || Permission::check("ADMIN");
     if (!$canAccess) {
         return Security::permissionFailure($this);
     }
 }
 public function init()
 {
     parent::init();
     $isRunningTests = class_exists('SapphireTest', false) && SapphireTest::is_running_test();
     $canAccess = Director::isDev() || Director::is_cli() && !$isRunningTests || Permission::check("ADMIN");
     if (!$canAccess) {
         return Security::permissionFailure($this);
     }
 }
 /**
  * Require basic authentication.  Will request a username and password if none is given.
  *
  * Used by {@link Controller::init()}.
  *
  * @throws SS_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 $member
  */
 public static function requireLogin($realm, $permissionCode = null, $tryUsingSessionLogin = true)
 {
     $isRunningTests = class_exists('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 SS_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 SS_HTTPResponse_Exception(null, 401);
         $e->setResponse($response);
         throw $e;
     }
     if ($permissionCode && !Permission::checkMember($member->ID, $permissionCode)) {
         $response = new SS_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 SS_HTTPResponse_Exception(null, 401);
         $e->setResponse($response);
         throw $e;
     }
     return $member;
 }
 /**
  * Register our shutdown handler
  */
 public function __construct()
 {
     // bind a shutdown function to process all 'immediate' queued jobs if needed, but only in CLI mode
     if (self::$use_shutdown_function && Director::is_cli()) {
         if (class_exists('PHPUnit_Framework_TestCase') && SapphireTest::is_running_test()) {
             // do NOTHING
         } else {
             register_shutdown_function(array($this, 'onShutdown'));
         }
     }
 }
 function init()
 {
     parent::init();
     // We allow access to this controller regardless of live-status or ADMIN permission only
     // if on CLI or with the database not ready. The latter makes it less errorprone to do an
     // initial schema build without requiring a default-admin login.
     // Access to this controller is always allowed in "dev-mode", or of the user is ADMIN.
     $canAccess = Director::isDev() || !Security::database_is_ready() || Director::is_cli() && !SapphireTest::is_running_test() || Permission::check("ADMIN");
     if (!$canAccess) {
         return Security::permissionFailure($this, "This page is secured and you need administrator rights to access it. " . "Enter your credentials below and we will send you right along.");
     }
 }
 /**
  * standard Silverstripe method - required
  *
  */
 function init()
 {
     parent::init();
     // We allow access to this controller regardless of live-status or ADMIN permission only
     // or if on CLI.
     // Access to this controller is always allowed in "dev-mode", or if the user is ADMIN.
     $isRunningTests = class_exists('SapphireTest', false) && SapphireTest::is_running_test();
     $canAccess = Director::isDev() || Director::is_cli() && !$isRunningTests || Permission::check("ADMIN") || Permission::check(EcommerceConfig::get("EcommerceRole", "admin_group_code"));
     if (!$canAccess) {
         return Security::permissionFailure($this, "The e-commerce development control panel is secured and you need administrator rights to access it. " . "Enter your credentials below and we will send you right along.");
     }
 }
示例#12
0
	function init() {
		parent::init();

		$isRunningTests = (class_exists('SapphireTest', false) && SapphireTest::is_running_test());
		$canAccess = (
			Director::isDev() 
			// We need to ensure that DevelopmentAdminTest can simulate permission failures when running
			// "dev/tasks" from CLI.
			|| (Director::is_cli() && !$isRunningTests)
			|| Permission::check("ADMIN")
		);
		if(!$canAccess) return Security::permissionFailure($this);
	}
 /**
  * @return \Member
  */
 protected static function getBasicAuthMember()
 {
     $realm = \Config::inst()->get('HttpAuth', 'Realm');
     $permissionCode = \Config::inst()->get('HttpAuth', 'PermissionCode');
     $isRunningTests = class_exists('SapphireTest', false) && \SapphireTest::is_running_test();
     $tryUsingSessionLogin = $isRunningTests || \Config::inst()->get('HttpAuth', 'TryUsingSessionLogin');
     try {
         $member = \BasicAuth::requireLogin($realm, $permissionCode, $tryUsingSessionLogin);
         return $member;
     } catch (\Exception $ex) {
         return null;
     }
 }
 /**
  * Use table information and locales to dynamically build required table fields
  * @see DataExtension::get_extra_config()
  * @inheritdoc
  */
 public static function get_extra_config($class, $extension, $args)
 {
     if (!self::is_translatable_installed()) {
         // remain silent during a test
         if (SapphireTest::is_running_test()) {
             return null;
         }
         // raise an error otherwise
         user_error('Translatable module is not installed but required.', E_USER_WARNING);
         return null;
     }
     if ($args) {
         self::$arguments[$class] = $args;
     }
     return array('db' => self::collectDBFields($class));
 }
 public function init()
 {
     parent::init();
     // We allow access to this controller regardless of live-status or ADMIN permission only
     // if on CLI or with the database not ready. The latter makes it less errorprone to do an
     // initial schema build without requiring a default-admin login.
     // Access to this controller is always allowed in "dev-mode", or of the user is ADMIN.
     $isRunningTests = class_exists('SapphireTest', false) && SapphireTest::is_running_test();
     $canAccess = Director::isDev() || !Security::database_is_ready() || Director::is_cli() && !$isRunningTests || Permission::check("ADMIN");
     if (!$canAccess) {
         return Security::permissionFailure($this, "This page is secured and you need administrator rights to access it. " . "Enter your credentials below and we will send you right along.");
     }
     //render the debug view
     $renderer = Object::create('DebugView');
     $renderer->writeHeader();
     $renderer->writeInfo(_t("Shop.DEVTOOLSTITLE", "Shop Development Tools"), Director::absoluteBaseURL());
 }
示例#16
0
 /**
  * Require basic authentication.  Will request a username and password if none is given.
  *
  * Used by {@link Controller::init()}.
  *
  * @throws SS_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 $member
  */
 public static function requireLogin($realm, $permissionCode = null, $tryUsingSessionLogin = true)
 {
     $isRunningTests = class_exists('SapphireTest', false) && SapphireTest::is_running_test();
     if (!Security::database_is_ready() || Director::is_cli() && !$isRunningTests) {
         return true;
     }
     $matches = array();
     if (isset($_SERVER['HTTP_AUTHORIZATION']) && preg_match('/Basic\\s+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $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 SS_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 SS_HTTPResponse_Exception(null, 401);
         $e->setResponse($response);
         throw $e;
     }
     if ($permissionCode && !Permission::checkMember($member->ID, $permissionCode)) {
         $response = new SS_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 SS_HTTPResponse_Exception(null, 401);
         $e->setResponse($response);
         throw $e;
     }
     return $member;
 }
 public function geocodeAddress()
 {
     //we don't want geocoding to occur during testing
     //TODO: we could possibly switch to a mock setup
     if (class_exists('SapphireTest', false) && SapphireTest::is_running_test()) {
         return;
     }
     //TODO: check if address is valid
     $geocoder = self::get_geocoder();
     try {
         $geocoded = $geocoder->geocode($this->owner->toString());
         $this->owner->Latitude = $geocoded->getLatitude();
         $this->owner->Longitude = $geocoded->getLongitude();
     } catch (Exception $e) {
         SS_Log::log($e, SS_Log::ERR);
     }
 }
 /**
  *
  * @param StaticPagesQueue $eventClass
  * @return bool - if the event was fired or not
  * @throws Exception 
  */
 public static function fire_event(StaticPagesQueueEvent $eventClass)
 {
     if (class_exists('SapphireTest') && SapphireTest::is_running_test() && !self::$fire_test_events) {
         return false;
     }
     $eventClassName = get_class($eventClass);
     if (!array_key_exists($eventClassName, self::$events)) {
         throw new StaticPagesQueueEvent_Exception('The event "' . $eventClassName . '" has not yet been registered and therefore can\'t be triggered.');
     }
     $interfaceName = self::$events[$eventClassName];
     $implementors = ClassInfo::implementorsOf($interfaceName);
     $methodName = lcfirst(str_replace('Listener', '', $interfaceName));
     foreach ($implementors as $implementor) {
         $controller = new $implementor();
         $controller->{$methodName}($eventClass);
     }
     return true;
 }
示例#19
0
	function init() {
		parent::init();
		
		// We allow access to this controller regardless of live-status or ADMIN permission only
		// if on CLI or with the database not ready. The latter makes it less errorprone to do an
		// initial schema build without requiring a default-admin login.
		// Access to this controller is always allowed in "dev-mode", or of the user is ADMIN.
		$isRunningTests = (class_exists('SapphireTest', false) && SapphireTest::is_running_test());
		$canAccess = (
			Director::isDev() 
			|| !Security::database_is_ready() 
			// We need to ensure that DevelopmentAdminTest can simulate permission failures when running
			// "dev/tests" from CLI. 
			|| (Director::is_cli() && !$isRunningTests)
			|| Permission::check("ADMIN")
		);
		if(!$canAccess) {
			return Security::permissionFailure($this,
				"This page is secured and you need administrator rights to access it. " .
				"Enter your credentials below and we will send you right along.");
		}
	}
 /**
  * Check if combined files are enabled
  *
  * @return bool
  */
 public function getCombinedFilesEnabled()
 {
     if (!$this->combinedFilesEnabled) {
         return false;
     }
     // Tests should be combined
     if (class_exists('SapphireTest', false) && SapphireTest::is_running_test()) {
         return true;
     }
     // Check if specified via querystring
     if (isset($_REQUEST['combine'])) {
         return true;
     }
     // Non-dev sites are always combined
     if (!Director::isDev()) {
         return true;
     }
     // Fallback to default
     return Config::inst()->get(__CLASS__, 'combine_in_dev');
 }
 /**
  * Register our shutdown handler
  */
 public function __construct()
 {
     // bind a shutdown function to process all 'immediate' queued jobs if needed, but only in CLI mode
     if (Config::inst()->get(__CLASS__, 'use_shutdown_function') && Director::is_cli()) {
         if (class_exists('PHPUnit_Framework_TestCase') && SapphireTest::is_running_test()) {
             // do NOTHING
         } else {
             register_shutdown_function(array($this, 'onShutdown'));
         }
     }
     if (Config::inst()->get('Email', 'queued_job_admin_email') == '') {
         Config::inst()->update('Email', 'queued_job_admin_email', Config::inst()->get('Email', 'admin_email'));
     }
 }
 function tearDown()
 {
     // Preserve memory settings
     ini_set('memory_limit', $this->originalMemoryLimit ? $this->originalMemoryLimit : -1);
     // Restore email configuration
     Email::set_mailer($this->originalMailer);
     $this->originalMailer = null;
     $this->mailer = null;
     // Restore password validation
     Member::set_password_validator($this->originalMemberPasswordValidator);
     // Restore requirements
     Requirements::set_backend($this->originalRequirements);
     // Mark test as no longer being run - we use originalIsRunningTest to allow for nested SapphireTest calls
     self::$is_running_test = $this->originalIsRunningTest;
     $this->originalIsRunningTest = null;
     // Reset theme setting
     SSViewer::set_theme($this->originalTheme);
     // Reset mocked datetime
     SS_Datetime::clear_mock_now();
     // Restore nested_urls state
     if ($this->originalNestedURLsState) {
         SiteTree::enable_nested_urls();
     } else {
         SiteTree::disable_nested_urls();
     }
     // Stop the redirection that might have been requested in the test.
     // Note: Ideally a clean Controller should be created for each test.
     // Now all tests executed in a batch share the same controller.
     $controller = Controller::has_curr() ? Controller::curr() : null;
     if ($controller && $controller->response && $controller->response->getHeader('Location')) {
         $controller->response->setStatusCode(200);
         $controller->response->removeHeader('Location');
     }
 }
 /**
  * @todo This should really be taken care of by the testing framework
  */
 protected function debugMessage($msg)
 {
     if (class_exists('SapphireTest', false) && !SapphireTest::is_running_test()) {
         Debug::message($msg);
     }
 }
示例#24
0
 /**
  * Force the site to run on SSL.
  * 
  * To use, call from _config.php. For example:
  * <code>
  * if(Director::isLive()) Director::forceSSL();
  * </code>
  * 
  * If you don't want your entire site to be on SSL, you can pass an array of PCRE regular expression
  * patterns for matching relative URLs. For example:
  * <code>
  * if(Director::isLive()) Director::forceSSL(array('/^admin/', '/^Security/'));
  * </code>
  * 
  * Note that the session data will be lost when moving from HTTP to HTTPS.
  * It is your responsibility to ensure that this won't cause usability problems.
  * 
  * CAUTION: This does not respect the site environment mode. You should check this
  * as per the above examples using Director::isLive() or Director::isTest() for example.
  * 
  * @return boolean|string String of URL when unit tests running, boolean FALSE if patterns don't match request URI
  */
 static function forceSSL($patterns = null)
 {
     $matched = false;
     if ($patterns) {
         // protect portions of the site based on the pattern
         $relativeURL = self::makeRelative(Director::absoluteURL($_SERVER['REQUEST_URI']));
         foreach ($patterns as $pattern) {
             if (preg_match($pattern, $relativeURL)) {
                 $matched = true;
                 break;
             }
         }
     } else {
         // protect the entire site
         $matched = true;
     }
     if ($matched && (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == 'off')) {
         $destURL = str_replace('http:', 'https:', Director::absoluteURL($_SERVER['REQUEST_URI']));
         // This coupling to SapphireTest is necessary to test the destination URL and to not interfere with tests
         if (class_exists('SapphireTest', false) && SapphireTest::is_running_test()) {
             return $destURL;
         } else {
             if (!headers_sent()) {
                 header("Location: {$destURL}");
             }
             die("<h1>Your browser is not accepting header redirects</h1><p>Please <a href=\"{$destURL}\">click here</a>");
         }
     } else {
         return false;
     }
 }
 /**
  * 
  * @param File $file
  * @return void
  */
 public function sendFileToBrowser($file)
 {
     $path = $file->getFullPath();
     if (SapphireTest::is_running_test()) {
         return file_get_contents($path);
     }
     $basename = basename($path);
     $length = $file->getAbsoluteSize();
     $type = HTTP::get_mime_type($file->getRelativePath());
     //handling time limitation
     if ($threshold = $this->config()->bandwidth_threshold) {
         increase_time_limit_to((int) ($length / $threshold));
     } else {
         increase_time_limit_to();
     }
     // send header
     header('Content-Description: File Transfer');
     /*
      * allow inline 'save as' popup, double quotation is present to prevent browser (eg. Firefox) from handling
      * wrongly a file with a name with whitespace, through a file in SilverStripe should not contain any whitespace
      * if the file is uploaded through SS interface
      * http://kb.mozillazine.org/Filenames_with_spaces_are_truncated_upon_download
      */
     header('Content-Type: ' . $type);
     header('Content-Disposition: inline; filename=' . $basename);
     header('Content-Transfer-Encoding: binary');
     header('Content-Length: ' . $length);
     /**
      * issue fixes for IE6,7,8  when downloading a file over HTTPS (http://support.microsoft.com/kb/812935)
      * http://www.dotvoid.com/2009/10/problem-with-downloading-files-with-internet-explorer-over-https/
      */
     if (Director::is_https()) {
         header('Pragma: ');
     }
     header('Expires: 0');
     header('Cache-Control: must-revalidate');
     /**
      * unload the php session file
      * see http://konrness.com/php5/how-to-prevent-blocking-php-requests
      */
     session_write_close();
     // if output buffering is active, we clear it to prevent the script from trying to to allocate memory for entire file.
     while (ob_get_level() > 0) {
         ob_end_clean();
     }
     flush();
     readfile($path);
     exit(0);
 }
 public function tearDown()
 {
     // Preserve memory settings
     ini_set('memory_limit', $this->originalMemoryLimit ? $this->originalMemoryLimit : -1);
     // Restore email configuration
     $this->originalMailer = null;
     $this->mailer = null;
     // Restore password validation
     if ($this->originalMemberPasswordValidator) {
         Member::set_password_validator($this->originalMemberPasswordValidator);
     }
     // Restore requirements
     if ($this->originalRequirements) {
         Requirements::set_backend($this->originalRequirements);
     }
     // Mark test as no longer being run - we use originalIsRunningTest to allow for nested SapphireTest calls
     self::$is_running_test = $this->originalIsRunningTest;
     $this->originalIsRunningTest = null;
     // Reset mocked datetime
     DBDatetime::clear_mock_now();
     // Stop the redirection that might have been requested in the test.
     // Note: Ideally a clean Controller should be created for each test.
     // Now all tests executed in a batch share the same controller.
     $controller = Controller::has_curr() ? Controller::curr() : null;
     if ($controller && $controller->response && $controller->response->getHeader('Location')) {
         $controller->response->setStatusCode(200);
         $controller->response->removeHeader('Location');
     }
     Versioned::set_reading_mode($this->originalReadingMode);
     //unnest injector / config now that tests are over
     Injector::unnest();
     Config::unnest();
 }
 /**
  * See {@link combine_files()}
  *
  */
 function process_combined_files()
 {
     // The class_exists call prevents us from loading SapphireTest.php (slow) just to know that
     // SapphireTest isn't running :-)
     if (class_exists('SapphireTest', false)) {
         $runningTest = SapphireTest::is_running_test();
     } else {
         $runningTest = false;
     }
     if (Director::isDev() && !$runningTest || !$this->combined_files_enabled) {
         return;
     }
     // Make a map of files that could be potentially combined
     $combinerCheck = array();
     foreach ($this->combine_files as $combinedFile => $sourceItems) {
         foreach ($sourceItems as $sourceItem) {
             if (isset($combinerCheck[$sourceItem]) && $combinerCheck[$sourceItem] != $combinedFile) {
                 user_error("Requirements_Backend::process_combined_files - file '{$sourceItem}' appears in two combined files:" . " '{$combinerCheck[$sourceItem]}' and '{$combinedFile}'", E_USER_WARNING);
             }
             $combinerCheck[$sourceItem] = $combinedFile;
         }
     }
     // Work out the relative URL for the combined files from the base folder
     $combinedFilesFolder = $this->getCombinedFilesFolder() ? $this->getCombinedFilesFolder() . '/' : '';
     // Figure out which ones apply to this pageview
     $combinedFiles = array();
     $newJSRequirements = array();
     $newCSSRequirements = array();
     foreach ($this->javascript as $file => $dummy) {
         if (isset($combinerCheck[$file])) {
             $newJSRequirements[$combinedFilesFolder . $combinerCheck[$file]] = true;
             $combinedFiles[$combinerCheck[$file]] = true;
         } else {
             $newJSRequirements[$file] = true;
         }
     }
     foreach ($this->css as $file => $params) {
         if (isset($combinerCheck[$file])) {
             $newCSSRequirements[$combinedFilesFolder . $combinerCheck[$file]] = true;
             $combinedFiles[$combinerCheck[$file]] = true;
         } else {
             $newCSSRequirements[$file] = $params;
         }
     }
     // Process the combined files
     $base = Director::baseFolder() . '/';
     foreach (array_diff_key($combinedFiles, $this->blocked) as $combinedFile => $dummy) {
         $fileList = $this->combine_files[$combinedFile];
         $combinedFilePath = $base . $combinedFilesFolder . '/' . $combinedFile;
         // Make the folder if necessary
         if (!file_exists(dirname($combinedFilePath))) {
             Filesystem::makeFolder(dirname($combinedFilePath));
         }
         // If the file isn't writebale, don't even bother trying to make the combined file
         // Complex test because is_writable fails if the file doesn't exist yet.
         if (file_exists($combinedFilePath) && !is_writable($combinedFilePath) || !file_exists($combinedFilePath) && !is_writable(dirname($combinedFilePath))) {
             user_error("Requirements_Backend::process_combined_files(): Couldn't create '{$combinedFilePath}'", E_USER_WARNING);
             continue;
         }
         // Determine if we need to build the combined include
         if (file_exists($combinedFilePath) && !isset($_GET['flush'])) {
             // file exists, check modification date of every contained file
             $srcLastMod = 0;
             foreach ($fileList as $file) {
                 $srcLastMod = max(filemtime($base . $file), $srcLastMod);
             }
             $refresh = $srcLastMod > filemtime($combinedFilePath);
         } else {
             // file doesn't exist, or refresh was explicitly required
             $refresh = true;
         }
         if (!$refresh) {
             continue;
         }
         $combinedData = "";
         foreach (array_diff($fileList, $this->blocked) as $file) {
             $fileContent = file_get_contents($base . $file);
             // if we have a javascript file and jsmin is enabled, minify the content
             $isJS = stripos($file, '.js');
             if ($isJS && $this->combine_js_with_jsmin) {
                 require_once 'thirdparty/jsmin/jsmin.php';
                 increase_time_limit_to();
                 $fileContent = JSMin::minify($fileContent);
             }
             // write a header comment for each file for easier identification and debugging
             // also the semicolon between each file is required for jQuery to be combinable properly
             $combinedData .= "/****** FILE: {$file} *****/\n" . $fileContent . "\n" . ($isJS ? ';' : '') . "\n";
         }
         $successfulWrite = false;
         $fh = fopen($combinedFilePath, 'wb');
         if ($fh) {
             if (fwrite($fh, $combinedData) == strlen($combinedData)) {
                 $successfulWrite = true;
             }
             fclose($fh);
             unset($fh);
         }
         // Unsuccessful write - just include the regular JS files, rather than the combined one
         if (!$successfulWrite) {
             user_error("Requirements_Backend::process_combined_files(): Couldn't create '{$combinedFilePath}'", E_USER_WARNING);
             continue;
         }
     }
     // @todo Alters the original information, which means you can't call this
     // method repeatedly - it will behave different on the second call!
     $this->javascript = $newJSRequirements;
     $this->css = $newCSSRequirements;
 }
示例#28
0
 /**
  * Support function for backwards compatibility purposes.
  * Caution: Volatile API, might be removed in 3.1 or later.
  *
  * @param  String $tabname Path to a tab, e.g. "Root.Content.Main"
  * @return String Rewritten path, based on {@link tabPathRewrites}
  */
 protected function rewriteTabPath($name)
 {
     $isRunningTest = class_exists('SapphireTest', false) && SapphireTest::is_running_test();
     foreach ($this->getTabPathRewrites() as $regex => $replace) {
         if (preg_match($regex, $name)) {
             $newName = preg_replace($regex, $replace, $name);
             Deprecation::notice('3.0.0', sprintf('Using outdated tab path "%s", please use the new location "%s" instead', $name, $newName), Deprecation::SCOPE_GLOBAL);
             return $newName;
         }
     }
     // No match found, return original path
     return $name;
 }
 /**
  * Force the site to run on SSL.
  *
  * To use, call from _config.php. For example:
  * <code>
  * if (Director::isLive()) Director::forceSSL();
  * </code>
  *
  * If you don't want your entire site to be on SSL, you can pass an array of PCRE regular expression
  * patterns for matching relative URLs. For example:
  * <code>
  * if (Director::isLive()) Director::forceSSL(array('/^admin/', '/^Security/'));
  * </code>
  *
  * If you want certain parts of your site protected under a different domain, you can specify
  * the domain as an argument:
  * <code>
  * if (Director::isLive()) Director::forceSSL(array('/^admin/', '/^Security/'), 'secure.mysite.com');
  * </code>
  *
  * Note that the session data will be lost when moving from HTTP to HTTPS. It is your responsibility
  * to ensure that this won't cause usability problems.
  *
  * CAUTION: This does not respect the site environment mode. You should check this
  * as per the above examples using Director::isLive() or Director::isTest() for example.
  *
  * @param array $patterns Array of regex patterns to match URLs that should be HTTPS.
  * @param string $secureDomain Secure domain to redirect to. Defaults to the current domain.
  *
  * @return bool|string String of URL when unit tests running, boolean FALSE if patterns don't match request URI.
  */
 public static function forceSSL($patterns = null, $secureDomain = null)
 {
     if (!isset($_SERVER['REQUEST_URI'])) {
         return false;
     }
     $matched = false;
     if ($patterns) {
         // Calling from the command-line?
         if (!isset($_SERVER['REQUEST_URI'])) {
             return;
         }
         $relativeURL = self::makeRelative(Director::absoluteURL($_SERVER['REQUEST_URI']));
         // protect portions of the site based on the pattern
         foreach ($patterns as $pattern) {
             if (preg_match($pattern, $relativeURL)) {
                 $matched = true;
                 break;
             }
         }
     } else {
         // protect the entire site
         $matched = true;
     }
     if ($matched && !self::is_https()) {
         // if an domain is specified, redirect to that instead of the current domain
         if ($secureDomain) {
             $url = 'https://' . $secureDomain . $_SERVER['REQUEST_URI'];
         } else {
             $url = $_SERVER['REQUEST_URI'];
         }
         $destURL = str_replace('http:', 'https:', Director::absoluteURL($url));
         // This coupling to SapphireTest is necessary to test the destination URL and to not interfere with tests
         if (class_exists('SapphireTest', false) && SapphireTest::is_running_test()) {
             return $destURL;
         } else {
             self::force_redirect($destURL);
         }
     } else {
         return false;
     }
 }
 function bulkimport($data, $form)
 {
     $fh = fopen($data['SourceFile']['tmp_name'], 'r');
     Versioned::reading_stage('Stage');
     if (isset($data['DeleteExisting']) && $data['DeleteExisting']) {
         foreach (Page::get() as $page) {
             $page->deleteFromStage('Stage');
             $page->deleteFromStage('Live');
         }
     }
     $parentRefs = array();
     while ($line = fgets($fh, 10000)) {
         // Skip comments
         if (preg_match('/^#/', $line)) {
             continue;
         }
         // Split up indentation, title and optional JSON
         if (preg_match("/^(\t*)([^{]*)({.*})?/", $line, $matches)) {
             $numTabs = strlen($matches[1]);
             $title = trim($matches[2]);
             $json = isset($matches[3]) && trim($matches[3]) ? json_decode(trim($matches[3]), true) : array();
             // Either extract the URL from provided meta data, or generate it
             $url = array_key_exists('URLSegment', $json) ? $json['URLSegment'] : $title;
             $url = Convert::raw2url($url);
             // Allow custom classes based on meta data
             $className = array_key_exists('ClassName', $json) ? $json['ClassName'] : 'Page';
             // If we've got too many tabs, then outdent until we find a page to attach to.
             while (!isset($parentRefs[$numTabs - 1]) && $numTabs > 0) {
                 $numTabs--;
             }
             $parentID = $numTabs > 0 ? $parentRefs[$numTabs - 1] : 0;
             // Try to find an existing page, or create a new one
             $page = Page::get()->filter(array('URLSegment' => $url, 'ParentID' => $parentID))->First();
             if (!$page) {
                 $page = new $className();
             }
             // Apply any meta data properties to the page
             $page->ParentID = $parentID;
             $page->Title = $title;
             $page->URLSegment = $url;
             if ($json) {
                 $page->update($json);
             }
             $page->write();
             // Optionall publish
             if (isset($data['PublishAll']) && $data['PublishAll']) {
                 $page->publish('Stage', 'Live');
             }
             if (!SapphireTest::is_running_test()) {
                 echo "<li>Written ID# {$page->ID}: {$page->Title}";
                 if ($page->ParentID) {
                     echo " (ParentID# {$page->ParentID})";
                 }
                 echo "</li>";
             }
             // Populate parentRefs with the most recent page at every level.   Necessary to build tree
             // Children of home should be placed at the top level
             if (strtolower($title) == 'home') {
                 $parentRefs[$numTabs] = 0;
             } else {
                 $parentRefs[$numTabs] = $page->ID;
             }
             // Remove no-longer-relevant children from the parentRefs.  Allows more graceful acceptance of files
             // with errors
             for ($i = sizeof($parentRefs) - 1; $i > $numTabs; $i--) {
                 unset($parentRefs[$i]);
             }
             // Memory cleanup
             $page->destroy();
             unset($page);
         }
     }
     if (!SapphireTest::is_running_test()) {
         $complete = $this->complete();
         echo $complete['Content'];
     } else {
         $this->redirect($this->Link() . 'complete');
     }
 }