From b338efe5a755503527c38baedb73f2ffee503d7d Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Wed, 11 Nov 2015 16:07:20 +1300 Subject: [PATCH 01/11] Update translations --- admin/javascript/lang/de.js | 2 +- admin/javascript/lang/ro.js | 4 ++-- admin/javascript/lang/src/de.js | 2 +- admin/javascript/lang/src/ro.js | 4 ++-- lang/cs.yml | 4 ---- lang/de.yml | 8 ++++++++ lang/es.yml | 10 ++++++++++ lang/fr.yml | 4 ++-- lang/it.yml | 3 +++ lang/lt.yml | 2 +- lang/sk.yml | 4 ---- 11 files changed, 30 insertions(+), 17 deletions(-) diff --git a/admin/javascript/lang/de.js b/admin/javascript/lang/de.js index d43b2335a..65eb96fb2 100644 --- a/admin/javascript/lang/de.js +++ b/admin/javascript/lang/de.js @@ -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_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_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?", "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.", diff --git a/admin/javascript/lang/ro.js b/admin/javascript/lang/ro.js index c5895f4ab..733561e71 100644 --- a/admin/javascript/lang/ro.js +++ b/admin/javascript/lang/ro.js @@ -4,8 +4,8 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined'); } else { ss.i18n.addDictionary('ro', { - "CMSMAIN.SELECTONEPAGE": "Please select at least one page", - "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to unpublish", + "CMSMAIN.SELECTONEPAGE": "Vă rugăm să selectaţi cel puțin o pagină.", + "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_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.", diff --git a/admin/javascript/lang/src/de.js b/admin/javascript/lang/src/de.js index 9f10852dd..5599a84af 100644 --- a/admin/javascript/lang/src/de.js +++ b/admin/javascript/lang/src/de.js @@ -4,7 +4,7 @@ "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_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?", "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.", diff --git a/admin/javascript/lang/src/ro.js b/admin/javascript/lang/src/ro.js index 43d6cba2c..2488400ea 100644 --- a/admin/javascript/lang/src/ro.js +++ b/admin/javascript/lang/src/ro.js @@ -1,6 +1,6 @@ { - "CMSMAIN.SELECTONEPAGE": "Please select at least one page", - "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to unpublish", + "CMSMAIN.SELECTONEPAGE": "Vă rugăm să selectaţi cel puțin o pagină.", + "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_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.", diff --git a/lang/cs.yml b/lang/cs.yml index 710dff459..a96f65879 100644 --- a/lang/cs.yml +++ b/lang/cs.yml @@ -292,8 +292,6 @@ cs: FROMWEB: 'Z webu' FindInFolder: 'Hledat ve složce' 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 IMAGEHEIGHTPX: Výška IMAGETITLE: 'Titul text (tooltip) - další informace o obrázku' @@ -328,11 +326,9 @@ cs: DELETED: Smazáno. DropdownBatchActionsDefault: Akcie 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.' 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.' - 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 REORGANISATIONSUCCESSFUL: 'Strom webu reorganizován úspěšně.' SAVEDUP: Uloženo. diff --git a/lang/de.yml b/lang/de.yml index 15f637333..037954c17 100644 --- a/lang/de.yml +++ b/lang/de.yml @@ -260,6 +260,7 @@ de: many_many_Members: Mitglieder GroupImportForm: Help1: '

Eine oder mehrere Gruppen im CSV-Format (kommaseparierte Werte) importieren. Erweiterte Nutzung

' + Help2: '

Erweiterte Benutzung

' ResultCreated: '{count} Gruppe(n) wurden erstellt' ResultDeleted: '%d Gruppe(n) gelöscht' ResultUpdated: '%d Gruppe(n) aktualisiert' @@ -291,6 +292,8 @@ de: FROMWEB: 'Aus dem Web' FindInFolder: 'In Ordner suchen' IMAGEALT: 'Alternativtext (alt)' + IMAGEALTTEXT: 'Alternativtext (alt) - erscheint, falls das Bild nicht angezeigt werden kann.' + IMAGEALTTEXTDESC: 'Wird von Screenreadern vorgelesen oder angezeigt, falls das Bild nicht angezeigt werden kann.' IMAGEDIMENSIONS: Dimensionen IMAGEHEIGHTPX: Höhe (px) IMAGETITLE: 'Titeltext (Tooltip) - für zusätzliche Informationen über das Bild' @@ -325,7 +328,11 @@ de: DELETED: Gelöscht. DropdownBatchActionsDefault: Aktionen 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.' + 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 REORGANISATIONSUCCESSFUL: 'Der Seitenbaum wurde erfolgreich sortiert.' SAVEDUP: Gespeichert. @@ -413,6 +420,7 @@ de: Toggle: 'Hilfe zur Formatierung anzeigen' MemberImportForm: Help1: '

Mitglieder im CSV-Format (kommaseparierte Werte) importieren. Erweiterte Nutzung

' + Help2: '

Erweiterte Benutzung

' ResultCreated: '{count} Mitglied(er) wurde(n) erstellt' ResultDeleted: '%d Mitglied(er) gelöscht' ResultNone: 'Keine Änderungen' diff --git a/lang/es.yml b/lang/es.yml index 427098d8f..b56ec237f 100644 --- a/lang/es.yml +++ b/lang/es.yml @@ -82,6 +82,7 @@ es: CMSSecurity: INVALIDUSER: '

Usuario inválido. Por favor, vuelva a autenticar aquí para continuar.

' LoginMessage: '

Si Ud tiene cualquier trabajo sin guardar puede volver donde lo dejó, iniciando sesión más abajo.

' + SUCCESS: Exito SUCCESSCONTENT: '

Inicio de sesión exitoso. Si Ud no es automáticamente redireccionado, haga clic aquí

' TimedOutTitleAnonymous: 'Expiró su sesión.' TimedOutTitleMember: 'Eh {name}!
Tu sesión expiró.' @@ -259,6 +260,7 @@ es: many_many_Members: Miembros GroupImportForm: Help1: '

Importar uno o más grupos en formato CSV (valores separados por coma). Mostrar uso avanzado

' + Help2: '

Uso avanzado

' ResultCreated: 'Creados {count} grupos' ResultDeleted: 'Se eliminaron %d grupos' ResultUpdated: 'Actualizados grupos %d' @@ -290,6 +292,8 @@ es: FROMWEB: 'Desde la web' FindInFolder: 'Buscar en carpeta' IMAGEALT: 'Texto alternativo (alt)' + IMAGEALTTEXT: 'Texto alternativo (alt) - es mostrado si la imagen no puede ser visualizada' + IMAGEALTTEXTDESC: 'Mostrado a los lectores de pantalla o si la imagen no se puede visualizar' IMAGEDIMENSIONS: Dimensiones IMAGEHEIGHTPX: Alto IMAGETITLE: 'Texto del título (tooltip) - para obtener más información acerca de la imagen' @@ -324,7 +328,11 @@ es: DELETED: Borrado DropdownBatchActionsDefault: Acciones HELP: Ayuda + PAGETYPE: 'Tipo de página' 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' + PLEASESAVE: 'Por favor Guarde la Página: Esta página no se ha podido actualizar porque aún no ha sido salvada' PreviewButton: Vista previa REORGANISATIONSUCCESSFUL: 'Reorganizado el árbol del sitio con éxito.' SAVEDUP: Guardado @@ -412,6 +420,7 @@ es: Toggle: 'Cambiar' MemberImportForm: Help1: '

Importar usuarios en formato CSV (valores separados por coma). Mostrar uso avanzado

' + Help2: '

Uso avanzado

' ResultCreated: 'Creados {count} miembros' ResultDeleted: 'Se eliminaron %d miembros' ResultNone: 'No hay cambios' @@ -475,6 +484,7 @@ es: SINGULARNAME: Regla Title: Título PermissionRoleCode: + PLURALNAME: 'Códigos de permiso' PermsError: 'No se puede asignar permisos privilegiados al código "% s" (requiere acceso de administrador)' SINGULARNAME: 'Códigos de las regla de permisos' Permissions: diff --git a/lang/fr.yml b/lang/fr.yml index 745b53d73..952d44c99 100644 --- a/lang/fr.yml +++ b/lang/fr.yml @@ -251,9 +251,9 @@ fr: CAPTIONTEXT: 'Légende' CSSCLASS: 'Alignement / Style' CSSCLASSCENTER: 'Centré' - CSSCLASSLEFT: 'A gauche, avec texte à la ligne.' + CSSCLASSLEFT: 'À gauche, avec texte autour.' CSSCLASSLEFTALONE: 'Sur la gauche seulement' - CSSCLASSRIGHT: 'a droite, avec texte à la ligne.' + CSSCLASSRIGHT: 'À droite, avec texte autour.' DETAILS: Détails EMAIL: 'Adresse email' FILE: Fichier diff --git a/lang/it.yml b/lang/it.yml index 17627d5cb..f79e319b9 100644 --- a/lang/it.yml +++ b/lang/it.yml @@ -325,7 +325,10 @@ it: DELETED: Eliminato. DropdownBatchActionsDefault: Azioni HELP: Aiuto + PAGETYPE: 'Tipo di pagina' 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 REORGANISATIONSUCCESSFUL: 'Albero del sito riorganizzato con successo.' SAVEDUP: Salvato. diff --git a/lang/lt.yml b/lang/lt.yml index 1725617f3..9da6bb6c9 100644 --- a/lang/lt.yml +++ b/lang/lt.yml @@ -328,7 +328,7 @@ lt: DELETED: Ištrinta. DropdownBatchActionsDefault: Veiksmai HELP: Pagalba - PAGETYPE: 'Puslapio tipas:' + PAGETYPE: 'Puslapio tipas' PERMAGAIN: 'Jūs atsijungėte. Norėdami vėl prisijungti, įveskite savo duomenis į žemiau esančius laukelius.' PERMALREADY: 'Deja, bet Jūs negalite patekti į šią TVS dalį. Jeigu norite prisijungti kitu vartotoju, tai atlikite žemiau.' PERMDEFAULT: 'Jūs turite būti prisijungę, norėdami pasiekti administravimo zoną; prašome suvesti prisijungimo duomenis į žemiau esančius laukelius.' diff --git a/lang/sk.yml b/lang/sk.yml index f46181354..91f68461c 100644 --- a/lang/sk.yml +++ b/lang/sk.yml @@ -292,8 +292,6 @@ sk: FROMWEB: 'Z webu' FindInFolder: 'Vyhľadať v priečinku' 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 IMAGEHEIGHTPX: Výška IMAGETITLE: 'Text titulky (tooltip) - pre doplňujúce informácie o obrázku' @@ -328,11 +326,9 @@ sk: DELETED: Zmazané. DropdownBatchActionsDefault: Akcie HELP: Pomoc - PAGETYPE: 'Typ stránky:' 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' 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 REORGANISATIONSUCCESSFUL: 'Strom webu bol reorganizovaný úspešne.' SAVEDUP: Uložené. From 132e9b3e2fad361ebb4b502b6a37d34d013bfba3 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Thu, 29 Oct 2015 11:53:44 +1300 Subject: [PATCH 02/11] [ss-2015-021] Fix rewrite hash links XSS --- tests/view/SSViewerTest.php | 29 +++++++++++++++++++++++------ view/SSTemplateParser.php | 10 +++++++--- view/SSTemplateParser.php.inc | 10 +++++++--- view/SSViewer.php | 6 +++--- 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/tests/view/SSViewerTest.php b/tests/view/SSViewerTest.php index 39a3dd412..a816f6802 100644 --- a/tests/view/SSViewerTest.php +++ b/tests/view/SSViewerTest.php @@ -2,6 +2,13 @@ class SSViewerTest extends SapphireTest { + /** + * Backup of $_SERVER global + * + * @var array + */ + protected $oldServer = array(); + protected $extraDataObjects = array( 'SSViewerTest_Object', ); @@ -10,6 +17,12 @@ class SSViewerTest extends SapphireTest { parent::setUp(); Config::inst()->update('SSViewer', 'source_file_comments', 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'); 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() - $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'; @@ -1227,10 +1243,11 @@ after') $obj = new ViewableData(); $obj->InsertedLink = 'InsertedLink'; $result = $tmpl->process($obj); - $this->assertContains( - '#anchor">InsertedLink +EOC; + $this->assertContains($code, $result); // TODO Fix inline links in PHP mode // $this->assertContains( // ']+href *= *)"#/i', - '\\1"\' . (Config::inst()->get(\'SSViewer\', \'rewrite_hash_links\') ?' . - ' Convert::raw2att( $_SERVER[\'REQUEST_URI\'] ) : "") . - \'#', + '\\1"\' . ' . addcslashes($code, '\\') . ' . \'#', $text ); diff --git a/view/SSTemplateParser.php.inc b/view/SSTemplateParser.php.inc index bc7640669..d4a654082 100644 --- a/view/SSTemplateParser.php.inc +++ b/view/SSTemplateParser.php.inc @@ -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 // 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( '/(]+href *= *)"#/i', - '\\1"\' . (Config::inst()->get(\'SSViewer\', \'rewrite_hash_links\') ?' . - ' Convert::raw2att( $_SERVER[\'REQUEST_URI\'] ) : "") . - \'#', + '\\1"\' . ' . addcslashes($code, '\\') . ' . \'#', $text ); diff --git a/view/SSViewer.php b/view/SSViewer.php index f84343d84..9556906a7 100644 --- a/view/SSViewer.php +++ b/view/SSViewer.php @@ -1129,10 +1129,10 @@ class SSViewer implements Flushable { $rewrite = Config::inst()->get('SSViewer', 'rewrite_hash_links'); if($this->rewriteHashlinks && $rewrite) { if(strpos($output, '"; } else { - $thisURLRelativeToBase = Convert::raw2att($_SERVER['REQUEST_URI']); + $thisURLRelativeToBase = Convert::raw2att(preg_replace("/^(\\/)+/", "/", $_SERVER['REQUEST_URI'])); } $output = preg_replace('/(]+href *= *)"#/i', '\\1"' . $thisURLRelativeToBase . '#', $output); From 4f55b6a115ce0de8c5c258fb44eca52b8b112caf Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Mon, 2 Nov 2015 11:33:04 +1300 Subject: [PATCH 03/11] [ss-2015-022]: XML escape RSSFeed $link parameter --- api/RSSFeed.php | 1 + tests/api/RSSFeedTest.php | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/api/RSSFeed.php b/api/RSSFeed.php index 12174d9c9..22d6d704e 100644 --- a/api/RSSFeed.php +++ b/api/RSSFeed.php @@ -16,6 +16,7 @@ class RSSFeed extends ViewableData { private static $casting = array( "Title" => "Varchar", "Description" => "Varchar", + "Link" => "Varchar", ); /** diff --git a/tests/api/RSSFeedTest.php b/tests/api/RSSFeedTest.php index 0402bd30a..9bbf25927 100644 --- a/tests/api/RSSFeedTest.php +++ b/tests/api/RSSFeedTest.php @@ -43,6 +43,13 @@ class RSSFeedTest extends SapphireTest { $this->assertContains('ItemC AltContent', $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('http://www.example.com/?param1=true&param2=true', $content); + } + public function testRSSFeedWithShortcode() { $list = new ArrayList(); $list->push(new RSSFeedTest_ItemD()); From f290d869e01e0087286b4f2bc92e95d15c229c45 Mon Sep 17 00:00:00 2001 From: Hamish Friedlander Date: Tue, 10 Nov 2015 11:27:49 +1300 Subject: [PATCH 04/11] [ss-2015-025]: FIX Dont expose class on error --- control/RequestHandler.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/control/RequestHandler.php b/control/RequestHandler.php index 41f5eba60..17ffe4ab8 100644 --- a/control/RequestHandler.php +++ b/control/RequestHandler.php @@ -188,14 +188,14 @@ class RequestHandler extends ViewableData { 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 { 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'))) { - 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); } @@ -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. } 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; @@ -276,10 +276,10 @@ class RequestHandler extends ViewableData { * @return SS_HTTPResponse */ protected function handleAction($request, $action) { - $className = get_class($this); + $classMessage = Director::isLive() ? 'on this handler' : 'on class '.get_class($this); 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); From bc1b2893accba6401c03f9ea3b0cbc4621c7a02c Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Wed, 11 Nov 2015 15:18:26 +1300 Subject: [PATCH 05/11] [ss-2015-026]: BUG Fix FormField error messages not being encoded safely --- docs/en/04_Changelogs/3.2.1.md | 25 +++++++++++++++++++++++++ forms/Form.php | 12 ++++++++++++ tests/forms/FormTest.php | 15 ++++++++++++++- 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 docs/en/04_Changelogs/3.2.1.md diff --git a/docs/en/04_Changelogs/3.2.1.md b/docs/en/04_Changelogs/3.2.1.md new file mode 100644 index 000000000..aa68c7e72 --- /dev/null +++ b/docs/en/04_Changelogs/3.2.1.md @@ -0,0 +1,25 @@ +# 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 this page") + ); + } + } + + diff --git a/forms/Form.php b/forms/Form.php index 5b24754ac..0714aceef 100644 --- a/forms/Form.php +++ b/forms/Form.php @@ -1303,6 +1303,18 @@ class Form extends RequestHandler { // Load errors into session and post back $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()}.data", $data); diff --git a/tests/forms/FormTest.php b/tests/forms/FormTest.php index 409bac60a..f9349665b 100644 --- a/tests/forms/FormTest.php +++ b/tests/forms/FormTest.php @@ -235,6 +235,7 @@ class FormTest extends FunctionalTest { 'FormTest_Controller/Form', array( 'Email' => 'invalid', + 'Number' => 'link' // XSS attempt // leaving out "Required" field ) ); @@ -253,6 +254,17 @@ class FormTest extends FunctionalTest { ), '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( + 'link', + $response->getBody(), + "Unsafe content is not emitted directly inside the response body" + ); } public function testSessionSuccessMessage() { @@ -685,7 +697,8 @@ class FormTest_Controller extends Controller implements TestOnly { new FieldList( new EmailField('Email'), 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 FormAction('doSubmit') From 1c1c0a23bdf21df0d57ff5d3185cbbca5aef20da Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Wed, 11 Nov 2015 17:02:05 +1300 Subject: [PATCH 06/11] Added 3.2.1-rc1 changelog --- docs/en/04_Changelogs/rc/3.2.1-rc1.md | 34 +++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 docs/en/04_Changelogs/rc/3.2.1-rc1.md diff --git a/docs/en/04_Changelogs/rc/3.2.1-rc1.md b/docs/en/04_Changelogs/rc/3.2.1-rc1.md new file mode 100644 index 000000000..05f1b2a18 --- /dev/null +++ b/docs/en/04_Changelogs/rc/3.2.1-rc1.md @@ -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 + + + +## 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) From b61d6dcd57577b0345af7a69e51da409305e1957 Mon Sep 17 00:00:00 2001 From: Hamish Friedlander Date: Fri, 13 Nov 2015 10:51:13 +1300 Subject: [PATCH 07/11] [ss-2015-027]: FIX HtmlEditorField_Toolbar#viewfile not whitelisting URLs --- .../Field_types/03_HTMLEditorField.md | 12 +++ forms/HtmlEditorField.php | 100 ++++++++++++++---- tests/forms/HtmlEditorFieldToolbarTest.php | 71 +++++++++++++ tests/forms/HtmlEditorFieldToolbarTest.yml | 9 ++ 4 files changed, 171 insertions(+), 21 deletions(-) create mode 100644 tests/forms/HtmlEditorFieldToolbarTest.php create mode 100644 tests/forms/HtmlEditorFieldToolbarTest.yml diff --git a/docs/en/02_Developer_Guides/03_Forms/Field_types/03_HTMLEditorField.md b/docs/en/02_Developer_Guides/03_Forms/Field_types/03_HTMLEditorField.md index 13b276dde..b18938ca5 100644 --- a/docs/en/02_Developer_Guides/03_Forms/Field_types/03_HTMLEditorField.md +++ b/docs/en/02_Developer_Guides/03_Forms/Field_types/03_HTMLEditorField.md @@ -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". +## 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 Since TinyMCE generates markup, it needs to know which doctype your documents will be rendered in. You can set this diff --git a/forms/HtmlEditorField.php b/forms/HtmlEditorField.php index fad081a74..4bc987e9b 100644 --- a/forms/HtmlEditorField.php +++ b/forms/HtmlEditorField.php @@ -449,40 +449,98 @@ class HtmlEditorField_Toolbar extends RequestHandler { 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. */ public function viewfile($request) { + $file = null; + $url = null; // 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. - if($url = $request->getVar('FileURL')) { - if(Director::is_absolute_url($url) && !Director::is_site_url($url)) { - $url = $url; - $file = new File(array( - 'Title' => basename($url), - '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 - )); + if($fileUrl = $request->getVar('FileURL')) { + // If this isn't an absolute URL, or is, but is to this site, try and get the File object + // that is associated with it + if(!Director::is_absolute_url($fileUrl) || Director::is_site_url($fileUrl)) { + list($file, $url) = $this->viewfile_getLocalFileByURL($fileUrl); } - } elseif($id = $request->getVar('ID')) { - $file = DataObject::get_by_id('File', $id); - $url = $file->RelativeLink(); - } else { - throw new LogicException('Need either "ID" or "FileURL" parameter to identify the file'); + // If this is an absolute URL, but not to this site, use as an oembed source (after whitelisting URL) + else { + list($file, $url) = $this->viewfile_getRemoteFileByURL($fileUrl); + } + } + // 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 // Check if appCategory is an image and exists on the local system, otherwise use oEmbed to refference a // 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); } elseif(!Director::is_site_url($url)) { $fileWrapper = new HtmlEditorField_Embed($url, $file); diff --git a/tests/forms/HtmlEditorFieldToolbarTest.php b/tests/forms/HtmlEditorFieldToolbarTest.php new file mode 100644 index 000000000..6b661936d --- /dev/null +++ b/tests/forms/HtmlEditorFieldToolbarTest.php @@ -0,0 +1,71 @@ +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'); + } + +} \ No newline at end of file diff --git a/tests/forms/HtmlEditorFieldToolbarTest.yml b/tests/forms/HtmlEditorFieldToolbarTest.yml new file mode 100644 index 000000000..164c30844 --- /dev/null +++ b/tests/forms/HtmlEditorFieldToolbarTest.yml @@ -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 From 49acc0d468de7cc796bcde1c33108779e65876f4 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Fri, 13 Nov 2015 15:27:08 +1300 Subject: [PATCH 08/11] Added 3.2.1-rc2 changelog --- docs/en/04_Changelogs/rc/3.2.1-rc2.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 docs/en/04_Changelogs/rc/3.2.1-rc2.md diff --git a/docs/en/04_Changelogs/rc/3.2.1-rc2.md b/docs/en/04_Changelogs/rc/3.2.1-rc2.md new file mode 100644 index 000000000..55acd92c0 --- /dev/null +++ b/docs/en/04_Changelogs/rc/3.2.1-rc2.md @@ -0,0 +1,9 @@ +# 3.2.1-rc2 + + + +## 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) From c19420f545a32f86b843a6fb7c893482f7812ad3 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Fri, 13 Nov 2015 15:32:09 +1300 Subject: [PATCH 09/11] Add 3.2.1-rc2 changelog --- docs/en/04_Changelogs/rc/3.2.1-rc2.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/en/04_Changelogs/rc/3.2.1-rc2.md b/docs/en/04_Changelogs/rc/3.2.1-rc2.md index 55acd92c0..dd7690a64 100644 --- a/docs/en/04_Changelogs/rc/3.2.1-rc2.md +++ b/docs/en/04_Changelogs/rc/3.2.1-rc2.md @@ -1,5 +1,7 @@ # 3.2.1-rc2 +See [3.2.1](/changelogs/3.2.1) changelog for more information on what is new in 3.2.1 + ## Change Log From 3fe8b7479c0b4b04377fd333341fdb210ac6cf71 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Mon, 16 Nov 2015 16:01:52 +1300 Subject: [PATCH 10/11] Update translations --- lang/de.yml | 3 +-- lang/es.yml | 4 ---- lang/it.yml | 1 - lang/lt.yml | 2 +- 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/lang/de.yml b/lang/de.yml index 037954c17..de6f1f233 100644 --- a/lang/de.yml +++ b/lang/de.yml @@ -293,7 +293,6 @@ de: FindInFolder: 'In Ordner suchen' IMAGEALT: 'Alternativtext (alt)' IMAGEALTTEXT: 'Alternativtext (alt) - erscheint, falls das Bild nicht angezeigt werden kann.' - IMAGEALTTEXTDESC: 'Wird von Screenreadern vorgelesen oder angezeigt, falls das Bild nicht angezeigt werden kann.' IMAGEDIMENSIONS: Dimensionen IMAGEHEIGHTPX: Höhe (px) IMAGETITLE: 'Titeltext (Tooltip) - für zusätzliche Informationen über das Bild' @@ -328,7 +327,7 @@ de: DELETED: Gelöscht. DropdownBatchActionsDefault: Aktionen HELP: Hilfe - PAGETYPE: 'Seitentyp' + 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.' 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.' diff --git a/lang/es.yml b/lang/es.yml index b56ec237f..e2a3c3768 100644 --- a/lang/es.yml +++ b/lang/es.yml @@ -292,8 +292,6 @@ es: FROMWEB: 'Desde la web' FindInFolder: 'Buscar en carpeta' IMAGEALT: 'Texto alternativo (alt)' - IMAGEALTTEXT: 'Texto alternativo (alt) - es mostrado si la imagen no puede ser visualizada' - IMAGEALTTEXTDESC: 'Mostrado a los lectores de pantalla o si la imagen no se puede visualizar' IMAGEDIMENSIONS: Dimensiones IMAGEHEIGHTPX: Alto IMAGETITLE: 'Texto del título (tooltip) - para obtener más información acerca de la imagen' @@ -328,11 +326,9 @@ es: DELETED: Borrado DropdownBatchActionsDefault: Acciones HELP: Ayuda - PAGETYPE: 'Tipo de página' 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' - PLEASESAVE: 'Por favor Guarde la Página: Esta página no se ha podido actualizar porque aún no ha sido salvada' PreviewButton: Vista previa REORGANISATIONSUCCESSFUL: 'Reorganizado el árbol del sitio con éxito.' SAVEDUP: Guardado diff --git a/lang/it.yml b/lang/it.yml index f79e319b9..acef00d87 100644 --- a/lang/it.yml +++ b/lang/it.yml @@ -325,7 +325,6 @@ it: DELETED: Eliminato. DropdownBatchActionsDefault: Azioni HELP: Aiuto - PAGETYPE: 'Tipo di pagina' 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' diff --git a/lang/lt.yml b/lang/lt.yml index 9da6bb6c9..1725617f3 100644 --- a/lang/lt.yml +++ b/lang/lt.yml @@ -328,7 +328,7 @@ lt: DELETED: Ištrinta. DropdownBatchActionsDefault: Veiksmai HELP: Pagalba - PAGETYPE: 'Puslapio tipas' + PAGETYPE: 'Puslapio tipas:' PERMAGAIN: 'Jūs atsijungėte. Norėdami vėl prisijungti, įveskite savo duomenis į žemiau esančius laukelius.' PERMALREADY: 'Deja, bet Jūs negalite patekti į šią TVS dalį. Jeigu norite prisijungti kitu vartotoju, tai atlikite žemiau.' PERMDEFAULT: 'Jūs turite būti prisijungę, norėdami pasiekti administravimo zoną; prašome suvesti prisijungimo duomenis į žemiau esančius laukelius.' From 0178fa5a1873a0f1d6100268c86dab81a18c23a5 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Mon, 16 Nov 2015 16:17:10 +1300 Subject: [PATCH 11/11] Added 3.2.1 changelog --- docs/en/04_Changelogs/3.2.1.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/docs/en/04_Changelogs/3.2.1.md b/docs/en/04_Changelogs/3.2.1.md index aa68c7e72..542610874 100644 --- a/docs/en/04_Changelogs/3.2.1.md +++ b/docs/en/04_Changelogs/3.2.1.md @@ -23,3 +23,34 @@ For example: } + + +## 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)