From 65939e1ede9e16fd0fda25fc4692914e6286aa0f Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Thu, 12 Sep 2013 16:48:20 +0200 Subject: [PATCH 1/6] Tagged 3.0.6-rc2 From 29e502a63adb453559a5ae7abbf0a8cf03b10367 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Tue, 24 Sep 2013 12:10:12 +0200 Subject: [PATCH 2/6] Hints for SiteTree.TreeTitle casting Relates to SS-2013-009 --- code/model/SiteTree.php | 1 + 1 file changed, 1 insertion(+) diff --git a/code/model/SiteTree.php b/code/model/SiteTree.php index 9801f8ea..bb74e6b7 100644 --- a/code/model/SiteTree.php +++ b/code/model/SiteTree.php @@ -117,6 +117,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid 'Link' => 'Text', 'RelativeLink' => 'Text', 'AbsoluteLink' => 'Text', + 'TreeTitle' => 'HTMLText', ); static $defaults = array( From 79996a76fe55bd95a99dd99aae5c5f27626f0f06 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Tue, 24 Sep 2013 12:11:13 +0200 Subject: [PATCH 3/6] Clearer escaping in ReportAdmin No direct security issue since report titles can't be set by the user --- code/controllers/ReportAdmin.php | 8 +++++++- code/reports/Report.php | 9 +++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/code/controllers/ReportAdmin.php b/code/controllers/ReportAdmin.php index 21067b78..946633ca 100644 --- a/code/controllers/ReportAdmin.php +++ b/code/controllers/ReportAdmin.php @@ -166,7 +166,13 @@ class ReportAdmin extends LeftAndMain implements PermissionProvider { 'title' => _t('ReportAdmin.ReportTitle', 'Title'), )); $columns->setFieldFormatting(array( - 'title' => '$value' + 'title' => function($value, &$item) { + return sprintf( + '%s', + Convert::raw2xml($item->Link), + Convert::raw2xml($value) + ); + } )); $gridField->addExtraClass('all-reports-gridfield'); $fields->push($gridField); diff --git a/code/reports/Report.php b/code/reports/Report.php index 35fafadf..09e3ce0c 100644 --- a/code/reports/Report.php +++ b/code/reports/Report.php @@ -301,8 +301,13 @@ class SS_Report extends ViewableData { if(isset($info['casting'])) $fieldCasting[$source] = $info['casting']; if(isset($info['link']) && $info['link']) { - $link = singleton('CMSPageEditController')->Link('show'); - $fieldFormatting[$source] = '$value'; + $fieldFormatting[$source] = function($value, &$item) { + return sprintf( + '%s', + Controller::join_links(singleton('CMSPageEditController')->Link('show'), $item->ID), + Convert::raw2xml($value) + ); + }; } $displayFields[$source] = isset($info['title']) ? $info['title'] : $source; From e170f4c21b908b27d91a7f19d9dee4817b6e434c Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Tue, 24 Sep 2013 12:12:21 +0200 Subject: [PATCH 4/6] FIX Escaping in "dependent pages" (SS-2013-009) --- code/model/SiteTree.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/code/model/SiteTree.php b/code/model/SiteTree.php index bb74e6b7..5f27fd8a 100644 --- a/code/model/SiteTree.php +++ b/code/model/SiteTree.php @@ -1827,8 +1827,20 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid ); $dependentTable->getConfig()->getComponentByType('GridFieldDataColumns') ->setFieldFormatting(array( - 'Title' => '$Title', - 'AbsoluteLink' => '$value', + 'Title' => function($value, &$item) { + return sprintf( + '%s', + (int)$item->ID, + Convert::raw2xml($item->Title) + ); + }, + 'AbsoluteLink' => function($value, &$item) { + return sprintf( + '%s', + Convert::raw2xml($value), + Convert::raw2xml($value) + ); + } )); } From 86339a551df55df8882bed7ea2b6ce681d33b74f Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Tue, 24 Sep 2013 12:12:57 +0200 Subject: [PATCH 5/6] Clearer escaping in CMSMain No direct security issue, but makes intent clearer --- code/controllers/CMSMain.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/code/controllers/CMSMain.php b/code/controllers/CMSMain.php index 8d2f96c1..860ea61d 100644 --- a/code/controllers/CMSMain.php +++ b/code/controllers/CMSMain.php @@ -747,13 +747,21 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr if($num) { return sprintf( '%s', - Controller::join_links($controller->Link(), "?ParentID={$item->ID}&view=list"), + Controller::join_links( + $controller->Link(), + sprintf("?ParentID=%d&view=list", (int)$item->ID) + ), $num ); } }, 'getTreeTitle' => function($value, &$item) use($controller) { - return '' . $item->TreeTitle . ''; + return sprintf( + '%s', + singleton('CMSPageEditController')->Link('show'), + (int)$item->ID, + $item->TreeTitle // returns HTML, does its own escaping + ); } )); From fbb9a4449d9bbebfd8fcd9441c966f51d4a2d202 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Thu, 26 Sep 2013 10:53:19 +0200 Subject: [PATCH 6/6] Removed stale salad tests, got behat now --- tests/salad/README.md | 20 ---- tests/salad/create-page.feature | 117 ---------------------- tests/salad/delete-page.feature | 47 --------- tests/salad/login.feature | 39 -------- tests/salad/logout.feature | 20 ---- tests/salad/step_definitions/content.rb | 101 ------------------- tests/salad/step_definitions/front-end.rb | 21 ---- tests/salad/step_definitions/general.rb | 40 -------- tests/salad/step_definitions/log-in.rb | 25 ----- tests/salad/step_definitions/security.rb | 23 ----- 10 files changed, 453 deletions(-) delete mode 100644 tests/salad/README.md delete mode 100644 tests/salad/create-page.feature delete mode 100644 tests/salad/delete-page.feature delete mode 100644 tests/salad/login.feature delete mode 100644 tests/salad/logout.feature delete mode 100644 tests/salad/step_definitions/content.rb delete mode 100644 tests/salad/step_definitions/front-end.rb delete mode 100644 tests/salad/step_definitions/general.rb delete mode 100644 tests/salad/step_definitions/log-in.rb delete mode 100644 tests/salad/step_definitions/security.rb diff --git a/tests/salad/README.md b/tests/salad/README.md deleted file mode 100644 index 12f4fa30..00000000 --- a/tests/salad/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Tests # - -Given I click on the "Tab Name" tab -Given I close window and go back to clean state -Given I fill out the log in form with user "user" and password "password" -Given I get a permission denied error -Given I go to the draft site -Given I log in as Fred -Given I log in as user -Given I log into the CMS as Fred@example.com -Given I log out -Given I visit admin/security -Given I wait for a status message -Given I wait for a success message -Given a "Blog" page called "News" as a child of "Blogs" -Given a "Publishers" group -Given a top-level "BlogPage" page called "News" -Given a user called "Fred" in the "Authors" group -Given the "News" page can be edited by the "Publishers" group -Given the site can be edited by the "Publishers" group diff --git a/tests/salad/create-page.feature b/tests/salad/create-page.feature deleted file mode 100644 index e12675b9..00000000 --- a/tests/salad/create-page.feature +++ /dev/null @@ -1,117 +0,0 @@ -Feature: Page creation in the CMS - As a content author - I want to create a basic text page at the root level and save it - So that our website can be kept up to date - - Scenario: An initial change to page name modifies key fields - Given I log into the CMS as admin - And I create a new page - When I put "Change Name" in the "Page name" field - And I click on the "Metadata" tab - Then the "URLSegment" field is "change-name" - And the "MetaTitle" field is "Change Name" - When I click on the "Main" tab - Then the "Navigation label" field is "Change Name" - - Scenario: Every subsequent change does not change the key fields - Given I save the page - And I cancel pop-ups - When I put "Change Again" in the "Page name" field - And I click on the "Metadata" tab - Then the "URLSegment" field is "change-name" - And the "MetaTitle" field is "Change Name" - When I click on the "Main" tab - Then the "Navigation label" field is "Change Name" - Then I delete the current page - - Scenario: I can populate all fields - And I create a new page - And I set "Page name" to "Populate name" - And I set "Navigation label" to "Populate label" - And I click on the "Metadata" tab - And I set "URLSegment" to "populate-url-segment" - And I set "MetaTitle" to "Populate MetaTitle" - And I set "Description" to "Populate Description" - And I set "Keywords" to "Populate Keywords" - And I set "Custom Meta Tags" to "Populate Custom Meta Tags" - And I click on the "Main" tab - And I save the page - When I load the "Populate label" page - Then the "Page name" field is "Populate name" - And the "Navigation label" field is "Populate label" - When I click on the "Metadata" tab - Then the "URLSegment" field is "populate-url-segment" - And the "MetaTitle" field is "Populate MetaTitle" - And the "Description" field is "Populate Description" - And the "Custom Meta Tags" field is "Populate Custom Meta Tags" - And I click on the "Main" tab - Then I delete the current page - - Scenario: I can create 2 identical pages - When I create a new page - And I create a new page - Then there are 2 root pages with navigation label "New Page" - Then I delete the current page - And I load the "New Page" root-level page - Then I delete the current page - - Scenario: Each change to page name changes the URL - When I create a new page - And I set "Page name" to "First Change" - And I click on the "Metadata" tab - Then the "URLSegment" field is "first-change" - - When I confirm pop-ups - And I click on the "Main" tab - And I set "Page name" to "Second Change" - And I click on the "Metadata" tab - Then the "URLSegment" field is "second-change" - - When I cancel pop-ups - And I click on the "Main" tab - And I set "Page name" to "Third Change" - And I click on the "Metadata" tab - Then the "URLSegment" field is "second-change" - And I click on the "Main" tab - - Then I delete the current page - - Scenario: Changes aren't saved if I cancel the warning - Given I create a new page - And I set "Page name" to "Change name" - When I confirm pop-ups to ignore the warning that their is unsaved content - And I load the "New Page" page - Then the "Page name" field is "New Page" - - Then I delete the current page - - Scenario: Page name and navigation label default to new page - Given I create a new page - Then the "Page name" field is "New Page" - And the "Navigation label" field is "New Page" - - When I click on the "Metadata" tab - Then the "URLSegment" field is "new-page" - And the "MetaTitle" field is blank - And the "Description" field is blank - And the "Keywords" field is blank - And the "Custom Meta Tags" field is blank - And I click on the "Main" tab - - Then I delete the current page - - Scenario: The navigation label is displayed in the site tree - Given I create a new page - And I set "Navigation label" to "New Label" - And I save the page - When I load the "New Label" page - Then the "Navigation label" field is "New Label" - - Scenario: If the navigation label is blanked out, it takes the value in the Page Name field - Given I set "Page name" to "Page Title" - When I set "Navigation label" to "" - And I save the page - And I load the "Page Title" page - Then the "Navigation label" field is "Page Title" - Then I delete the current page - \ No newline at end of file diff --git a/tests/salad/delete-page.feature b/tests/salad/delete-page.feature deleted file mode 100644 index c4153e3a..00000000 --- a/tests/salad/delete-page.feature +++ /dev/null @@ -1,47 +0,0 @@ -Feature: Page deletion in the CMS - As a content author - I want to delete pages in the CMS - So that out of date content can be removed - - Scenario: User can delete a page without making any changes - Given I log into the CMS as admin - And there are 0 root pages with navigation label "delete-page.scenario1" - And I create a new page called "delete-page.scenario1" - And there are 1 root pages with navigation label "delete-page.scenario1" - When I delete the current page - Then there are 0 root pages with navigation label "delete-page.scenario1" - - Scenario: A deleted page can't be viewed - And there are 0 root pages with navigation label "delete-page.scenario2" - Given I create a new page called "delete-page.scenario2" - And there is 1 root page with navigation label "delete-page.scenario2" - When I delete the current page - And there are 0 root pages with navigation label "delete-page.scenario2" - And I log out - Then url delete-page-scenario2 does not exist - - Scenario: A deleted URL can be re-used - Given I log into the CMS as admin - And there are 0 root pages with navigation label "delete-page.scenario3" - And I create a new page called "delete-page.scenario3" - And there are 1 root pages with navigation label "delete-page.scenario3" - And I click on the "Metadata" tab - And the "URLSegment" field is "delete-page-scenario3" - And I delete the current page - And there are 0 root pages with navigation label "delete-page.scenario3" - When I create a new page called "delete-page.scenario3" - And I click on the "Metadata" tab - Then the "URLSegment" field is "delete-page-scenario3" - Then delete the current page - - Scenario: A deleted page doesn't appear after re-login - Given there are 0 root pages with navigation label "delete-page.scenario4" - And I create a new page called "delete-page.scenario4" - And there is 1 root page with navigation label "delete-page.scenario4" - And I save the page - And I delete the current page - And there are 0 root pages with navigation label "delete-page.scenario4" - When I log out - And I log into the CMS as admin - Then there are 0 root pages with navigation label "delete-page.scenario4" - diff --git a/tests/salad/login.feature b/tests/salad/login.feature deleted file mode 100644 index 3c7707da..00000000 --- a/tests/salad/login.feature +++ /dev/null @@ -1,39 +0,0 @@ -Feature: Log in - As a CMS user - I want to security log into the CMS - So that I can make changes, knowing that other people can't. - - Background: - Given I visit Security/logout - - Scenario: opening admin asks user log-in - And I visit admin - Then I am sent to Security/login - - Scenario: valid login - When I fill out the login form with user "admin" and password "password" - Then I see "You're logged in as" - - Scenario: no password login - When I fill out the log in form with user "admin" and password "" - Then I see "That doesn't seem to be the right e-mail address or password." - - Scenario: no user login - When I fill out the log in form with user "" and password "password" - Then I see "That doesn't seem to be the right e-mail address or password." - - Scenario: invalid login, getting right 2nd time - Given I visit admin - And I put "admin" in the "Email" field - And I put "wrongpassword" in the "Password" field - And I click the "Log in" button - Then I am sent to Security/login - And I see "That doesn't seem to be the right e-mail address or password." - Given I put "admin" in the "Email" field - And I put "password" in the "Password" field - And I click the "Log in" button - Then I am sent to admin - - Scenario: Re-login - Given I visit Security/logout - Then I log into the CMS as admin diff --git a/tests/salad/logout.feature b/tests/salad/logout.feature deleted file mode 100644 index 04ab5c6f..00000000 --- a/tests/salad/logout.feature +++ /dev/null @@ -1,20 +0,0 @@ -Feature: Log out - As a CMS user - I want to be able to log and be locked out of the CMS - So that I can know other people can't edit my site - - Scenario: Log out from CMS - Given I log into the CMS as admin - And I click the "Log out" link - When I visit admin/ - Then I see "Please choose an authentication method and enter your credentials to access the CMS." - When I visit admin/assets/ - Then I see "Please choose an authentication method and enter your credentials to access the CMS." - When I visit admin/comments/ - Then I see "Please choose an authentication method and enter your credentials to access the CMS." - When I visit admin/reports/ - Then I see "Please choose an authentication method and enter your credentials to access the CMS." - When I visit admin/security/ - Then I see "Please choose an authentication method and enter your credentials to access the CMS." - When I visit admin/subsites/ - Then I see "Please choose an authentication method and enter your credentials to access the CMS." \ No newline at end of file diff --git a/tests/salad/step_definitions/content.rb b/tests/salad/step_definitions/content.rb deleted file mode 100644 index 721601e7..00000000 --- a/tests/salad/step_definitions/content.rb +++ /dev/null @@ -1,101 +0,0 @@ -## FIXTURE GENERATON - -Given /^the site can be edited by the "([^\"]*)" group$/i do |arg1| - pending -end - -Given /^the "([^\"]*)" page can be edited by the "([^\"]*)" group$/i do |arg1, arg2| - pending -end - -Given /a "(.*)" page called "(.*)" as a child of "(.*)"/i do |type, title, parent| - Given "I click the \"#{parent}\" link" - And 'I wait 2s' - And 'I click the "Create" button' - And "I select \"#{type}\" from \"PageType\"" - And 'I click the "Go" button' - And 'I click the "Create" button' - And "I put \"#{title}\" in the \"Title\" field" - And "I click \"Save\"" -end - -Given /^a top\-level "(.*)" page called "(.*)"$/i do |type,title| - Given "I click the \"Site Content\" link" - And "I create a new page " - And "I click on the \"Main\" tab" - And "I put \"#{title}\" in the \"Title\" field" - And "I click \"Save\"" -end - -## ACTIONS - -Given /load the "(.*)" page/i do |title| - Given "I click the \"#{title}\" link" -end - -Given /I load the "(.*)" root-level page/ do |nav| - @browser.link(:xpath, "//ul[@id='sitetree']/li/ul/li//a[.='#{nav}']").click -end - -Given /I load the root node/ do - Given 'I click the "admin/show/root" link' -end - -Given /create a new page$/i do - Given "I create a new page using template \"Page\"" -end - -Given /create a new page called "(.*)"$/i do |title| - Given "I create a new page using template \"Page\"" - And "I click on the \"Main\" tab" - And "I put \"#{title}\" in the \"Page name\" field" - And "I click the \"Save\" button" -end - -Given /create a new page using template \"(.*)\"/i do |type| - Given 'I load the root node (ajax)' - And 'I click the "Create" button' - And "I select \"#{type}\" from \"PageType\"" - And 'I click the "Go" button (ajax)' - And 'I click the "Create" button' -end - -Given /save the page$/i do - Given 'I click the "Form_EditForm_action_save" button (ajax)' -end - -Given /delete the current page$/i do - Given 'I click the "Delete from the draft site" button' -end - - -## ASSERTIONS - -Given /There (?:are|is) ([0-9]+) root pages? with navigation label "(.*)"/i do |count, nav| - @browser.elements_by_xpath("//ul[@id='sitetree']/li/ul/li//a[.='#{nav}']").count.should == count.to_i -end - -Given /The "(.*)" page does not exist/i do | page| - @browser.link(:title, title).should empty? - #|''get url''|@{root_url}PAGE| - #|''title''|'''is not'''|PAGE| -end - - -## Current Page - -Given /^The (.*) of the current page is "([^\"]*)"$/i do |arg1| - pending -end - -Then /^The current page is editable$/i do - pending -end - -Then /^The current page is read-only$/i do - pending -end - -Then /^The current page is at the top\-level$/i do - pending -end diff --git a/tests/salad/step_definitions/front-end.rb b/tests/salad/step_definitions/front-end.rb deleted file mode 100644 index 93633dff..00000000 --- a/tests/salad/step_definitions/front-end.rb +++ /dev/null @@ -1,21 +0,0 @@ -## -## Step definitions for testing the front-end site -## - - -Given /I go to the draft site/ do - pending - Given 'I click the "viewStageSite" link' -# |''element''|//a[@id="viewStageSite"]|''exists''| -# |''checking timeout''|@{fast_checking_timeout}| -# |''optionally''|''element''|//a[@id="viewStageSite"][@style=""]|''exists''| -# |''checking timeout''|@{checking_timeout}| -# |''click''|viewStageSite| -end - -Given /I close window and go back to clean state/ do -# |''close''| -# |''select initial window''| -# |default frame| -# |''go to root node''| -end diff --git a/tests/salad/step_definitions/general.rb b/tests/salad/step_definitions/general.rb deleted file mode 100644 index 994689bf..00000000 --- a/tests/salad/step_definitions/general.rb +++ /dev/null @@ -1,40 +0,0 @@ -## -## General rules for the SilverStripe CMS as a whole. They mostly have to do with the LeftAndMain -## interface - -# Match general CMS tabs, ModelAdmin needs another system -Given /I click on the "([^\"]*)" tab/ do |tab| - found = nil - links = @salad.browser.links() - links.each {|link| - if /^tab-.+/.match(link.id) then - if link.innerText == tab or /^tab-.*#{tab}(_set)?/.match(link.id) then - found = link - break - end - end - } - if found then - Given "I click the \"#{found.id}\" link" - else - fail("Could not find the \"#{tab}\" tab") - end -end - -Given /I wait for a status message/ do - Watir::Waiter::wait_until { - @browser.p(:id, 'statusMessage').exists? && @browser.p(:id, 'statusMessage').visible? - } -end - -Given /I wait for a success message/ do - # We have to wait until after messages of the form 'Saving...', to get either a good message or - # a bad message - Watir::Waiter::wait_until { - @browser.p(:id, 'statusMessage').exists? && @browser.p(:id, 'statusMessage').visible? && @browser.p(:id, 'statusMessage').class_name != "" - } - - @browser.p(:id, 'statusMessage').class_name.should == 'good' -end - - diff --git a/tests/salad/step_definitions/log-in.rb b/tests/salad/step_definitions/log-in.rb deleted file mode 100644 index 04fc610e..00000000 --- a/tests/salad/step_definitions/log-in.rb +++ /dev/null @@ -1,25 +0,0 @@ - -# Log in -Given /log in as (.*)$/ do |user| - Given "I fill out the log in form with user \"#{user}\" and password \"password\"" - And 'I see "You\'re logged in as"' -end - -Given /log into the CMS as (.*)/ do |user| - Given "I log in as #{user}" - And "I visit admin/" - And "I load the root node" -end - -Given /log out$/ do - Given "I visit Security/logout" -end - -Given /fill out the log(?:\s*)in form with user "(.*)" and password "(.*)"/ do |user, password| - Given 'I visit Security/logout' - And 'I visit Security/login?BackURL=Security/login' - And "I put \"#{user}\" in the \"Email\" field" - And "I put \"#{password}\" in the \"Password\" field" - And "I click the \"Log in\" button" -end - \ No newline at end of file diff --git a/tests/salad/step_definitions/security.rb b/tests/salad/step_definitions/security.rb deleted file mode 100644 index 3278a033..00000000 --- a/tests/salad/step_definitions/security.rb +++ /dev/null @@ -1,23 +0,0 @@ -# Steps definitions for security - -# Fixture instantiation -Given /a "(.*)" group/ do |group| - Given 'I visit admin/security' - And 'I click the "Security Groups" link' - And 'I click the "Create" button' - And "I put \"#{group}\" in the \"Title\" field" - And 'I click the "Save" button' -end - -Given /a user called "(.*)" in the "(.*)" group/ do |user, group| - Given 'I visit admin/security' - And "I click the \"#{group} (global group)\" link" - And "I put \"#{user}\" in the \"FirstName\" field" - And "I put \"#{user}\" in the \"Email\" field" - And "I put \"password\" in the \"SetPassword\" field" - And "I click the \"Add\" button" -end - -Given /^I get a permission denied error$/ do - pending -end