mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge 3.1 into 3.2
Conflicts: admin/javascript/LeftAndMain.js control/HTTPRequest.php docs/en/00_Getting_Started/00_Server_Requirements.md
This commit is contained in:
commit
a0812f987a
@ -176,7 +176,7 @@ jQuery.noConflict();
|
||||
var msg = (xhr.getResponseHeader('X-Status')) ? xhr.getResponseHeader('X-Status') : xhr.statusText,
|
||||
reathenticate = xhr.getResponseHeader('X-Reauthenticate'),
|
||||
msgType = (xhr.status < 200 || xhr.status > 399) ? 'bad' : 'good',
|
||||
ignoredMessages = ['OK'];
|
||||
ignoredMessages = ['OK', 'success'];
|
||||
|
||||
// Enable reauthenticate dialog if requested
|
||||
if(reathenticate) {
|
||||
@ -911,8 +911,11 @@ jQuery.noConflict();
|
||||
sessionStates = sessionData ? JSON.parse(sessionData) : false;
|
||||
|
||||
this.find('.cms-tabset, .ss-tabset').each(function() {
|
||||
var index, tabset = $(this), tabsetId = tabset.attr('id'), tab,
|
||||
forcedTab = tabset.find('.ss-tabs-force-active');
|
||||
var index,
|
||||
tabset = $(this),
|
||||
tabsetId = tabset.attr('id'),
|
||||
tab,
|
||||
forcedTab = tabset.children('ul').children('li.ss-tabs-force-active');
|
||||
|
||||
if(!tabset.data('tabs')){
|
||||
return; // don't act on uninit'ed controls
|
||||
@ -921,18 +924,18 @@ jQuery.noConflict();
|
||||
// The tabs may have changed, notify the widget that it should update its internal state.
|
||||
tabset.tabs('refresh');
|
||||
|
||||
// Make sure the intended tab is selected.
|
||||
// Make sure the intended tab is selected. Only force the tab on the correct tabset though
|
||||
if(forcedTab.length) {
|
||||
index = forcedTab.index();
|
||||
index = forcedTab.first().index();
|
||||
} else if(overrideStates && overrideStates[tabsetId]) {
|
||||
tab = tabset.find(overrideStates[tabsetId].tabSelector);
|
||||
if(tab.length){
|
||||
index = tab.index();
|
||||
}
|
||||
} else if(sessionStates) {
|
||||
$.each(sessionStates, function(i, sessionState) {
|
||||
if(tabset.is('#' + sessionState.id)){
|
||||
index = sessionState.selected;
|
||||
$.each(sessionStates, function(i, state) {
|
||||
if(tabsetId == state.id){
|
||||
index = state.selected;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -671,7 +671,7 @@ class SS_HTTPRequest implements ArrayAccess {
|
||||
}
|
||||
|
||||
if ($headerOverrideIP) {
|
||||
return $headerOverrideIP;
|
||||
return $this->getIPFromHeaderValue($headerOverrideIP);
|
||||
} elseif(isset($_SERVER['REMOTE_ADDR'])) {
|
||||
return $_SERVER['REMOTE_ADDR'];
|
||||
} else {
|
||||
@ -679,6 +679,28 @@ class SS_HTTPRequest implements ArrayAccess {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract an IP address from a header value that has been obtained. Accepts single IP or comma separated string of
|
||||
* IPs
|
||||
*
|
||||
* @param string $headerValue The value from a trusted header
|
||||
* @return string The IP address
|
||||
*/
|
||||
protected function getIPFromHeaderValue($headerValue) {
|
||||
if (strpos($headerValue, ',') !== false) {
|
||||
//sometimes the IP from a load balancer could be "x.x.x.x, y.y.y.y, z.z.z.z" so we need to find the most
|
||||
// likely candidate
|
||||
$ips = explode(',', $headerValue);
|
||||
foreach ($ips as $ip) {
|
||||
$ip = trim($ip);
|
||||
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) {
|
||||
return $ip;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $headerValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all mimetypes from the HTTP "Accept" header
|
||||
* as an array.
|
||||
|
@ -67,9 +67,21 @@ class ErrorControlChain {
|
||||
$this->error = (bool)$error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether errors are suppressed or not
|
||||
* Notes:
|
||||
* - Errors cannot be suppressed if not handling errors.
|
||||
* - Errors cannot be un-suppressed if original mode dis-allowed visible errors
|
||||
*
|
||||
* @param bool $suppression
|
||||
*/
|
||||
public function setSuppression($suppression) {
|
||||
$this->suppression = (bool)$suppression;
|
||||
if ($this->handleFatalErrors) ini_set('display_errors', !$suppression);
|
||||
// Don't modify errors unless handling fatal errors, and if errors were
|
||||
// originally allowed to be displayed.
|
||||
if ($this->handleFatalErrors && $this->originalDisplayErrors) {
|
||||
ini_set('display_errors', !$suppression);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,7 +179,7 @@ class ErrorControlChain {
|
||||
$this->handleFatalErrors = true;
|
||||
|
||||
$this->originalDisplayErrors = ini_get('display_errors');
|
||||
ini_set('display_errors', !$this->suppression);
|
||||
$this->setSuppression($this->suppression);
|
||||
|
||||
$this->step();
|
||||
}
|
||||
|
@ -194,8 +194,8 @@ class ParameterConfirmationToken {
|
||||
$_SERVER['HTTP_HOST'],
|
||||
// SilverStripe base
|
||||
self::$alternateBaseURL !== null ? self::$alternateBaseURL : BASE_URL,
|
||||
// And URL
|
||||
$url
|
||||
// And URL including base script (eg: if it's index.php/page/url/)
|
||||
(defined('BASE_SCRIPT_URL') ? '/' . BASE_SCRIPT_URL : '') . $url,
|
||||
));
|
||||
|
||||
// Join together with protocol into our current absolute URL, avoiding duplicated "/" characters
|
||||
|
@ -10,10 +10,10 @@
|
||||
*
|
||||
* <code>
|
||||
* $parser = new CSVParser('myfile.csv');
|
||||
* $parser->mapColumns(
|
||||
* $parser->mapColumns(array(
|
||||
* 'first name' => 'FirstName'
|
||||
* 'lastname' => 'Surname',
|
||||
* 'last name' => 'Surname'
|
||||
* 'last name' => 'Surname',
|
||||
* ));
|
||||
* foreach($parser as $row) {
|
||||
* // $row is a map of column name => column value
|
||||
|
@ -8,7 +8,7 @@ Our web-based [PHP installer](installation/) can check if you meet the requireme
|
||||
|
||||
## Web server software requirements
|
||||
|
||||
* PHP 5.3.3+
|
||||
* PHP 5.3.3+, <7
|
||||
* We recommend using a PHP accelerator or opcode cache, such as [xcache](http://xcache.lighttpd.net/) or [WinCache](http://www.iis.net/download/wincacheforphp).
|
||||
* Allocate at least 48MB of memory to each PHP process. (SilverStripe can be resource hungry for some intensive operations.)
|
||||
* Required modules: dom, gd2, fileinfo, hash, iconv, mbstring, mysqli (or other database driver), session, simplexml, tokenizer, xml.
|
||||
@ -23,7 +23,7 @@ Our web-based [PHP installer](installation/) can check if you meet the requireme
|
||||
* MySQL 5.0+
|
||||
* PostgreSQL 8.3+ (requires ["postgresql" module](http://silverstripe.org/postgresql-module))
|
||||
* SQL Server 2008+ (requires ["mssql" module](http://silverstripe.org/microsoft-sql-server-database/))
|
||||
* Support for `[Oracle](http://www.silverstripe.org/oracle-database-module/)` and [SQLite](http://silverstripe.org/sqlite-database/) is not commercially supported, but is under development by our open source community.
|
||||
* Support for [Oracle](http://www.silverstripe.org/oracle-database-module/) and [SQLite](http://silverstripe.org/sqlite-database/) is not commercially supported, but is under development by our open source community.
|
||||
* One of the following web server products:
|
||||
* Apache 2.0+ with mod_rewrite and "AllowOverride All" set
|
||||
* IIS 7+
|
||||
@ -34,6 +34,11 @@ Our web-based [PHP installer](installation/) can check if you meet the requireme
|
||||
* Microsoft Windows XP SP3, Vista, Windows 7, Server 2008, Server 2008 R2
|
||||
* Mac OS X 10.4+
|
||||
|
||||
### Why doesn't SilverStripe 3 work with PHP 7?
|
||||
Unfortunately, SilverStripe has classes named the same as PHP reserved words, such as "Int" and "Float". This means that
|
||||
we are unable to make SilverStripe 3 support PHP 7 without breaking backward compatibility. SilverStripe 4 will work
|
||||
with PHP 7 and will be released in 2016. Until then, we recommend that you use PHP 5.6.
|
||||
|
||||
## Web server hardware requirements
|
||||
|
||||
Hardware requirements vary widely depending on the traffic to your website, the complexity of its logic (i.e., PHP), and
|
||||
|
@ -30,7 +30,7 @@ directly calling methods that they shouldn't.
|
||||
'cmsrestrictedaction' => 'CMS_ACCESS_CMSMain',
|
||||
|
||||
// complexaction can only be accessed if $this->canComplexAction() returns true.
|
||||
'complexaction' '->canComplexAction'
|
||||
'complexaction' => '->canComplexAction',
|
||||
|
||||
// complexactioncheck can only be accessed if $this->canComplexAction("MyRestrictedAction", false, 42) is true.
|
||||
'complexactioncheck' => '->canComplexAction("MyRestrictedAction", false, 42)',
|
||||
@ -200,4 +200,4 @@ execution. This behavior can be used to implement permission checks.
|
||||
|
||||
## API Documentation
|
||||
|
||||
* [api:Controller]
|
||||
* [api:Controller]
|
||||
|
@ -254,4 +254,23 @@ class HTTPRequestTest extends SapphireTest {
|
||||
$this->assertEquals('home?test=1', $req->getURL(true));
|
||||
$this->assertEquals('home', $req->getURL());
|
||||
}
|
||||
|
||||
public function testGetIPFromHeaderValue() {
|
||||
$req = new SS_HTTPRequest('GET', '/');
|
||||
$reflectionMethod = new ReflectionMethod($req, 'getIPFromHeaderValue');
|
||||
$reflectionMethod->setAccessible(true);
|
||||
|
||||
$headers = array(
|
||||
'80.79.208.21, 149.126.76.1, 10.51.0.68' => '80.79.208.21',
|
||||
'52.19.19.103, 10.51.0.49' => '52.19.19.103',
|
||||
'10.51.0.49, 52.19.19.103' => '52.19.19.103',
|
||||
'10.51.0.49' => '10.51.0.49',
|
||||
'127.0.0.1, 10.51.0.49' => '127.0.0.1',
|
||||
);
|
||||
|
||||
foreach ($headers as $header => $ip) {
|
||||
$this->assertEquals($ip, $reflectionMethod->invoke($req, $header));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,11 @@ require_once '$classpath';
|
||||
|
||||
class ErrorControlChainTest extends SapphireTest {
|
||||
|
||||
protected $displayErrors = null;
|
||||
|
||||
function setUp() {
|
||||
$this->displayErrors = (bool)ini_get('display_errors');
|
||||
|
||||
// Check we can run PHP at all
|
||||
$null = is_writeable('/dev/null') ? '/dev/null' : 'NUL';
|
||||
exec("php -v 2> $null", $out, $rv);
|
||||
@ -76,8 +80,48 @@ class ErrorControlChainTest extends SapphireTest {
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
if($this->displayErrors !== null) {
|
||||
ini_set('display_errors', $this->displayErrors);
|
||||
$this->displayErrors = null;
|
||||
}
|
||||
parent::tearDown(); // TODO: Change the autogenerated stub
|
||||
}
|
||||
|
||||
function testErrorSuppression() {
|
||||
|
||||
// Errors disabled by default
|
||||
ini_set('display_errors', false);
|
||||
$chain = new ErrorControlChain();
|
||||
$whenNotSuppressed = null;
|
||||
$whenSuppressed = null;
|
||||
$chain->then(function($chain) use(&$whenNotSuppressed, &$whenSuppressed) {
|
||||
$chain->setSuppression(true);
|
||||
$whenSuppressed = ini_get('display_errors');
|
||||
$chain->setSuppression(false);
|
||||
$whenNotSuppressed = ini_get('display_errors');
|
||||
})->execute();
|
||||
|
||||
// Disabled errors never un-disable
|
||||
$this->assertFalse((bool)$whenNotSuppressed);
|
||||
$this->assertFalse((bool)$whenSuppressed);
|
||||
|
||||
// Errors enabled by default
|
||||
ini_set('display_errors', true);
|
||||
$chain = new ErrorControlChain();
|
||||
$whenNotSuppressed = null;
|
||||
$whenSuppressed = null;
|
||||
$chain->then(function($chain) use(&$whenNotSuppressed, &$whenSuppressed) {
|
||||
$chain->setSuppression(true);
|
||||
$whenSuppressed = ini_get('display_errors');
|
||||
$chain->setSuppression(false);
|
||||
$whenNotSuppressed = ini_get('display_errors');
|
||||
})->execute();
|
||||
|
||||
// Errors can be suppressed an un-suppressed when initially enabled
|
||||
$this->assertTrue((bool)$whenNotSuppressed);
|
||||
$this->assertFalse((bool)$whenSuppressed);
|
||||
|
||||
// Fatal error
|
||||
|
||||
$chain = new ErrorControlChainTest_Chain();
|
||||
|
Loading…
Reference in New Issue
Block a user