mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge remote-tracking branch 'origin/3.2.1' into 3.2
This commit is contained in:
commit
fd6ae72e1d
@ -9,7 +9,7 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') {
|
|||||||
"CMSMAIN.BATCH_PUBLISH_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich veröffentlichen?",
|
"CMSMAIN.BATCH_PUBLISH_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich veröffentlichen?",
|
||||||
"CMSMAIN.BATCH_DELETE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich löschen?",
|
"CMSMAIN.BATCH_DELETE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich löschen?",
|
||||||
"CMSMAIN.BATCH_ARCHIVE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich archivieren?\n\nDiese Seiten und alle Unterseiten davon werden von der veröffentlichen Seite gelöscht und in das Archiv verschoben.",
|
"CMSMAIN.BATCH_ARCHIVE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich archivieren?\n\nDiese Seiten und alle Unterseiten davon werden von der veröffentlichen Seite gelöscht und in das Archiv verschoben.",
|
||||||
"CMSMAIN.BATCH_RESTORE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to restore to stage?\n\nChildren of archived pages will be restored to the root level, unless those pages are also being restored.",
|
"CMSMAIN.BATCH_RESTORE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\\n\\nWollen Sie diese wirklich wiederherstellen?\\n\\nUnterseiten von archivierten Seiten werden auf der Root-Ebene wiederhergestellt, es sei denn, diese Seiten werden ebenfalls wiederhergestellt.",
|
||||||
"CMSMAIN.BATCH_DELETELIVE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich von der veröfffentlichten Seite löschen?",
|
"CMSMAIN.BATCH_DELETELIVE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich von der veröfffentlichten Seite löschen?",
|
||||||
"LeftAndMain.CONFIRMUNSAVED": "Sind Sie sicher, dass Sie die Seite verlassen möchten?\n\nWARNUNG: Ihre Änderungen werden nicht gespeichert.\n\nDrücken Sie \"OK\" um fortzufahren, oder \"Abbrechen\" um auf dieser Seite zu bleiben.",
|
"LeftAndMain.CONFIRMUNSAVED": "Sind Sie sicher, dass Sie die Seite verlassen möchten?\n\nWARNUNG: Ihre Änderungen werden nicht gespeichert.\n\nDrücken Sie \"OK\" um fortzufahren, oder \"Abbrechen\" um auf dieser Seite zu bleiben.",
|
||||||
"LeftAndMain.CONFIRMUNSAVEDSHORT": "WARNUNG: Ihre Änderungen wurden nicht gespeichert.",
|
"LeftAndMain.CONFIRMUNSAVEDSHORT": "WARNUNG: Ihre Änderungen wurden nicht gespeichert.",
|
||||||
|
@ -4,8 +4,8 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') {
|
|||||||
if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined');
|
if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined');
|
||||||
} else {
|
} else {
|
||||||
ss.i18n.addDictionary('ro', {
|
ss.i18n.addDictionary('ro', {
|
||||||
"CMSMAIN.SELECTONEPAGE": "Please select at least one page",
|
"CMSMAIN.SELECTONEPAGE": "Vă rugăm să selectaţi cel puțin o pagină.",
|
||||||
"CMSMAIN.BATCH_UNPUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to unpublish",
|
"CMSMAIN.BATCH_UNPUBLISH_PROMPT": "Aveti {num} pagina(i) selectate.\n\nDoriti sa le nenublicati",
|
||||||
"CMSMAIN.BATCH_PUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to publish?",
|
"CMSMAIN.BATCH_PUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to publish?",
|
||||||
"CMSMAIN.BATCH_DELETE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete?",
|
"CMSMAIN.BATCH_DELETE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete?",
|
||||||
"CMSMAIN.BATCH_ARCHIVE_PROMPT": "You have {num} page(s) selected.\n\nAre you sure you want to archive these pages?\n\nThese pages and all of their children pages will be unpublished and sent to the archive.",
|
"CMSMAIN.BATCH_ARCHIVE_PROMPT": "You have {num} page(s) selected.\n\nAre you sure you want to archive these pages?\n\nThese pages and all of their children pages will be unpublished and sent to the archive.",
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"CMSMAIN.BATCH_PUBLISH_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich veröffentlichen?",
|
"CMSMAIN.BATCH_PUBLISH_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich veröffentlichen?",
|
||||||
"CMSMAIN.BATCH_DELETE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich löschen?",
|
"CMSMAIN.BATCH_DELETE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich löschen?",
|
||||||
"CMSMAIN.BATCH_ARCHIVE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich archivieren?\n\nDiese Seiten und alle Unterseiten davon werden von der veröffentlichen Seite gelöscht und in das Archiv verschoben.",
|
"CMSMAIN.BATCH_ARCHIVE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich archivieren?\n\nDiese Seiten und alle Unterseiten davon werden von der veröffentlichen Seite gelöscht und in das Archiv verschoben.",
|
||||||
"CMSMAIN.BATCH_RESTORE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to restore to stage?\n\nChildren of archived pages will be restored to the root level, unless those pages are also being restored.",
|
"CMSMAIN.BATCH_RESTORE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\\n\\nWollen Sie diese wirklich wiederherstellen?\\n\\nUnterseiten von archivierten Seiten werden auf der Root-Ebene wiederhergestellt, es sei denn, diese Seiten werden ebenfalls wiederhergestellt.",
|
||||||
"CMSMAIN.BATCH_DELETELIVE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich von der veröfffentlichten Seite löschen?",
|
"CMSMAIN.BATCH_DELETELIVE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich von der veröfffentlichten Seite löschen?",
|
||||||
"LeftAndMain.CONFIRMUNSAVED": "Sind Sie sicher, dass Sie die Seite verlassen möchten?\n\nWARNUNG: Ihre Änderungen werden nicht gespeichert.\n\nDrücken Sie \"OK\" um fortzufahren, oder \"Abbrechen\" um auf dieser Seite zu bleiben.",
|
"LeftAndMain.CONFIRMUNSAVED": "Sind Sie sicher, dass Sie die Seite verlassen möchten?\n\nWARNUNG: Ihre Änderungen werden nicht gespeichert.\n\nDrücken Sie \"OK\" um fortzufahren, oder \"Abbrechen\" um auf dieser Seite zu bleiben.",
|
||||||
"LeftAndMain.CONFIRMUNSAVEDSHORT": "WARNUNG: Ihre Änderungen wurden nicht gespeichert.",
|
"LeftAndMain.CONFIRMUNSAVEDSHORT": "WARNUNG: Ihre Änderungen wurden nicht gespeichert.",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"CMSMAIN.SELECTONEPAGE": "Please select at least one page",
|
"CMSMAIN.SELECTONEPAGE": "Vă rugăm să selectaţi cel puțin o pagină.",
|
||||||
"CMSMAIN.BATCH_UNPUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to unpublish",
|
"CMSMAIN.BATCH_UNPUBLISH_PROMPT": "Aveti {num} pagina(i) selectate.\n\nDoriti sa le nenublicati",
|
||||||
"CMSMAIN.BATCH_PUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to publish?",
|
"CMSMAIN.BATCH_PUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to publish?",
|
||||||
"CMSMAIN.BATCH_DELETE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete?",
|
"CMSMAIN.BATCH_DELETE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete?",
|
||||||
"CMSMAIN.BATCH_ARCHIVE_PROMPT": "You have {num} page(s) selected.\n\nAre you sure you want to archive these pages?\n\nThese pages and all of their children pages will be unpublished and sent to the archive.",
|
"CMSMAIN.BATCH_ARCHIVE_PROMPT": "You have {num} page(s) selected.\n\nAre you sure you want to archive these pages?\n\nThese pages and all of their children pages will be unpublished and sent to the archive.",
|
||||||
|
@ -16,6 +16,7 @@ class RSSFeed extends ViewableData {
|
|||||||
private static $casting = array(
|
private static $casting = array(
|
||||||
"Title" => "Varchar",
|
"Title" => "Varchar",
|
||||||
"Description" => "Varchar",
|
"Description" => "Varchar",
|
||||||
|
"Link" => "Varchar",
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -188,14 +188,14 @@ class RequestHandler extends ViewableData {
|
|||||||
user_error("Non-string method name: " . var_export($action, true), E_USER_ERROR);
|
user_error("Non-string method name: " . var_export($action, true), E_USER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
$className = get_class($this);
|
$classMessage = Director::isLive() ? 'on this handler' : 'on class '.get_class($this);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(!$this->hasAction($action)) {
|
if(!$this->hasAction($action)) {
|
||||||
return $this->httpError(404, "Action '$action' isn't available on class $className.");
|
return $this->httpError(404, "Action '$action' isn't available $classMessage.");
|
||||||
}
|
}
|
||||||
if(!$this->checkAccessAction($action) || in_array(strtolower($action), array('run', 'init'))) {
|
if(!$this->checkAccessAction($action) || in_array(strtolower($action), array('run', 'init'))) {
|
||||||
return $this->httpError(403, "Action '$action' isn't allowed on class $className.");
|
return $this->httpError(403, "Action '$action' isn't allowed $classMessage.");
|
||||||
}
|
}
|
||||||
$result = $this->handleAction($request, $action);
|
$result = $this->handleAction($request, $action);
|
||||||
}
|
}
|
||||||
@ -232,7 +232,7 @@ class RequestHandler extends ViewableData {
|
|||||||
|
|
||||||
// But if we have more content on the URL and we don't know what to do with it, return an error.
|
// But if we have more content on the URL and we don't know what to do with it, return an error.
|
||||||
} else {
|
} else {
|
||||||
return $this->httpError(404, "I can't handle sub-URLs of a $this->class object.");
|
return $this->httpError(404, "I can't handle sub-URLs $classMessage.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -276,10 +276,10 @@ class RequestHandler extends ViewableData {
|
|||||||
* @return SS_HTTPResponse
|
* @return SS_HTTPResponse
|
||||||
*/
|
*/
|
||||||
protected function handleAction($request, $action) {
|
protected function handleAction($request, $action) {
|
||||||
$className = get_class($this);
|
$classMessage = Director::isLive() ? 'on this handler' : 'on class '.get_class($this);
|
||||||
|
|
||||||
if(!$this->hasMethod($action)) {
|
if(!$this->hasMethod($action)) {
|
||||||
return new SS_HTTPResponse("Action '$action' isn't available on class $className.", 404);
|
return new SS_HTTPResponse("Action '$action' isn't available $classMessage.", 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$res = $this->extend('beforeCallActionHandler', $request, $action);
|
$res = $this->extend('beforeCallActionHandler', $request, $action);
|
||||||
|
@ -218,6 +218,18 @@ To refresh a oEmbed cache, append `?flush=1` to a URL.
|
|||||||
|
|
||||||
To disable oEmbed usage, set the `Oembed.enabled` configuration property to "false".
|
To disable oEmbed usage, set the `Oembed.enabled` configuration property to "false".
|
||||||
|
|
||||||
|
## Limiting oembed URLs
|
||||||
|
|
||||||
|
HtmlEditorField can have whitelists set on both the scheme (default http & https) and domains allowed when
|
||||||
|
inserting files for use with oembed.
|
||||||
|
|
||||||
|
This is performed through the config variables `HtmlEditorField_Toolbar::$fileurl_scheme_whitelist` and
|
||||||
|
`HtmlEditorField_Toolbar::$fileurl_domain_whitelist`.
|
||||||
|
|
||||||
|
Setting these configuration variables to empty arrays will disable the whitelist. Setting them to an array of
|
||||||
|
lower case strings will require the scheme or domain respectively to exactly match one of those strings (no
|
||||||
|
wildcards are currently supported).
|
||||||
|
|
||||||
### Doctypes
|
### Doctypes
|
||||||
|
|
||||||
Since TinyMCE generates markup, it needs to know which doctype your documents will be rendered in. You can set this
|
Since TinyMCE generates markup, it needs to know which doctype your documents will be rendered in. You can set this
|
||||||
|
56
docs/en/04_Changelogs/3.2.1.md
Normal file
56
docs/en/04_Changelogs/3.2.1.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# 3.2.1
|
||||||
|
|
||||||
|
## Upgrading
|
||||||
|
|
||||||
|
FormField validation messages generated by the `Validator` class will now be automatically XML
|
||||||
|
encoded before being rendered alongside an invalid field.
|
||||||
|
|
||||||
|
If a validation message in a custom `Validator` instance should be rendered as literal HTML,
|
||||||
|
then the $message parameter for `Validator::validationError` should be passed as an instance
|
||||||
|
of `HTMLText`
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
:::php
|
||||||
|
class MyCustomValidator extends Validator {
|
||||||
|
public function php($data) {
|
||||||
|
$this->validationError(
|
||||||
|
'EmailAddress',
|
||||||
|
DBField::create_field('HTMLText', "Invalid email. Please sign up at <a href='signup'>this page</a>")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
<!--- Changes below this line will be automatically regenerated -->
|
||||||
|
|
||||||
|
## Change Log
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
* 2015-11-12 [b61d6dc](https://github.com/silverstripe/silverstripe-framework/commit/b61d6dcd57577b0345af7a69e51da409305e1957) HtmlEditorField_Toolbar#viewfile not whitelisting URLs (Hamish Friedlander) - See [ss-2015-027](http://www.silverstripe.org/download/security-releases/ss-2015-027)
|
||||||
|
* 2015-11-11 [bc1b289](https://github.com/silverstripe/silverstripe-framework/commit/bc1b2893accba6401c03f9ea3b0cbc4621c7a02c) Fix FormField error messages not being encoded safely (Damian Mooyman) - See [ss-2015-026](http://www.silverstripe.org/download/security-releases/ss-2015-026)
|
||||||
|
* 2015-11-09 [f290d86](https://github.com/silverstripe/silverstripe-framework/commit/f290d869e01e0087286b4f2bc92e95d15c229c45) Dont expose class on error (Hamish Friedlander) - See [ss-2015-025](http://www.silverstripe.org/download/security-releases/ss-2015-025)
|
||||||
|
* 2015-11-01 [4f55b6a](https://github.com/silverstripe/silverstripe-framework/commit/4f55b6a115ce0de8c5c258fb44eca52b8b112caf) XML escape RSSFeed $link parameter (Ingo Schommer) - See [ss-2015-022](http://www.silverstripe.org/download/security-releases/ss-2015-022)
|
||||||
|
* 2015-10-28 [132e9b3](https://github.com/silverstripe/silverstripe-framework/commit/132e9b3e2fad361ebb4b502b6a37d34d013bfba3) Fix rewrite hash links XSS (Damian Mooyman) - See [ss-2015-021](http://www.silverstripe.org/download/security-releases/ss-2015-021)
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
|
||||||
|
* 2015-11-10 [732e705](https://github.com/silverstripe/silverstripe-framework/commit/732e705bbf548024b123d5160863395f2f74e7d9) Correct behaviour for empty filter array (as per 3.1) (Damian Mooyman)
|
||||||
|
* 2015-11-09 [414ea3d](https://github.com/silverstripe/silverstripe-framework/commit/414ea3de9e87812c5ac96cc15062307c608e0963) prevent UploadField edit form generation for Folders (Damian Mooyman)
|
||||||
|
* 2015-11-05 [c6c650f](https://github.com/silverstripe/silverstripe-cms/commit/c6c650f1366348327d973ca6cc5a5ed33a467786) Ensure CMSMainTest uses correct siteconfig (Damian Mooyman)
|
||||||
|
* 2015-11-02 [0272e44](https://github.com/silverstripe/silverstripe-framework/commit/0272e443f44ebca55b05c14f2a112260ff0df284) Prevent dev/build continually regenerating Number field type (Damian Mooyman)
|
||||||
|
* 2015-10-30 [2813f94](https://github.com/silverstripe/silverstripe-framework/commit/2813f94124c2ba14f1e4a51001e3898b0e0c32aa) Ensure that filters on any fixed field are scoped to the base data table (Damian Mooyman)
|
||||||
|
* 2015-10-30 [38ca963](https://github.com/silverstripe/silverstripe-framework/commit/38ca9632c4e9df0a74eae70cec98fdce242da529) Add missing CMSSecurity route (Damian Mooyman)
|
||||||
|
* 2015-10-29 [daa86d3](https://github.com/silverstripe/silverstripe-framework/commit/daa86d3a4ce75bf8637134726864ae14fbbdf586) Fix regression from #4396 in test fixtures (Damian Mooyman)
|
||||||
|
* 2015-10-28 [db16248](https://github.com/silverstripe/silverstripe-framework/commit/db16248b9ab7677cc4b4e25857a6b6d36f8c35f0) Fix broken InlineFormAction (Damian Mooyman)
|
||||||
|
* 2015-10-27 [293d847](https://github.com/silverstripe/silverstripe-framework/commit/293d84721efafedf3dd3fe69dd1d013a8c07d3ff) for #4712: Dropping in some PHP documentation on return types for dynamically generated image methods. (Patrick Nelson)
|
||||||
|
* 2015-10-20 [b857bdf](https://github.com/silverstripe/silverstripe-framework/commit/b857bdf209d79fc623724e68f6a660354cbd5f93) Fix duplicate files being included in case of flush (Damian Mooyman)
|
||||||
|
* 2015-10-19 [c364158](https://github.com/silverstripe/silverstripe-framework/commit/c3641587a5d5977af4fa053e5813846ce990d86c) only use sethasemptydefault if exists. (Cam Findlay)
|
||||||
|
* 2015-10-08 [ff6c0a3](https://github.com/silverstripe/silverstripe-cms/commit/ff6c0a3160c5eb3ca624efea6585efb44399dc1c) (v3.1) for #1294 to workaround ErrorPage fatal errors (and undefined var) when publishing. (Patrick Nelson)
|
||||||
|
* 2015-10-08 [785f850](https://github.com/silverstripe/silverstripe-cms/commit/785f85047f64b76011c34542362c7f09dbf59021) for #1294 to workaround ErrorPage fatal errors (and undefined var) when publishing. (Patrick Nelson)
|
||||||
|
* 2015-10-01 [75dc391](https://github.com/silverstripe/silverstripe-cms/commit/75dc391df9b396756a6f02c5fca08eafcb53ba31) for #586 and possible fix for #736 and relates to #2449: Don't perform validation upon deletion, since it isn't necessary. Cleaned up type hint. (Patrick Nelson)
|
||||||
|
* 2015-09-17 [e64d73c](https://github.com/silverstripe/silverstripe-framework/commit/e64d73c1f741399412b6015f6602ed707b2e9778) Fix ClassInfo::table_for_object_field (Damian Mooyman)
|
||||||
|
* 2015-08-05 [2901664](https://github.com/silverstripe/silverstripe-framework/commit/29016645e5e759b1ecf49876fa79c357a68c5794) . FulltextFilter requires table identifiers in match query (Elvinas L.)
|
||||||
|
* 2015-07-12 [f192a6e](https://github.com/silverstripe/silverstripe-framework/commit/f192a6ecaf70446ec60f6c7ef2a555395f83ea16) #4392: Ensure headers are checked first before being clobbered by globally maintained state. Also ensuring tests utilize separate responses for isolation. (Patrick Nelson)
|
34
docs/en/04_Changelogs/rc/3.2.1-rc1.md
Normal file
34
docs/en/04_Changelogs/rc/3.2.1-rc1.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# 3.2.1-rc1
|
||||||
|
|
||||||
|
See [3.2.1](/changelogs/3.2.1) changelog for more information on what is new in 3.2.1
|
||||||
|
|
||||||
|
<!--- Changes below this line will be automatically regenerated -->
|
||||||
|
|
||||||
|
## Change Log
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
* 2015-11-11 [bc1b289](https://github.com/silverstripe/silverstripe-framework/commit/bc1b2893accba6401c03f9ea3b0cbc4621c7a02c) Fix FormField error messages not being encoded safely (Damian Mooyman) - See [ss-2015-026](http://www.silverstripe.org/download/security-releases/ss-2015-026)
|
||||||
|
* 2015-11-09 [f290d86](https://github.com/silverstripe/silverstripe-framework/commit/f290d869e01e0087286b4f2bc92e95d15c229c45) Dont expose class on error (Hamish Friedlander) - See [ss-2015-025](http://www.silverstripe.org/download/security-releases/ss-2015-025)
|
||||||
|
* 2015-11-01 [4f55b6a](https://github.com/silverstripe/silverstripe-framework/commit/4f55b6a115ce0de8c5c258fb44eca52b8b112caf) XML escape RSSFeed $link parameter (Ingo Schommer) - See [ss-2015-022](http://www.silverstripe.org/download/security-releases/ss-2015-022)
|
||||||
|
* 2015-10-28 [132e9b3](https://github.com/silverstripe/silverstripe-framework/commit/132e9b3e2fad361ebb4b502b6a37d34d013bfba3) Fix rewrite hash links XSS (Damian Mooyman) - See [ss-2015-021](http://www.silverstripe.org/download/security-releases/ss-2015-021)
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
|
||||||
|
* 2015-11-10 [732e705](https://github.com/silverstripe/silverstripe-framework/commit/732e705bbf548024b123d5160863395f2f74e7d9) Correct behaviour for empty filter array (as per 3.1) (Damian Mooyman)
|
||||||
|
* 2015-11-09 [414ea3d](https://github.com/silverstripe/silverstripe-framework/commit/414ea3de9e87812c5ac96cc15062307c608e0963) prevent UploadField edit form generation for Folders (Damian Mooyman)
|
||||||
|
* 2015-11-05 [c6c650f](https://github.com/silverstripe/silverstripe-cms/commit/c6c650f1366348327d973ca6cc5a5ed33a467786) Ensure CMSMainTest uses correct siteconfig (Damian Mooyman)
|
||||||
|
* 2015-11-02 [0272e44](https://github.com/silverstripe/silverstripe-framework/commit/0272e443f44ebca55b05c14f2a112260ff0df284) Prevent dev/build continually regenerating Number field type (Damian Mooyman)
|
||||||
|
* 2015-10-30 [2813f94](https://github.com/silverstripe/silverstripe-framework/commit/2813f94124c2ba14f1e4a51001e3898b0e0c32aa) Ensure that filters on any fixed field are scoped to the base data table (Damian Mooyman)
|
||||||
|
* 2015-10-30 [38ca963](https://github.com/silverstripe/silverstripe-framework/commit/38ca9632c4e9df0a74eae70cec98fdce242da529) Add missing CMSSecurity route (Damian Mooyman)
|
||||||
|
* 2015-10-29 [daa86d3](https://github.com/silverstripe/silverstripe-framework/commit/daa86d3a4ce75bf8637134726864ae14fbbdf586) Fix regression from #4396 in test fixtures (Damian Mooyman)
|
||||||
|
* 2015-10-28 [db16248](https://github.com/silverstripe/silverstripe-framework/commit/db16248b9ab7677cc4b4e25857a6b6d36f8c35f0) Fix broken InlineFormAction (Damian Mooyman)
|
||||||
|
* 2015-10-27 [293d847](https://github.com/silverstripe/silverstripe-framework/commit/293d84721efafedf3dd3fe69dd1d013a8c07d3ff) for #4712: Dropping in some PHP documentation on return types for dynamically generated image methods. (Patrick Nelson)
|
||||||
|
* 2015-10-20 [b857bdf](https://github.com/silverstripe/silverstripe-framework/commit/b857bdf209d79fc623724e68f6a660354cbd5f93) Fix duplicate files being included in case of flush (Damian Mooyman)
|
||||||
|
* 2015-10-19 [c364158](https://github.com/silverstripe/silverstripe-framework/commit/c3641587a5d5977af4fa053e5813846ce990d86c) only use sethasemptydefault if exists. (Cam Findlay)
|
||||||
|
* 2015-10-08 [ff6c0a3](https://github.com/silverstripe/silverstripe-cms/commit/ff6c0a3160c5eb3ca624efea6585efb44399dc1c) (v3.1) for #1294 to workaround ErrorPage fatal errors (and undefined var) when publishing. (Patrick Nelson)
|
||||||
|
* 2015-10-08 [785f850](https://github.com/silverstripe/silverstripe-cms/commit/785f85047f64b76011c34542362c7f09dbf59021) for #1294 to workaround ErrorPage fatal errors (and undefined var) when publishing. (Patrick Nelson)
|
||||||
|
* 2015-10-01 [75dc391](https://github.com/silverstripe/silverstripe-cms/commit/75dc391df9b396756a6f02c5fca08eafcb53ba31) for #586 and possible fix for #736 and relates to #2449: Don't perform validation upon deletion, since it isn't necessary. Cleaned up type hint. (Patrick Nelson)
|
||||||
|
* 2015-09-17 [e64d73c](https://github.com/silverstripe/silverstripe-framework/commit/e64d73c1f741399412b6015f6602ed707b2e9778) Fix ClassInfo::table_for_object_field (Damian Mooyman)
|
||||||
|
* 2015-08-05 [2901664](https://github.com/silverstripe/silverstripe-framework/commit/29016645e5e759b1ecf49876fa79c357a68c5794) . FulltextFilter requires table identifiers in match query (Elvinas L.)
|
||||||
|
* 2015-07-12 [f192a6e](https://github.com/silverstripe/silverstripe-framework/commit/f192a6ecaf70446ec60f6c7ef2a555395f83ea16) #4392: Ensure headers are checked first before being clobbered by globally maintained state. Also ensuring tests utilize separate responses for isolation. (Patrick Nelson)
|
11
docs/en/04_Changelogs/rc/3.2.1-rc2.md
Normal file
11
docs/en/04_Changelogs/rc/3.2.1-rc2.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# 3.2.1-rc2
|
||||||
|
|
||||||
|
See [3.2.1](/changelogs/3.2.1) changelog for more information on what is new in 3.2.1
|
||||||
|
|
||||||
|
<!--- Changes below this line will be automatically regenerated -->
|
||||||
|
|
||||||
|
## Change Log
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
* 2015-11-12 [b61d6dc](https://github.com/silverstripe/silverstripe-framework/commit/b61d6dcd57577b0345af7a69e51da409305e1957) HtmlEditorField_Toolbar#viewfile not whitelisting URLs (Hamish Friedlander) - See [ss-2015-027](http://www.silverstripe.org/download/security-releases/ss-2015-027)
|
@ -1303,6 +1303,18 @@ class Form extends RequestHandler {
|
|||||||
// Load errors into session and post back
|
// Load errors into session and post back
|
||||||
$data = $this->getData();
|
$data = $this->getData();
|
||||||
|
|
||||||
|
// Encode validation messages as XML before saving into session state
|
||||||
|
// As per Form::addErrorMessage()
|
||||||
|
$errors = array_map(function($error) {
|
||||||
|
// Encode message as XML by default
|
||||||
|
if($error['message'] instanceof DBField) {
|
||||||
|
$error['message'] = $error['message']->forTemplate();;
|
||||||
|
} else {
|
||||||
|
$error['message'] = Convert::raw2xml($error['message']);
|
||||||
|
}
|
||||||
|
return $error;
|
||||||
|
}, $errors);
|
||||||
|
|
||||||
Session::set("FormInfo.{$this->FormName()}.errors", $errors);
|
Session::set("FormInfo.{$this->FormName()}.errors", $errors);
|
||||||
Session::set("FormInfo.{$this->FormName()}.data", $data);
|
Session::set("FormInfo.{$this->FormName()}.data", $data);
|
||||||
|
|
||||||
|
@ -449,40 +449,98 @@ class HtmlEditorField_Toolbar extends RequestHandler {
|
|||||||
return $form;
|
return $form;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @config
|
||||||
|
* @var array - list of allowed schemes (no wildcard, all lower case) or empty to allow all schemes
|
||||||
|
*/
|
||||||
|
private static $fileurl_scheme_whitelist = array('http', 'https');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @config
|
||||||
|
* @var array - list of allowed domains (no wildcard, all lower case) or empty to allow all domains
|
||||||
|
*/
|
||||||
|
private static $fileurl_domain_whitelist = array();
|
||||||
|
|
||||||
|
protected function viewfile_getLocalFileByID($id) {
|
||||||
|
$file = DataObject::get_by_id('File', $id);
|
||||||
|
|
||||||
|
if ($file && $file->canView()) return array($file, $file->RelativeLink());
|
||||||
|
return array(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function viewfile_getLocalFileByURL($fileUrl) {
|
||||||
|
$filteredUrl = Director::makeRelative($fileUrl);
|
||||||
|
$filteredUrl = preg_replace('/_resampled\/[^-]+-/', '', $filteredUrl);
|
||||||
|
|
||||||
|
$file = File::get()->filter('Filename', $filteredUrl)->first();
|
||||||
|
|
||||||
|
if ($file && $file->canView()) return array($file, $filteredUrl);
|
||||||
|
return array(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function viewfile_getRemoteFileByURL($fileUrl) {
|
||||||
|
$scheme = strtolower(parse_url($fileUrl, PHP_URL_SCHEME));
|
||||||
|
$allowed_schemes = self::config()->fileurl_scheme_whitelist;
|
||||||
|
|
||||||
|
if (!$scheme || ($allowed_schemes && !in_array($scheme, $allowed_schemes))) {
|
||||||
|
$exception = new SS_HTTPResponse_Exception("This file scheme is not included in the whitelist", 400);
|
||||||
|
$exception->getResponse()->addHeader('X-Status', $exception->getMessage());
|
||||||
|
throw $exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
$domain = strtolower(parse_url($fileUrl, PHP_URL_HOST));
|
||||||
|
$allowed_domains = self::config()->fileurl_domain_whitelist;
|
||||||
|
|
||||||
|
if (!$domain || ($allowed_domains && !in_array($domain, $allowed_domains))) {
|
||||||
|
$exception = new SS_HTTPResponse_Exception("This file hostname is not included in the whitelist", 400);
|
||||||
|
$exception->getResponse()->addHeader('X-Status', $exception->getMessage());
|
||||||
|
throw $exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
new File(array(
|
||||||
|
'Title' => basename($fileUrl),
|
||||||
|
'Filename' => $fileUrl
|
||||||
|
)),
|
||||||
|
$fileUrl
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View of a single file, either on the filesystem or on the web.
|
* View of a single file, either on the filesystem or on the web.
|
||||||
*/
|
*/
|
||||||
public function viewfile($request) {
|
public function viewfile($request) {
|
||||||
|
$file = null;
|
||||||
|
$url = null;
|
||||||
|
|
||||||
// TODO Would be cleaner to consistently pass URL for both local and remote files,
|
// TODO Would be cleaner to consistently pass URL for both local and remote files,
|
||||||
// but GridField doesn't allow for this kind of metadata customization at the moment.
|
// but GridField doesn't allow for this kind of metadata customization at the moment.
|
||||||
if($url = $request->getVar('FileURL')) {
|
if($fileUrl = $request->getVar('FileURL')) {
|
||||||
if(Director::is_absolute_url($url) && !Director::is_site_url($url)) {
|
// If this isn't an absolute URL, or is, but is to this site, try and get the File object
|
||||||
$url = $url;
|
// that is associated with it
|
||||||
$file = new File(array(
|
if(!Director::is_absolute_url($fileUrl) || Director::is_site_url($fileUrl)) {
|
||||||
'Title' => basename($url),
|
list($file, $url) = $this->viewfile_getLocalFileByURL($fileUrl);
|
||||||
'Filename' => $url
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
$url = Director::makeRelative($request->getVar('FileURL'));
|
|
||||||
$url = preg_replace('/_resampled\/[^-]+-/', '', $url);
|
|
||||||
$file = File::get()->filter('Filename', $url)->first();
|
|
||||||
if(!$file) $file = new File(array(
|
|
||||||
'Title' => basename($url),
|
|
||||||
'Filename' => $url
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
} elseif($id = $request->getVar('ID')) {
|
// If this is an absolute URL, but not to this site, use as an oembed source (after whitelisting URL)
|
||||||
$file = DataObject::get_by_id('File', $id);
|
else {
|
||||||
$url = $file->RelativeLink();
|
list($file, $url) = $this->viewfile_getRemoteFileByURL($fileUrl);
|
||||||
} else {
|
}
|
||||||
throw new LogicException('Need either "ID" or "FileURL" parameter to identify the file');
|
}
|
||||||
|
// Or we could have been passed an ID directly
|
||||||
|
elseif($id = $request->getVar('ID')) {
|
||||||
|
list($file, $url) = $this->viewfile_getLocalFileByID($id);
|
||||||
|
}
|
||||||
|
// Or we could have been passed nothing, in which case panic
|
||||||
|
else {
|
||||||
|
throw new SS_HTTPResponse_Exception('Need either "ID" or "FileURL" parameter to identify the file', 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instanciate file wrapper and get fields based on its type
|
// Instanciate file wrapper and get fields based on its type
|
||||||
// Check if appCategory is an image and exists on the local system, otherwise use oEmbed to refference a
|
// Check if appCategory is an image and exists on the local system, otherwise use oEmbed to refference a
|
||||||
// remote image
|
// remote image
|
||||||
if($file && $file->appCategory() == 'image' && Director::is_site_url($url)) {
|
if (!$file || !$url) {
|
||||||
|
throw new SS_HTTPResponse_Exception('Unable to find file to view', 404);
|
||||||
|
} elseif($file->appCategory() == 'image' && Director::is_site_url($url)) {
|
||||||
$fileWrapper = new HtmlEditorField_Image($url, $file);
|
$fileWrapper = new HtmlEditorField_Image($url, $file);
|
||||||
} elseif(!Director::is_site_url($url)) {
|
} elseif(!Director::is_site_url($url)) {
|
||||||
$fileWrapper = new HtmlEditorField_Embed($url, $file);
|
$fileWrapper = new HtmlEditorField_Embed($url, $file);
|
||||||
|
@ -292,8 +292,6 @@ cs:
|
|||||||
FROMWEB: 'Z webu'
|
FROMWEB: 'Z webu'
|
||||||
FindInFolder: 'Hledat ve složce'
|
FindInFolder: 'Hledat ve složce'
|
||||||
IMAGEALT: 'Alternativní text (alt)'
|
IMAGEALT: 'Alternativní text (alt)'
|
||||||
IMAGEALTTEXT: 'Alternativní text (alt) - ukáže se, když obrázek nemúže být zobrazen'
|
|
||||||
IMAGEALTTEXTDESC: 'Zobrazeno na obrazovce, anebo když obrázek nemůže být zobrazen'
|
|
||||||
IMAGEDIMENSIONS: Rozměry
|
IMAGEDIMENSIONS: Rozměry
|
||||||
IMAGEHEIGHTPX: Výška
|
IMAGEHEIGHTPX: Výška
|
||||||
IMAGETITLE: 'Titul text (tooltip) - další informace o obrázku'
|
IMAGETITLE: 'Titul text (tooltip) - další informace o obrázku'
|
||||||
@ -328,11 +326,9 @@ cs:
|
|||||||
DELETED: Smazáno.
|
DELETED: Smazáno.
|
||||||
DropdownBatchActionsDefault: Akcie
|
DropdownBatchActionsDefault: Akcie
|
||||||
HELP: Nápověda
|
HELP: Nápověda
|
||||||
PAGETYPE: 'Typ stránky:'
|
|
||||||
PERMAGAIN: 'Byli jste odhlášeni z CMS. Pokud se chcete znovu přihlásit, zadejte níže své uživatelské jméno a heslo.'
|
PERMAGAIN: 'Byli jste odhlášeni z CMS. Pokud se chcete znovu přihlásit, zadejte níže své uživatelské jméno a heslo.'
|
||||||
PERMALREADY: 'Omlouvám se, ale nemůžete vstoupit do této části CMS. Pokud se chcete přihlásit jako někdo jiný, udělejte tak níže.'
|
PERMALREADY: 'Omlouvám se, ale nemůžete vstoupit do této části CMS. Pokud se chcete přihlásit jako někdo jiný, udělejte tak níže.'
|
||||||
PERMDEFAULT: 'Musíte být přihlášen/a k přístup do oblasti administrace, zadejte vaše přihlošovací údaje dole, prosím.'
|
PERMDEFAULT: 'Musíte být přihlášen/a k přístup do oblasti administrace, zadejte vaše přihlošovací údaje dole, prosím.'
|
||||||
PLEASESAVE: 'Uložte stránku, prosím. Tato stránka nemůže být aktualizována, protože ještě nebyla uložena.'
|
|
||||||
PreviewButton: Náhled
|
PreviewButton: Náhled
|
||||||
REORGANISATIONSUCCESSFUL: 'Strom webu reorganizován úspěšně.'
|
REORGANISATIONSUCCESSFUL: 'Strom webu reorganizován úspěšně.'
|
||||||
SAVEDUP: Uloženo.
|
SAVEDUP: Uloženo.
|
||||||
|
@ -260,6 +260,7 @@ de:
|
|||||||
many_many_Members: Mitglieder
|
many_many_Members: Mitglieder
|
||||||
GroupImportForm:
|
GroupImportForm:
|
||||||
Help1: '<p>Eine oder mehrere Gruppen im <em>CSV</em>-Format (kommaseparierte Werte) importieren. <small><a href="#" class="toggle-advanced">Erweiterte Nutzung</a></small></p>'
|
Help1: '<p>Eine oder mehrere Gruppen im <em>CSV</em>-Format (kommaseparierte Werte) importieren. <small><a href="#" class="toggle-advanced">Erweiterte Nutzung</a></small></p>'
|
||||||
|
Help2: '<div class="advanced"><h4>Erweiterte Benutzung</h4><ul><li>Gültige Spalten: <em>%s</em></li><li>Bereits existierende Gruppen werden anhand ihres eindeutigen <em>Code</em> identifiziert und um neue Einträge aus der Importdatei erweitert.</li><li>Gruppenhierarchien können mittels der Spalte <em>ParentCode</em> erstellt werden.</li><li>Berechtigungen können in der Spalte <em>PermissionCode</em> hinzugefügt werden. Schon zugewiesene Berechtigungen werden nicht entfernt.</li></ul></div>'
|
||||||
ResultCreated: '{count} Gruppe(n) wurden erstellt'
|
ResultCreated: '{count} Gruppe(n) wurden erstellt'
|
||||||
ResultDeleted: '%d Gruppe(n) gelöscht'
|
ResultDeleted: '%d Gruppe(n) gelöscht'
|
||||||
ResultUpdated: '%d Gruppe(n) aktualisiert'
|
ResultUpdated: '%d Gruppe(n) aktualisiert'
|
||||||
@ -291,6 +292,7 @@ de:
|
|||||||
FROMWEB: 'Aus dem Web'
|
FROMWEB: 'Aus dem Web'
|
||||||
FindInFolder: 'In Ordner suchen'
|
FindInFolder: 'In Ordner suchen'
|
||||||
IMAGEALT: 'Alternativtext (alt)'
|
IMAGEALT: 'Alternativtext (alt)'
|
||||||
|
IMAGEALTTEXT: 'Alternativtext (alt) - erscheint, falls das Bild nicht angezeigt werden kann.'
|
||||||
IMAGEDIMENSIONS: Dimensionen
|
IMAGEDIMENSIONS: Dimensionen
|
||||||
IMAGEHEIGHTPX: Höhe (px)
|
IMAGEHEIGHTPX: Höhe (px)
|
||||||
IMAGETITLE: 'Titeltext (Tooltip) - für zusätzliche Informationen über das Bild'
|
IMAGETITLE: 'Titeltext (Tooltip) - für zusätzliche Informationen über das Bild'
|
||||||
@ -325,7 +327,11 @@ de:
|
|||||||
DELETED: Gelöscht.
|
DELETED: Gelöscht.
|
||||||
DropdownBatchActionsDefault: Aktionen
|
DropdownBatchActionsDefault: Aktionen
|
||||||
HELP: Hilfe
|
HELP: Hilfe
|
||||||
|
PAGETYPE: 'Seitentyp:'
|
||||||
PERMAGAIN: 'Sie wurden aus dem System ausgeloggt. Falls Sie sich wieder einloggen möchten, geben Sie bitte Benutzernamen und Passwort im untenstehenden Formular an.'
|
PERMAGAIN: 'Sie wurden aus dem System ausgeloggt. Falls Sie sich wieder einloggen möchten, geben Sie bitte Benutzernamen und Passwort im untenstehenden Formular an.'
|
||||||
|
PERMALREADY: 'Leider dürfen Sie diesen Teil des CMS nicht aufrufen. Wenn Sie sich als jemand anderes einloggen wollen, benutzen Sie bitte das nachstehende Formular.'
|
||||||
|
PERMDEFAULT: 'Sie müssen angemeldet sein, um auf diesen Bereich zugreifen zu können. Bitte geben Sie Ihre Zugangsdaten ein.'
|
||||||
|
PLEASESAVE: 'Diese Seite konnte nicht aktualisiert werden weil sie noch nicht gespeichert wurde - bitte speichern.'
|
||||||
PreviewButton: Vorschau
|
PreviewButton: Vorschau
|
||||||
REORGANISATIONSUCCESSFUL: 'Der Seitenbaum wurde erfolgreich sortiert.'
|
REORGANISATIONSUCCESSFUL: 'Der Seitenbaum wurde erfolgreich sortiert.'
|
||||||
SAVEDUP: Gespeichert.
|
SAVEDUP: Gespeichert.
|
||||||
@ -413,6 +419,7 @@ de:
|
|||||||
Toggle: 'Hilfe zur Formatierung anzeigen'
|
Toggle: 'Hilfe zur Formatierung anzeigen'
|
||||||
MemberImportForm:
|
MemberImportForm:
|
||||||
Help1: '<p>Mitglieder im <em>CSV</em>-Format (kommaseparierte Werte) importieren. <small><a href="#" class="toggle-advanced">Erweiterte Nutzung</a></small></p>'
|
Help1: '<p>Mitglieder im <em>CSV</em>-Format (kommaseparierte Werte) importieren. <small><a href="#" class="toggle-advanced">Erweiterte Nutzung</a></small></p>'
|
||||||
|
Help2: '<div class="advanced"><h4>Erweiterte Benutzung</h4><ul><li>Gültige Spalten: <em>%s</em></li><li>Bereits existierende Benutzer werden anhand ihres eindeutigen <em>Code</em> identifiziert und um neue Einträge aus der Importdatei erweitert.</li><li>Gruppen können in der Spalte <em>Gruppen</em> hinzugefügt werden. Gruppen werden anhand ihres <em>Code</em> erkannt. Mehrere Gruppen werden Komma-separiert eingetragen. Schon zugewiesene Gruppen werden nicht entfernt.</li></ul></div>'
|
||||||
ResultCreated: '{count} Mitglied(er) wurde(n) erstellt'
|
ResultCreated: '{count} Mitglied(er) wurde(n) erstellt'
|
||||||
ResultDeleted: '%d Mitglied(er) gelöscht'
|
ResultDeleted: '%d Mitglied(er) gelöscht'
|
||||||
ResultNone: 'Keine Änderungen'
|
ResultNone: 'Keine Änderungen'
|
||||||
|
@ -82,6 +82,7 @@ es:
|
|||||||
CMSSecurity:
|
CMSSecurity:
|
||||||
INVALIDUSER: '<p>Usuario inválido. <a target="_top" href="{link}">Por favor, vuelva a autenticar aquí</a> para continuar.</p>'
|
INVALIDUSER: '<p>Usuario inválido. <a target="_top" href="{link}">Por favor, vuelva a autenticar aquí</a> para continuar.</p>'
|
||||||
LoginMessage: '<p>Si Ud tiene cualquier trabajo sin guardar puede volver donde lo dejó, iniciando sesión más abajo.</p>'
|
LoginMessage: '<p>Si Ud tiene cualquier trabajo sin guardar puede volver donde lo dejó, iniciando sesión más abajo.</p>'
|
||||||
|
SUCCESS: Exito
|
||||||
SUCCESSCONTENT: '<p>Inicio de sesión exitoso. Si Ud no es automáticamente redireccionado, <a target="_top" href="{link}">haga clic aquí</a></p>'
|
SUCCESSCONTENT: '<p>Inicio de sesión exitoso. Si Ud no es automáticamente redireccionado, <a target="_top" href="{link}">haga clic aquí</a></p>'
|
||||||
TimedOutTitleAnonymous: 'Expiró su sesión.'
|
TimedOutTitleAnonymous: 'Expiró su sesión.'
|
||||||
TimedOutTitleMember: 'Eh {name}!<br />Tu sesión expiró.'
|
TimedOutTitleMember: 'Eh {name}!<br />Tu sesión expiró.'
|
||||||
@ -259,6 +260,7 @@ es:
|
|||||||
many_many_Members: Miembros
|
many_many_Members: Miembros
|
||||||
GroupImportForm:
|
GroupImportForm:
|
||||||
Help1: '<p>Importar uno o más grupos en formato <em>CSV</em> (valores separados por coma). <small><a href="#" class="toggle-advanced">Mostrar uso avanzado</a></small></p>'
|
Help1: '<p>Importar uno o más grupos en formato <em>CSV</em> (valores separados por coma). <small><a href="#" class="toggle-advanced">Mostrar uso avanzado</a></small></p>'
|
||||||
|
Help2: '<div class="advanced"><h4>Uso avanzado</h4><ul><li>Columnas permitidas: <em>%s</em></li><li>Grupos existentes son relacionados con su <em>Código único</em> y actualizados con cualquier nuevo valor desde el archivo importado</li><li>Jerarquías de grupo pueden ser creadas utilizando la columna <em>ParentCode</em>.</li><li>Códigos de permiso pueden ser asignados por la columna <em>PermissionCode</em>. Códigos de permisos existentes no son eliminados.</li></ul></div>'
|
||||||
ResultCreated: 'Creados {count} grupos'
|
ResultCreated: 'Creados {count} grupos'
|
||||||
ResultDeleted: 'Se eliminaron %d grupos'
|
ResultDeleted: 'Se eliminaron %d grupos'
|
||||||
ResultUpdated: 'Actualizados grupos %d'
|
ResultUpdated: 'Actualizados grupos %d'
|
||||||
@ -325,6 +327,8 @@ es:
|
|||||||
DropdownBatchActionsDefault: Acciones
|
DropdownBatchActionsDefault: Acciones
|
||||||
HELP: Ayuda
|
HELP: Ayuda
|
||||||
PERMAGAIN: 'Ha sido desconectado del CMS. Si quiere volver a entrar, introduzca su nombre de usuario y contraseña a continuación.'
|
PERMAGAIN: 'Ha sido desconectado del CMS. Si quiere volver a entrar, introduzca su nombre de usuario y contraseña a continuación.'
|
||||||
|
PERMALREADY: 'Lamentablemente no puede acceder a esta parte del CMS. Si quiere entrar como alguien distinto, hágalo a continuación'
|
||||||
|
PERMDEFAULT: 'Debes estar conectado para acceder al área de administración; por favor ingresa tus datos a continuación'
|
||||||
PreviewButton: Vista previa
|
PreviewButton: Vista previa
|
||||||
REORGANISATIONSUCCESSFUL: 'Reorganizado el árbol del sitio con éxito.'
|
REORGANISATIONSUCCESSFUL: 'Reorganizado el árbol del sitio con éxito.'
|
||||||
SAVEDUP: Guardado
|
SAVEDUP: Guardado
|
||||||
@ -412,6 +416,7 @@ es:
|
|||||||
Toggle: 'Cambiar'
|
Toggle: 'Cambiar'
|
||||||
MemberImportForm:
|
MemberImportForm:
|
||||||
Help1: '<p>Importar usuarios en <em>formato CSV</em> (valores separados por coma). <small><a href="#" class="toggle-advanced">Mostrar uso avanzado</a></small></p>'
|
Help1: '<p>Importar usuarios en <em>formato CSV</em> (valores separados por coma). <small><a href="#" class="toggle-advanced">Mostrar uso avanzado</a></small></p>'
|
||||||
|
Help2: '<div class="advanced"><h4>Uso avanzado</h4><ul><li>Columnas permitidas: <em>%s</em></li><li>Usuarios existentes son relacionados con su <em>Código único</em>, y actualizados con cualquier nuevo valor desde el archivo importado.</li><li>Grupos pueden ser asignados por la columna <em>Groups</em>. Grupos son identificados por su propiedad <em>Code</em>, multiples grupos pueden ser separados por una coma. La pertenencia a grupos existentes no se borra.</li></ul></div>'
|
||||||
ResultCreated: 'Creados {count} miembros'
|
ResultCreated: 'Creados {count} miembros'
|
||||||
ResultDeleted: 'Se eliminaron %d miembros'
|
ResultDeleted: 'Se eliminaron %d miembros'
|
||||||
ResultNone: 'No hay cambios'
|
ResultNone: 'No hay cambios'
|
||||||
@ -475,6 +480,7 @@ es:
|
|||||||
SINGULARNAME: Regla
|
SINGULARNAME: Regla
|
||||||
Title: Título
|
Title: Título
|
||||||
PermissionRoleCode:
|
PermissionRoleCode:
|
||||||
|
PLURALNAME: 'Códigos de permiso'
|
||||||
PermsError: 'No se puede asignar permisos privilegiados al código "% s" (requiere acceso de administrador)'
|
PermsError: 'No se puede asignar permisos privilegiados al código "% s" (requiere acceso de administrador)'
|
||||||
SINGULARNAME: 'Códigos de las regla de permisos'
|
SINGULARNAME: 'Códigos de las regla de permisos'
|
||||||
Permissions:
|
Permissions:
|
||||||
|
@ -251,9 +251,9 @@ fr:
|
|||||||
CAPTIONTEXT: 'Légende'
|
CAPTIONTEXT: 'Légende'
|
||||||
CSSCLASS: 'Alignement / Style'
|
CSSCLASS: 'Alignement / Style'
|
||||||
CSSCLASSCENTER: 'Centré'
|
CSSCLASSCENTER: 'Centré'
|
||||||
CSSCLASSLEFT: 'A gauche, avec texte à la ligne.'
|
CSSCLASSLEFT: 'À gauche, avec texte autour.'
|
||||||
CSSCLASSLEFTALONE: 'Sur la gauche seulement'
|
CSSCLASSLEFTALONE: 'Sur la gauche seulement'
|
||||||
CSSCLASSRIGHT: 'a droite, avec texte à la ligne.'
|
CSSCLASSRIGHT: 'À droite, avec texte autour.'
|
||||||
DETAILS: Détails
|
DETAILS: Détails
|
||||||
EMAIL: 'Adresse email'
|
EMAIL: 'Adresse email'
|
||||||
FILE: Fichier
|
FILE: Fichier
|
||||||
|
@ -326,6 +326,8 @@ it:
|
|||||||
DropdownBatchActionsDefault: Azioni
|
DropdownBatchActionsDefault: Azioni
|
||||||
HELP: Aiuto
|
HELP: Aiuto
|
||||||
PERMAGAIN: 'Sei stato disconnesso dal CMS. Se desideri autenticarti nuovamente, inserisci qui sotto nome utente e password.'
|
PERMAGAIN: 'Sei stato disconnesso dal CMS. Se desideri autenticarti nuovamente, inserisci qui sotto nome utente e password.'
|
||||||
|
PERMALREADY: 'Siamo spiacenti, ma non puoi accedere a questa sezione del CMS. Se desideri autenticarti come qualcun altro, fallo qui sotto.'
|
||||||
|
PERMDEFAULT: 'Devi essere autenticato per accedere all''area amministrativa; Per favore inserisci le tue credenziali qui sotto'
|
||||||
PreviewButton: Anteprima
|
PreviewButton: Anteprima
|
||||||
REORGANISATIONSUCCESSFUL: 'Albero del sito riorganizzato con successo.'
|
REORGANISATIONSUCCESSFUL: 'Albero del sito riorganizzato con successo.'
|
||||||
SAVEDUP: Salvato.
|
SAVEDUP: Salvato.
|
||||||
|
@ -292,8 +292,6 @@ sk:
|
|||||||
FROMWEB: 'Z webu'
|
FROMWEB: 'Z webu'
|
||||||
FindInFolder: 'Vyhľadať v priečinku'
|
FindInFolder: 'Vyhľadať v priečinku'
|
||||||
IMAGEALT: 'Atlernatívny text (alt)'
|
IMAGEALT: 'Atlernatívny text (alt)'
|
||||||
IMAGEALTTEXT: 'Atlernatívny text (alt) - zobrazí sa ak obrázok nemože byť zobrazený '
|
|
||||||
IMAGEALTTEXTDESC: 'Zobrazí sa na obrazovke, ak obrázok nemôže byť zobrazený'
|
|
||||||
IMAGEDIMENSIONS: Rozmery
|
IMAGEDIMENSIONS: Rozmery
|
||||||
IMAGEHEIGHTPX: Výška
|
IMAGEHEIGHTPX: Výška
|
||||||
IMAGETITLE: 'Text titulky (tooltip) - pre doplňujúce informácie o obrázku'
|
IMAGETITLE: 'Text titulky (tooltip) - pre doplňujúce informácie o obrázku'
|
||||||
@ -328,11 +326,9 @@ sk:
|
|||||||
DELETED: Zmazané.
|
DELETED: Zmazané.
|
||||||
DropdownBatchActionsDefault: Akcie
|
DropdownBatchActionsDefault: Akcie
|
||||||
HELP: Pomoc
|
HELP: Pomoc
|
||||||
PAGETYPE: 'Typ stránky:'
|
|
||||||
PERMAGAIN: 'Boli ste odhlásený'
|
PERMAGAIN: 'Boli ste odhlásený'
|
||||||
PERMALREADY: 'Je mi ľúto, ale nemáte prístup k tejto časti CMS. Ak sa chcete prihlásiť ako niekto iný, urobte tak nižšie'
|
PERMALREADY: 'Je mi ľúto, ale nemáte prístup k tejto časti CMS. Ak sa chcete prihlásiť ako niekto iný, urobte tak nižšie'
|
||||||
PERMDEFAULT: 'Musíte byť prihlásený/á k prístupu do oblasti administrácie, zadajte vaše prihlasovacie údaje dole, prosím.'
|
PERMDEFAULT: 'Musíte byť prihlásený/á k prístupu do oblasti administrácie, zadajte vaše prihlasovacie údaje dole, prosím.'
|
||||||
PLEASESAVE: 'Uložte stránku, prosím. Táto stránka nemôže byť aktualizovaná, pretože eště nebola uložená.'
|
|
||||||
PreviewButton: Náhľad
|
PreviewButton: Náhľad
|
||||||
REORGANISATIONSUCCESSFUL: 'Strom webu bol reorganizovaný úspešne.'
|
REORGANISATIONSUCCESSFUL: 'Strom webu bol reorganizovaný úspešne.'
|
||||||
SAVEDUP: Uložené.
|
SAVEDUP: Uložené.
|
||||||
|
@ -43,6 +43,13 @@ class RSSFeedTest extends SapphireTest {
|
|||||||
$this->assertContains('<description>ItemC AltContent</description>', $content);
|
$this->assertContains('<description>ItemC AltContent</description>', $content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testLinkEncoding() {
|
||||||
|
$list = new ArrayList();
|
||||||
|
$rssFeed = new RSSFeed($list, "http://www.example.com/?param1=true¶m2=true", "Test RSS Feed");
|
||||||
|
$content = $rssFeed->outputToBrowser();
|
||||||
|
$this->assertContains('<link>http://www.example.com/?param1=true&param2=true', $content);
|
||||||
|
}
|
||||||
|
|
||||||
public function testRSSFeedWithShortcode() {
|
public function testRSSFeedWithShortcode() {
|
||||||
$list = new ArrayList();
|
$list = new ArrayList();
|
||||||
$list->push(new RSSFeedTest_ItemD());
|
$list->push(new RSSFeedTest_ItemD());
|
||||||
|
@ -235,6 +235,7 @@ class FormTest extends FunctionalTest {
|
|||||||
'FormTest_Controller/Form',
|
'FormTest_Controller/Form',
|
||||||
array(
|
array(
|
||||||
'Email' => 'invalid',
|
'Email' => 'invalid',
|
||||||
|
'Number' => '<a href="http://mysite.com">link</a>' // XSS attempt
|
||||||
// leaving out "Required" field
|
// leaving out "Required" field
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -253,6 +254,17 @@ class FormTest extends FunctionalTest {
|
|||||||
),
|
),
|
||||||
'Required fields show a notification on field when left blank'
|
'Required fields show a notification on field when left blank'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$this->assertContains(
|
||||||
|
''<a href="http://mysite.com">link</a>' is not a number, only numbers can be accepted for this field',
|
||||||
|
$response->getBody(),
|
||||||
|
"Validation messages are safely XML encoded"
|
||||||
|
);
|
||||||
|
$this->assertNotContains(
|
||||||
|
'<a href="http://mysite.com">link</a>',
|
||||||
|
$response->getBody(),
|
||||||
|
"Unsafe content is not emitted directly inside the response body"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSessionSuccessMessage() {
|
public function testSessionSuccessMessage() {
|
||||||
@ -685,7 +697,8 @@ class FormTest_Controller extends Controller implements TestOnly {
|
|||||||
new FieldList(
|
new FieldList(
|
||||||
new EmailField('Email'),
|
new EmailField('Email'),
|
||||||
new TextField('SomeRequiredField'),
|
new TextField('SomeRequiredField'),
|
||||||
new CheckboxSetField('Boxes', null, array('1'=>'one','2'=>'two'))
|
new CheckboxSetField('Boxes', null, array('1'=>'one','2'=>'two')),
|
||||||
|
new NumericField('Number')
|
||||||
),
|
),
|
||||||
new FieldList(
|
new FieldList(
|
||||||
new FormAction('doSubmit')
|
new FormAction('doSubmit')
|
||||||
|
71
tests/forms/HtmlEditorFieldToolbarTest.php
Normal file
71
tests/forms/HtmlEditorFieldToolbarTest.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class HtmlEditorFieldToolbarTest_Toolbar extends HtmlEditorField_Toolbar {
|
||||||
|
public function viewfile_getLocalFileByID($id) {
|
||||||
|
return parent::viewfile_getLocalFileByID($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function viewfile_getLocalFileByURL($fileUrl) {
|
||||||
|
return parent::viewfile_getLocalFileByURL($fileUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function viewfile_getRemoteFileByURL($fileUrl) {
|
||||||
|
return parent::viewfile_getRemoteFileByURL($fileUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HtmlEditorFieldToolbarTest extends SapphireTest {
|
||||||
|
|
||||||
|
protected static $fixture_file = 'HtmlEditorFieldToolbarTest.yml';
|
||||||
|
|
||||||
|
protected function getToolbar() {
|
||||||
|
return new HtmlEditorFieldToolbarTest_Toolbar(null, '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUp() {
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
Config::nest();
|
||||||
|
Config::inst()->update('HtmlEditorField_Toolbar', 'fileurl_scheme_whitelist', array('http'));
|
||||||
|
Config::inst()->update('HtmlEditorField_Toolbar', 'fileurl_domain_whitelist', array('example.com'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tearDown() {
|
||||||
|
Config::unnest();
|
||||||
|
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testValidLocalReference() {
|
||||||
|
list($file, $url) = $this->getToolbar()->viewfile_getLocalFileByURL('folder/subfolder/example.pdf');
|
||||||
|
$this->assertEquals($this->objFromFixture('File', 'example_file'), $file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvalidLocalReference() {
|
||||||
|
list($file, $url) = $this->getToolbar()->viewfile_getLocalFileByURL('folder/subfolder/missing.pdf');
|
||||||
|
$this->assertNull($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testValidScheme() {
|
||||||
|
list($file, $url) = $this->getToolbar()->viewfile_getRemoteFileByURL('http://example.com/test.pdf');
|
||||||
|
$this->assertInstanceOf('File', $file);
|
||||||
|
$this->assertEquals($file->Filename, 'http://example.com/test.pdf');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @expectedException SS_HTTPResponse_Exception */
|
||||||
|
public function testInvalidScheme() {
|
||||||
|
list($file, $url) = $this->getToolbar()->viewfile_getRemoteFileByURL('nosuchscheme://example.com/test.pdf');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testValidDomain() {
|
||||||
|
list($file, $url) = $this->getToolbar()->viewfile_getRemoteFileByURL('http://example.com/test.pdf');
|
||||||
|
$this->assertInstanceOf('File', $file);
|
||||||
|
$this->assertEquals($file->Filename, 'http://example.com/test.pdf');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @expectedException SS_HTTPResponse_Exception */
|
||||||
|
public function testInvalidDomain() {
|
||||||
|
list($file, $url) = $this->getToolbar()->viewfile_getRemoteFileByURL('http://evil.com/test.pdf');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
9
tests/forms/HtmlEditorFieldToolbarTest.yml
Normal file
9
tests/forms/HtmlEditorFieldToolbarTest.yml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
File:
|
||||||
|
example_file:
|
||||||
|
Name: example.pdf
|
||||||
|
Filename: folder/subfolder/example.pdf
|
||||||
|
|
||||||
|
Image:
|
||||||
|
example_image:
|
||||||
|
Name: HTMLEditorFieldTest_example.jpg
|
||||||
|
Filename: tests/forms/images/HTMLEditorFieldTest_example.jpg
|
@ -2,6 +2,13 @@
|
|||||||
|
|
||||||
class SSViewerTest extends SapphireTest {
|
class SSViewerTest extends SapphireTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Backup of $_SERVER global
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $oldServer = array();
|
||||||
|
|
||||||
protected $extraDataObjects = array(
|
protected $extraDataObjects = array(
|
||||||
'SSViewerTest_Object',
|
'SSViewerTest_Object',
|
||||||
);
|
);
|
||||||
@ -10,6 +17,12 @@ class SSViewerTest extends SapphireTest {
|
|||||||
parent::setUp();
|
parent::setUp();
|
||||||
Config::inst()->update('SSViewer', 'source_file_comments', false);
|
Config::inst()->update('SSViewer', 'source_file_comments', false);
|
||||||
Config::inst()->update('SSViewer_FromString', 'cache_template', false);
|
Config::inst()->update('SSViewer_FromString', 'cache_template', false);
|
||||||
|
$this->oldServer = $_SERVER;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tearDown() {
|
||||||
|
$_SERVER = $this->oldServer;
|
||||||
|
parent::tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1156,10 +1169,13 @@ after')
|
|||||||
$orig = Config::inst()->get('SSViewer', 'rewrite_hash_links');
|
$orig = Config::inst()->get('SSViewer', 'rewrite_hash_links');
|
||||||
Config::inst()->update('SSViewer', 'rewrite_hash_links', true);
|
Config::inst()->update('SSViewer', 'rewrite_hash_links', true);
|
||||||
|
|
||||||
$_SERVER['REQUEST_URI'] = 'http://path/to/file?foo"onclick="alert(\'xss\')""';
|
$_SERVER['HTTP_HOST'] = 'www.mysite.com';
|
||||||
|
$_SERVER['REQUEST_URI'] = '//file.com?foo"onclick="alert(\'xss\')""';
|
||||||
|
|
||||||
// Emulate SSViewer::process()
|
// Emulate SSViewer::process()
|
||||||
$base = Convert::raw2att($_SERVER['REQUEST_URI']);
|
// Note that leading double slashes have been rewritten to prevent these being mis-interepreted
|
||||||
|
// as protocol-less absolute urls
|
||||||
|
$base = Convert::raw2att('/file.com?foo"onclick="alert(\'xss\')""');
|
||||||
|
|
||||||
$tmplFile = TEMP_FOLDER . '/SSViewerTest_testRewriteHashlinks_' . sha1(rand()) . '.ss';
|
$tmplFile = TEMP_FOLDER . '/SSViewerTest_testRewriteHashlinks_' . sha1(rand()) . '.ss';
|
||||||
|
|
||||||
@ -1227,10 +1243,11 @@ after')
|
|||||||
$obj = new ViewableData();
|
$obj = new ViewableData();
|
||||||
$obj->InsertedLink = '<a class="inserted" href="#anchor">InsertedLink</a>';
|
$obj->InsertedLink = '<a class="inserted" href="#anchor">InsertedLink</a>';
|
||||||
$result = $tmpl->process($obj);
|
$result = $tmpl->process($obj);
|
||||||
$this->assertContains(
|
|
||||||
'<a class="inserted" href="<?php echo Convert::raw2att(',
|
$code = <<<'EOC'
|
||||||
$result
|
<a class="inserted" href="<?php echo Convert::raw2att(preg_replace("/^(\/)+/", "/", $_SERVER['REQUEST_URI'])); ?>#anchor">InsertedLink</a>
|
||||||
);
|
EOC;
|
||||||
|
$this->assertContains($code, $result);
|
||||||
// TODO Fix inline links in PHP mode
|
// TODO Fix inline links in PHP mode
|
||||||
// $this->assertContains(
|
// $this->assertContains(
|
||||||
// '<a class="inline" href="<?php echo str_replace(',
|
// '<a class="inline" href="<?php echo str_replace(',
|
||||||
|
@ -4681,11 +4681,15 @@ class SSTemplateParser extends Parser implements TemplateParser {
|
|||||||
|
|
||||||
// TODO: This is pretty ugly & gets applied on all files not just html. I wonder if we can make this
|
// TODO: This is pretty ugly & gets applied on all files not just html. I wonder if we can make this
|
||||||
// non-dynamically calculated
|
// non-dynamically calculated
|
||||||
|
$code = <<<'EOC'
|
||||||
|
(\Config::inst()->get('SSViewer', 'rewrite_hash_links')
|
||||||
|
? \Convert::raw2att( preg_replace("/^(\\/)+/", "/", $_SERVER['REQUEST_URI'] ) )
|
||||||
|
: "")
|
||||||
|
EOC;
|
||||||
|
// Because preg_replace replacement requires escaped slashes, addcslashes here
|
||||||
$text = preg_replace(
|
$text = preg_replace(
|
||||||
'/(<a[^>]+href *= *)"#/i',
|
'/(<a[^>]+href *= *)"#/i',
|
||||||
'\\1"\' . (Config::inst()->get(\'SSViewer\', \'rewrite_hash_links\') ?' .
|
'\\1"\' . ' . addcslashes($code, '\\') . ' . \'#',
|
||||||
' Convert::raw2att( $_SERVER[\'REQUEST_URI\'] ) : "") .
|
|
||||||
\'#',
|
|
||||||
$text
|
$text
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1135,11 +1135,15 @@ class SSTemplateParser extends Parser implements TemplateParser {
|
|||||||
|
|
||||||
// TODO: This is pretty ugly & gets applied on all files not just html. I wonder if we can make this
|
// TODO: This is pretty ugly & gets applied on all files not just html. I wonder if we can make this
|
||||||
// non-dynamically calculated
|
// non-dynamically calculated
|
||||||
|
$code = <<<'EOC'
|
||||||
|
(\Config::inst()->get('SSViewer', 'rewrite_hash_links')
|
||||||
|
? \Convert::raw2att( preg_replace("/^(\\/)+/", "/", $_SERVER['REQUEST_URI'] ) )
|
||||||
|
: "")
|
||||||
|
EOC;
|
||||||
|
// Because preg_replace replacement requires escaped slashes, addcslashes here
|
||||||
$text = preg_replace(
|
$text = preg_replace(
|
||||||
'/(<a[^>]+href *= *)"#/i',
|
'/(<a[^>]+href *= *)"#/i',
|
||||||
'\\1"\' . (Config::inst()->get(\'SSViewer\', \'rewrite_hash_links\') ?' .
|
'\\1"\' . ' . addcslashes($code, '\\') . ' . \'#',
|
||||||
' Convert::raw2att( $_SERVER[\'REQUEST_URI\'] ) : "") .
|
|
||||||
\'#',
|
|
||||||
$text
|
$text
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1129,10 +1129,10 @@ class SSViewer implements Flushable {
|
|||||||
$rewrite = Config::inst()->get('SSViewer', 'rewrite_hash_links');
|
$rewrite = Config::inst()->get('SSViewer', 'rewrite_hash_links');
|
||||||
if($this->rewriteHashlinks && $rewrite) {
|
if($this->rewriteHashlinks && $rewrite) {
|
||||||
if(strpos($output, '<base') !== false) {
|
if(strpos($output, '<base') !== false) {
|
||||||
if($rewrite === 'php') {
|
if($rewrite === 'php') {
|
||||||
$thisURLRelativeToBase = "<?php echo Convert::raw2att(\$_SERVER['REQUEST_URI']); ?>";
|
$thisURLRelativeToBase = "<?php echo Convert::raw2att(preg_replace(\"/^(\\\\/)+/\", \"/\", \$_SERVER['REQUEST_URI'])); ?>";
|
||||||
} else {
|
} else {
|
||||||
$thisURLRelativeToBase = Convert::raw2att($_SERVER['REQUEST_URI']);
|
$thisURLRelativeToBase = Convert::raw2att(preg_replace("/^(\\/)+/", "/", $_SERVER['REQUEST_URI']));
|
||||||
}
|
}
|
||||||
|
|
||||||
$output = preg_replace('/(<a[^>]+href *= *)"#/i', '\\1"' . $thisURLRelativeToBase . '#', $output);
|
$output = preg_replace('/(<a[^>]+href *= *)"#/i', '\\1"' . $thisURLRelativeToBase . '#', $output);
|
||||||
|
Loading…
Reference in New Issue
Block a user