diff --git a/admin/code/CMSProfileController.php b/admin/code/CMSProfileController.php index ae5a525c0..c5ae65888 100644 --- a/admin/code/CMSProfileController.php +++ b/admin/code/CMSProfileController.php @@ -59,7 +59,13 @@ class CMSProfileController extends LeftAndMain { if(!$member) return $this->httpError(404); $origLocale = $member->Locale; + if(!$member->canEdit()) { + $form->sessionMessage(_t('Member.CANTEDIT', 'You don\'t have permission to do that'), 'bad'); + return $this->controller->redirectBack(); + } + $response = parent::save($data, $form); + if($origLocale != $data['Locale']) { $response->addHeader('X-Reload', true); $response->addHeader('X-ControllerURL', $this->Link()); diff --git a/admin/css/ie7.css b/admin/css/ie7.css index fce4e75bb..9281a3f44 100644 --- a/admin/css/ie7.css +++ b/admin/css/ie7.css @@ -99,3 +99,6 @@ table.ss-gridfield-table tr.ss-gridfield-item.even { background: #F0F4F7; } .cms-content-header .cms-content-header-tabs { position: absolute; right: 0; } .ss-ui-button.ss-gridfield-button-filter { border: none !important; } + +.cms-panel-content-collapsed { position: relative; width: 40px; } +.cms-panel-content-collapsed h2.cms-panel-header, .cms-panel-content-collapsed h3.cms-panel-header { zoom: 1; position: absolute; top: 10px; right: 10px; writing-mode: tb-rl; float: right; z-index: 5000; } diff --git a/admin/scss/_style.scss b/admin/scss/_style.scss index 08f35c5e8..06fb95dd4 100644 --- a/admin/scss/_style.scss +++ b/admin/scss/_style.scss @@ -1838,8 +1838,15 @@ form.import-form { } } - .ss-tabset .ui-tabs-panel { - background: darken($color-widget-bg, 2%); + .ui-tabs-nav ~ .ui-tabs-panel { + background: darken($color-widget-bg, 2%); + border-top:1px solid $color-button-generic-border; + clear: both; + } + + &.ss-tabset-tabshidden .ui-tabs-panel { + border-top: none; + } } } } diff --git a/admin/scss/ie7.scss b/admin/scss/ie7.scss index 73a35d75e..35b4ef52f 100644 --- a/admin/scss/ie7.scss +++ b/admin/scss/ie7.scss @@ -218,3 +218,5 @@ table.ss-gridfield-table { border:none !important; } } + +@include IEVerticalPanelText; diff --git a/docs/en/changelogs/2.4.8.md b/docs/en/changelogs/2.4.8.md new file mode 100644 index 000000000..d64c3531b --- /dev/null +++ b/docs/en/changelogs/2.4.8.md @@ -0,0 +1,42 @@ +# 2.4.8 (2012-10-30) # + +## Overview ## + + * Security (Moderate Severity): More solid relative/site URL checks (related to "BackURL" redirection). + * Security (Moderate Severity): Ensure javascript content type is sent in form responses. If content type is html, and the javascript contains script tags within the content, this content will be executed. + * Security (Low Severity): Fixed remote code execution vuln in install.php due to inserting unescaped user data into mysite/_config.php. Not critical because install.php is required to be removed on a SilverStripe installation anyway + +## Details + +### API Changes + + * 2012-02-01 [bf4476a](https://github.com/silverstripe/sapphire/commit/bf4476a) silverstripe_version file now contains the plain version number, rather than an SVN path (Ingo Schommer) + * 2012-02-01 [4abe136](https://github.com/silverstripe/silverstripe-cms/commit/4abe136) silverstripe_version file now contains the plain version number, rather than an SVN path (Ingo Schommer) + +### Features and Enhancements + + * 2012-02-03 [921bf9a](https://github.com/silverstripe/sapphire/commit/921bf9a) Ensure that forceSSL and protocol detection respects the X-Forwarded-Protocol header. (Sam Minnee) + +### Bugfixes + + * 2012-09-14 [8ec6312](https://github.com/silverstripe/sapphire/commit/8ec6312) to prevent unintended results from getComponentsQuery(...) (stozze) + * 2012-07-09 [838ac97](https://github.com/silverstripe/silverstripe-cms/commit/838ac97) fixing an edge-case bug where a 404-page would get statically published and overwrite the homepage of the site (this would sometimes happen when a RedirectorPage was set to an external URL and still referenced an internal page ID) (Julian Seidenberg) + * 2012-05-04 [392543b](https://github.com/silverstripe/sapphire/commit/392543b) Don't' set 'Referer' header in FunctionalTest->get()/post() if its explicitly passed to the method (Ingo Schommer) + +### Minor changes + + * 2012-08-15 [7669871](https://github.com/silverstripe/sapphire/commit/7669871) fixed array to string conversion to avoid PHP 5.4 warnings (Adam Skrzypulec) + * 2012-05-29 [039a372](https://github.com/silverstripe/silverstripe-installer/commit/039a372) Fixed phpunit bootstrap relative path (Ingo Schommer) + * 2012-05-14 [b211c38](https://github.com/silverstripe/sapphire/commit/b211c38) Manually testing exceptions in SSViewerCacheBlockTest to avoid PHPUnit 3.6 warnings (Ingo Schommer) + * 2012-03-30 [c1d2cd1](https://github.com/silverstripe/sapphire/commit/c1d2cd1) Corrected Geoip entries for ex-Yugoslavia ... better late than never (Ingo Schommer) + * 2012-03-14 [44b9d05](https://github.com/silverstripe/sapphire/commit/44b9d05) Backported bootstrap.php changes from master and cstom TeamCity configuration (required to run tests through phpunit binary) (Ingo Schommer) + * 2011-12-17 [af22d07](https://github.com/silverstripe/sapphire/commit/af22d07) On PHPUnit 3.6, show the output of tests. (Sam Minnee) + * 2011-11-08 [5956ad8](https://github.com/silverstripe/sapphire/commit/5956ad8) Amended PHPUnit execution to work with PHPUnit 3.6 (Sam Minnee) + +### Other + + * 2012-10-05 [1c7b7d0](https://github.com/silverstripe/sapphire/commit/1c7b7d0) Fixed grammatical error for Form.FIELDISREQUIRED (Will Morgan) + * 2012-08-08 [f6c69d5](https://github.com/silverstripe/sapphire/commit/f6c69d5) Update widget documentation (fixes #706) (Will Rossiter) + * 2012-05-16 [b7c8737](https://github.com/silverstripe/silverstripe-installer/commit/b7c8737) SECURITY Fixed remote code execution vuln in install.php due to inserting unescaped user data into mysite/_config.php. Not critical because install.php is required to be removed on a SilverStripe installation anyway (fixes #7205) (Ingo Schommer) + * 2012-05-04 [46064f8](https://github.com/silverstripe/sapphire/commit/46064f8) SECURITY More solid relative/site URL checks (related to "BackURL" redirection) (Ingo Schommer) + * 2012-05-03 [9bf3ae9](https://github.com/silverstripe/sapphire/commit/9bf3ae9) SECURITY: Ensure javascript content type is sent in form responses. If content type is html, and the javascript contains script tags within the content, this content will be executed. (Andrew O'Neil) \ No newline at end of file diff --git a/docs/en/changelogs/3.0.0.md b/docs/en/changelogs/3.0.0.md index edc290af0..7d11106ca 100644 --- a/docs/en/changelogs/3.0.0.md +++ b/docs/en/changelogs/3.0.0.md @@ -27,7 +27,7 @@ The detailed change logs are broken down by pre-release: * [3.0.0-rc3](/changelogs/rc/3.0.0-rc3) - 27 June 2012 - * [3.0.0-rc2](changelogs/rc/3.0.0-rc2) - 26 June 2012 + * [3.0.0-rc2](/changelogs/rc/3.0.0-rc2) - 26 June 2012 * [3.0.0-rc1](/changelogs/rc/3.0.0-rc1) - 18 June 2012 * [3.0.0-beta3](/changelogs)/beta/3.0.0-beta3) - 28 May 2012 * [3.0.0-beta2](/changelogs/beta/3.0.0-beta2) - 20 April 2012 @@ -40,15 +40,15 @@ The detailed change logs are broken down by pre-release: ### Common Upgrade Tasks - * Rename foder from `sapphire/`to `framework/`, replace own paths with `FRAMEWORK_DIR` (in PHP) or `$ModulePath(framework)` (in templates). Update paths in `.htaccess` or `web.config` ([more](#sapphire-rename)) + * Rename foder from `sapphire/`to `framework/`, replace own paths with `FRAMEWORK_DIR` (in PHP) or `$ModulePath(framework)` (in templates). Update paths in `.htaccess` or `web.config` ([more](/changelogs/3.0.0#sapphire-rename)) * Replace `<% control %>` in your templates with `<% loop %>` and `<% with %>` ([more](/reference/templates-upgrading-guide#control)) - * Replace `DataObjectSet` with `DataList` or `ArrayList` ([more](#deprecated-classes)) - * Rewrite `ComplexTableField` and `DataObjectManager` instances to `GridField` - * Rewrite `Director::redirect()` and `Director::redirectBack()` calls ([more] (#director-static-functions-deprecated-director-redirect-and-director-redirectback-in-particular) - * Use `::get()` rather than `DataObject::get()` ([more](#new-orm-datalist)) - * Use new syntax for `DataObjectDecorator::extraStatics` ([more](#extensions)) - * Change CMS tab paths from `Root.Content.Main` to `Root.Main`, move some field changes to new `SiteTree->getSettingsFields()` method ([more](#tab-paths)) - * Add new modules if using specific core features like Widget, RestfulServer, PageComment or Translatable + * Replace `DataObjectSet` with `DataList` or `ArrayList` ([more](/changelogs/3.0.0#deprecated-classes)) + * Rewrite `ComplexTableField` and `DataObjectManager` instances to `GridField` ([more](/changelogs/3.0.0#gridfield-replacement-for-tablelistfield-and-complextablefield-gridfield)) + * Rewrite `Director::redirect()` and `Director::redirectBack()` calls ([more](/changelogs/3.0.0#director-static-functions-deprecated-e-g-redirect-and-redirectback) + * Use `::get()` rather than `DataObject::get()` ([more](/changelogs/3.0.0#new-orm-datalist)) + * Use new syntax for `DataObjectDecorator::extraStatics` ([more](/changelogs/3.0.0#extensions)) + * Change CMS tab paths from `Root.Content.Main` to `Root.Main`, move some field changes to new `SiteTree->getSettingsFields()` method ([more](/changelogs/3.0.0#tab-paths)) + * Add new modules if using specific core features like Widget, RestfulServer, PageComment or Translatable ([more](/changelogs/3.0.0#moved-widget-api-into-new-widgets-module-widgets)) ### sapphire renamed to framework {#sapphire-rename} @@ -215,7 +215,7 @@ for the presence of records, please call the count() method on the `DataList`: if(!DataObject::get('SiteTree', '"ParentID" = 5')->count()) echo "Page 5 has no children"; Beware that `DataList->remove()` will delete an entry from the database. -See the ["datamodel" documentation](../../topics/datamodel) for more details. +See the ["datamodel" documentation](../topics/datamodel) for more details. ### New ORM: Changes to manipulation of SQL queries {#new-orm-sql-queries} @@ -354,7 +354,7 @@ the detailed changelog for this release. Many interface components have changed unfortunately there is no clear upgrade path for every interface detail. As a starting point, have a look at the new templates in `cms/templates` and `framework/admin/templates`, as well as the new [jQuery.entwine](https://github.com/hafriedlander/jquery.entwine) -based JavaScript logic. Have a look at the new ["Extending the CMS" guide](../howto/extending-the-cms), +based JavaScript logic. Have a look at the new ["Extending the CMS" guide](../howto/extend-cms-interface), ["CSS" guide](../topics/css), ["JavaScript" guide](../topics/javascript) and ["CMS Architecture" guide](/reference/cms-architecture) to get you started. @@ -477,7 +477,7 @@ as well as the HTML form element itself.
- + After (abbreviated):
@@ -569,11 +569,11 @@ You can now call the `_t()` function in both templates and code with a namespace The new syntax supports injecting variables into the translation. For example: :::php - _t( + _t( 'i18nTestModule.INJECTIONS2', "Hello {name} {greeting}", array("name"=>"Paul", "greeting"=>"good you are here") - ); + ); We've written the injection logic in a way that keeps backwards compatible with existing translations. This means that you can migrate from `sprintf()` to the new injection diff --git a/docs/en/reference/urlvariabletools.md b/docs/en/reference/urlvariabletools.md index 8ff6bf29e..561dadaac 100644 --- a/docs/en/reference/urlvariabletools.md +++ b/docs/en/reference/urlvariabletools.md @@ -3,7 +3,7 @@ ## Introduction This page lists a number of "page options" , "rendering tools" or "special URL variables" that you can use to debug your -SilverStruoe applications. These are consumed in PHP using the $_REQUEST or $_GET super globals throughout the SilverStripe +SilverStripe applications. These are consumed in PHP using the $_REQUEST or $_GET superglobals throughout the SilverStripe core. **General Usage** diff --git a/docs/en/topics/grid-field.md b/docs/en/topics/grid-field.md index 46b415571..465786a1e 100644 --- a/docs/en/topics/grid-field.md +++ b/docs/en/topics/grid-field.md @@ -133,16 +133,17 @@ The fields displayed in the edit form are from `DataObject::getCMSFields()` ### GridFieldConfig_RelationEditor Similar to `GridFieldConfig_RecordEditor`, but adds features to work on a record's has-many or -many-many relationships. +many-many relationships. As such, it expects the list used with the `GridField` to be a +`RelationList`. That is, the list returned by a has-many or many-many getter. The relations can be: - Searched for existing records and add a relationship - Detach records from the relationship (rather than removing them from the database) -- Create new related records and automatically add the relationship. +- Create new related records and automatically add them to the relationship. :::php - $gridField = new GridField('pages', 'All pages', SiteTree::get(), GridFieldConfig_RecordEditor::create()); + $gridField = new GridField('images', 'Linked images', $this->Images(), GridFieldConfig_RelationEditor::create()); The fields displayed in the edit form are from `DataObject::getCMSFields()` @@ -259,5 +260,5 @@ A GridFieldComponent sets and gets data from the GridState. ## Related - * [/reference/modeladmin](ModelAdmin: A UI driven by GridField) - * [/tutorials/5-dataobject-relationship-management](Tutorial 5: Dataobject Relationship Management) \ No newline at end of file + * [ModelAdmin: A UI driven by GridField](/reference/modeladmin) + * [Tutorial 5: Dataobject Relationship Management](/tutorials/5-dataobject-relationship-management) \ No newline at end of file diff --git a/forms/DateField.php b/forms/DateField.php index 8a070c615..9d39b6044 100644 --- a/forms/DateField.php +++ b/forms/DateField.php @@ -148,7 +148,7 @@ class DateField extends TextField { $config = array( 'showcalendar' => $this->getConfig('showcalendar'), 'isoDateformat' => $this->getConfig('dateformat'), - 'jqueryDateformat' => DateField_View_JQuery::convert_iso_to_jquery_format($this->getConfig('dateformat')), + 'jquerydateformat' => DateField_View_JQuery::convert_iso_to_jquery_format($this->getConfig('dateformat')), 'min' => $this->getConfig('min'), 'max' => $this->getConfig('max') ); diff --git a/model/HTMLValue.php b/model/HTMLValue.php index 86d754895..e06d3e5d7 100644 --- a/model/HTMLValue.php +++ b/model/HTMLValue.php @@ -48,6 +48,10 @@ class SS_HTMLValue extends ViewableData { // strip any surrounding tags before the and after the which are automatically added by // DOMDocument. Note that we can't use the argument to saveHTML() as it's only supported in PHP 5.3.6+, // we support 5.3.2 as a minimum in addition to the above, trim any surrounding newlines from the output + + // shortcodes use square brackets which get escaped into HTML entities by saveHTML() + // this manually replaces them back to square brackets so that the shortcodes still work correctly + // we can't use urldecode() here, as valid characters like "+" will be incorrectly replaced with spaces return trim( preg_replace( array( @@ -55,7 +59,7 @@ class SS_HTMLValue extends ViewableData { '/<\/body>(.*)/is', ), '', - urldecode($this->getDocument()->saveHTML()) + str_replace(array('%5B', '%5D'), array('[', ']'), $this->getDocument()->saveHTML()) ) ); } diff --git a/tests/control/CMSProfileControllerTest.php b/tests/control/CMSProfileControllerTest.php new file mode 100644 index 000000000..71c56c70f --- /dev/null +++ b/tests/control/CMSProfileControllerTest.php @@ -0,0 +1,83 @@ +objFromFixture('Member', 'user1'); + $anotherMember = $this->objFromFixture('Member', 'user2'); + $this->session()->inst_set('loggedInAs', $member->ID); + + $response = $this->post('admin/myprofile/EditForm', array( + 'action_save' => 1, + 'ID' => $anotherMember->ID, + 'FirstName' => 'JoeEdited', + 'Surname' => 'BloggsEdited', + 'Email' => $member->Email, + 'Locale' => $member->Locale, + 'Password[_Password]' => 'password', + 'Password[_ConfirmPassword]' => 'password', + )); + + $anotherMember = $this->objFromFixture('Member', 'user2'); + + $this->assertNotEquals($anotherMember->FirstName, 'JoeEdited', 'FirstName field stays the same'); + } + + public function testMemberEditsOwnProfile() { + $member = $this->objFromFixture('Member', 'user1'); + $this->session()->inst_set('loggedInAs', $member->ID); + + $response = $this->post('admin/myprofile/EditForm', array( + 'action_save' => 1, + 'ID' => $member->ID, + 'FirstName' => 'JoeEdited', + 'Surname' => 'BloggsEdited', + 'Email' => $member->Email, + 'Locale' => $member->Locale, + 'Password[_Password]' => 'password', + 'Password[_ConfirmPassword]' => 'password', + )); + + $member = $this->objFromFixture('Member', 'user1'); + + $this->assertEquals($member->FirstName, 'JoeEdited', 'FirstName field was changed'); + } + + public function testExtendedPermissionsStopEditingOwnProfile() { + $existingExtensions = Config::inst()->get('Member', 'extensions'); + Config::inst()->update('Member', 'extensions', array('CMSProfileControllerTestExtension')); + + $member = $this->objFromFixture('Member', 'user1'); + $this->session()->inst_set('loggedInAs', $member->ID); + + $response = $this->post('admin/myprofile/EditForm', array( + 'action_save' => 1, + 'ID' => $member->ID, + 'FirstName' => 'JoeEdited', + 'Surname' => 'BloggsEdited', + 'Email' => $member->Email, + 'Locale' => $member->Locale, + 'Password[_Password]' => 'password', + 'Password[_ConfirmPassword]' => 'password', + )); + + $member = $this->objFromFixture('Member', 'user1'); + + $this->assertNotEquals($member->FirstName, 'JoeEdited', + 'FirstName field was NOT changed because we modified canEdit'); + + Config::inst()->remove('Member', 'extensions'); + Config::inst()->update('Member', 'extensions', $existingExtensions); + } + +} +class CMSProfileControllerTestExtension extends DataExtension { + + public function canEdit($member = null) { + return false; + } + +} diff --git a/tests/control/CMSProfileControllerTest.yml b/tests/control/CMSProfileControllerTest.yml new file mode 100644 index 000000000..4ab2d44f3 --- /dev/null +++ b/tests/control/CMSProfileControllerTest.yml @@ -0,0 +1,27 @@ +Permission: + admin: + Code: ADMIN + cmsmain: + Code: CMS_ACCESS_LeftAndMain + leftandmain: + Code: CMS_ACCESS_CMSMain +Group: + admins: + Title: Administrators + Permissions: =>Permission.admin + cmsusers: + Title: CMS Users + Permissions: =>Permission.cmsmain, =>Permission.leftandmain +Member: + admin: + FirstName: Admin + Email: admin@user.com + Groups: =>Group.admins + user1: + FirstName: Joe + Email: user1@user.com + Groups: =>Group.cmsusers + user2: + FirstName: Steve + Email: user2@user.com + Groups: =>Group.cmsusers