Merge pull request #10651 from creative-commoners/pulls/5/merge-up-from-4

Merge up from 4 to 5
This commit is contained in:
Guy Sartorelli 2023-01-19 09:46:09 +13:00 committed by GitHub
commit a8c374becb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 337 additions and 34 deletions

View File

@ -5,7 +5,7 @@ en:
EDITINFO: 'Edit this file' EDITINFO: 'Edit this file'
REMOVE: Remove REMOVE: Remove
SilverStripe\Control\ChangePasswordEmail_ss: SilverStripe\Control\ChangePasswordEmail_ss:
CHANGEPASSWORDFOREMAIL: 'The password for account with email address {email} has been changed. If you didn''t change your password please change your password using the link below' CHANGEPASSWORDFOREMAIL: 'The password for account with email address {email} has been changed. If you didn\''t change your password please change your password using the link below'
CHANGEPASSWORDTEXT1: 'You changed your password for' CHANGEPASSWORDTEXT1: 'You changed your password for'
CHANGEPASSWORDTEXT3: 'Change password' CHANGEPASSWORDTEXT3: 'Change password'
HELLO: Hi HELLO: Hi
@ -143,12 +143,12 @@ en:
SilverStripe\Forms\TimeField: SilverStripe\Forms\TimeField:
VALIDATEFORMAT: 'Please enter a valid time format ({format})' VALIDATEFORMAT: 'Please enter a valid time format ({format})'
SilverStripe\ORM\DataObject: SilverStripe\ORM\DataObject:
GENERALSEARCH: 'General Search'
PLURALNAME: 'Data Objects' PLURALNAME: 'Data Objects'
PLURALS: PLURALS:
one: 'A Data Object' one: 'A Data Object'
other: '{count} Data Objects' other: '{count} Data Objects'
SINGULARNAME: 'Data Object' SINGULARNAME: 'Data Object'
GENERALSEARCH: 'General Search'
SilverStripe\ORM\FieldType\DBBoolean: SilverStripe\ORM\FieldType\DBBoolean:
ANY: Any ANY: Any
NOANSWER: 'No' NOANSWER: 'No'

View File

@ -236,6 +236,7 @@ eo:
Sort: 'Ordiga Ordo' Sort: 'Ordiga Ordo'
has_many_Permissions: Permesoj has_many_Permissions: Permesoj
many_many_Members: Membroj many_many_Members: Membroj
ValidationIdentifierAlreadyExists: 'Jam ekzistas grupo ({group}) kun la sama {identifier}'
SilverStripe\Security\LoginAttempt: SilverStripe\Security\LoginAttempt:
Email: 'Retpoŝta adreso' Email: 'Retpoŝta adreso'
EmailHashed: 'Retpoŝta adreso (haketa)' EmailHashed: 'Retpoŝta adreso (haketa)'

View File

@ -78,6 +78,7 @@ es:
PLURALS: PLURALS:
one: 'Un Objeto de Dato' one: 'Un Objeto de Dato'
other: '{count} Objetos de Datos' other: '{count} Objetos de Datos'
many: '{count} Objetos de Datos'
SINGULARNAME: 'Objeto de Dato' SINGULARNAME: 'Objeto de Dato'
SilverStripe\ORM\FieldType\DBBoolean: SilverStripe\ORM\FieldType\DBBoolean:
ANY: Cualquiera ANY: Cualquiera
@ -87,24 +88,30 @@ es:
DAYS_SHORT_PLURALS: DAYS_SHORT_PLURALS:
one: '{count} día' one: '{count} día'
other: '{count} días' other: '{count} días'
many: '{count} días'
HOURS_SHORT_PLURALS: HOURS_SHORT_PLURALS:
one: '{count} hora' one: '{count} hora'
other: '{count} horas' other: '{count} horas'
many: '{count} horas'
LessThanMinuteAgo: 'Hace menos de un minuto' LessThanMinuteAgo: 'Hace menos de un minuto'
MINUTES_SHORT_PLURALS: MINUTES_SHORT_PLURALS:
one: '{count} minuto' one: '{count} minuto'
other: '{count} minutos' other: '{count} minutos'
many: '{count} minutos'
MONTHS_SHORT_PLURALS: MONTHS_SHORT_PLURALS:
one: '{count} mes' one: '{count} mes'
other: '{count} meses' other: '{count} meses'
many: '{count} meses'
SECONDS_SHORT_PLURALS: SECONDS_SHORT_PLURALS:
one: '{count} segundo' one: '{count} segundo'
other: '{count} segundos' other: '{count} segundos'
many: '{count} segundos'
TIMEDIFFAGO: 'hace {difference}' TIMEDIFFAGO: 'hace {difference}'
TIMEDIFFIN: 'en {difference}' TIMEDIFFIN: 'en {difference}'
YEARS_SHORT_PLURALS: YEARS_SHORT_PLURALS:
one: '{count} año' one: '{count} año'
other: '{count} años' other: '{count} años'
many: '{count} años'
SilverStripe\ORM\FieldType\DBEnum: SilverStripe\ORM\FieldType\DBEnum:
ANY: Cualquiera ANY: Cualquiera
SilverStripe\ORM\Hierarchy\Hierarchy: SilverStripe\ORM\Hierarchy\Hierarchy:
@ -135,6 +142,7 @@ es:
PLURALS: PLURALS:
one: 'Un Grupo' one: 'Un Grupo'
other: '{count} Grupos' other: '{count} Grupos'
many: '{count} Grupos'
Parent: 'Grupo Padre' Parent: 'Grupo Padre'
RolesAddEditLink: 'Gestionar Roles' RolesAddEditLink: 'Gestionar Roles'
SINGULARNAME: Grupo SINGULARNAME: Grupo
@ -147,6 +155,7 @@ es:
PLURALS: PLURALS:
one: 'Un intento de inicio de sesión' one: 'Un intento de inicio de sesión'
other: '{count} Intentos de inicios de sesión' other: '{count} Intentos de inicios de sesión'
many: '{count} Intentos de inicios de sesión'
SINGULARNAME: 'Intento de ingreso' SINGULARNAME: 'Intento de ingreso'
Status: Estado Status: Estado
SilverStripe\Security\Member: SilverStripe\Security\Member:
@ -176,6 +185,7 @@ es:
PLURALS: PLURALS:
one: 'Un Miembro' one: 'Un Miembro'
other: '{count} Miembros' other: '{count} Miembros'
many: '{count} Miembros'
SINGULARNAME: Miembro SINGULARNAME: Miembro
SUBJECTPASSWORDCHANGED: 'Su contraseña ha sido cambiada' SUBJECTPASSWORDCHANGED: 'Su contraseña ha sido cambiada'
SUBJECTPASSWORDRESET: 'Enlace para restaurar su contraseña' SUBJECTPASSWORDRESET: 'Enlace para restaurar su contraseña'
@ -192,6 +202,7 @@ es:
PLURALS: PLURALS:
one: 'Una Contraseña de Miembro' one: 'Una Contraseña de Miembro'
other: '{count} Contraseñas de Miembros' other: '{count} Contraseñas de Miembros'
many: '{count} Contraseñas de Miembros'
SINGULARNAME: 'Contraseña del Miembro' SINGULARNAME: 'Contraseña del Miembro'
SilverStripe\Security\PasswordValidator: SilverStripe\Security\PasswordValidator:
LOWCHARSTRENGTH: 'Necesitas aumentar la complejidad de tu contraseña agregando los siguientes caracteres: {chars}' LOWCHARSTRENGTH: 'Necesitas aumentar la complejidad de tu contraseña agregando los siguientes caracteres: {chars}'
@ -206,6 +217,7 @@ es:
PLURALS: PLURALS:
one: 'Un Permiso' one: 'Un Permiso'
other: '{count} Permisos' other: '{count} Permisos'
many: '{count} Permisos'
SINGULARNAME: Permiso SINGULARNAME: Permiso
UserPermissionsIntro: 'Asignar grupos a este usuario ajustará los permisos que tienen. Vea la sección de grupos para obtener información sobre permisos en grupos individuales.' UserPermissionsIntro: 'Asignar grupos a este usuario ajustará los permisos que tienen. Vea la sección de grupos para obtener información sobre permisos en grupos individuales.'
SilverStripe\Security\PermissionCheckboxSetField: SilverStripe\Security\PermissionCheckboxSetField:
@ -219,6 +231,7 @@ es:
PLURALS: PLURALS:
one: 'Un Rol' one: 'Un Rol'
other: '{count} Roles' other: '{count} Roles'
many: '{count} Roles'
SINGULARNAME: Rol SINGULARNAME: Rol
Title: Título Title: Título
SilverStripe\Security\PermissionRoleCode: SilverStripe\Security\PermissionRoleCode:
@ -226,6 +239,7 @@ es:
PLURALS: PLURALS:
one: 'Un Código de Rol de Permiso' one: 'Un Código de Rol de Permiso'
other: '{count} Códigos de Roles de Permiso' other: '{count} Códigos de Roles de Permiso'
many: '{count} Códigos de Roles 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ódigo del Rol de Permiso' SINGULARNAME: 'Código del Rol de Permiso'
SilverStripe\Security\RememberLoginHash: SilverStripe\Security\RememberLoginHash:
@ -233,6 +247,7 @@ es:
PLURALS: PLURALS:
one: 'Un Hash de inicio de sesión' one: 'Un Hash de inicio de sesión'
other: '{count} Hashes de inicio de sesión' other: '{count} Hashes de inicio de sesión'
many: '{count} Hashes de inicio de sesión'
SINGULARNAME: 'Hash de inicio de sesión' SINGULARNAME: 'Hash de inicio de sesión'
SilverStripe\Security\Security: SilverStripe\Security\Security:
ALREADYLOGGEDIN: 'No tiene acceso a esta página. Si posee otra cuenta con los privilegios para acceder a esta página, puede iniciar sesión a continuación.' ALREADYLOGGEDIN: 'No tiene acceso a esta página. Si posee otra cuenta con los privilegios para acceder a esta página, puede iniciar sesión a continuación.'

View File

@ -113,6 +113,7 @@ fr:
PLURALS: PLURALS:
one: 'Un modèle de donnée' one: 'Un modèle de donnée'
other: '{count} modèles de donnée' other: '{count} modèles de donnée'
many: '{count} modèles de donnée'
SINGULARNAME: 'Modèle de donnée' SINGULARNAME: 'Modèle de donnée'
SilverStripe\ORM\FieldType\DBBoolean: SilverStripe\ORM\FieldType\DBBoolean:
ANY: Tout ANY: Tout
@ -122,24 +123,30 @@ fr:
DAYS_SHORT_PLURALS: DAYS_SHORT_PLURALS:
one: '{count} jour' one: '{count} jour'
other: '{count} jours' other: '{count} jours'
many: '{count} jours'
HOURS_SHORT_PLURALS: HOURS_SHORT_PLURALS:
one: '{count} heure' one: '{count} heure'
other: '{count} heures' other: '{count} heures'
many: '{count} heures'
LessThanMinuteAgo: 'moins d''une minute' LessThanMinuteAgo: 'moins d''une minute'
MINUTES_SHORT_PLURALS: MINUTES_SHORT_PLURALS:
one: '{count} min.' one: '{count} min.'
other: '{count} min.' other: '{count} min.'
many: '{count} min.'
MONTHS_SHORT_PLURALS: MONTHS_SHORT_PLURALS:
one: '{count} mois' one: '{count} mois'
other: '{count} mois' other: '{count} mois'
many: '{count} mois'
SECONDS_SHORT_PLURALS: SECONDS_SHORT_PLURALS:
one: '{count} sec.' one: '{count} sec.'
other: '{count} sec.' other: '{count} sec.'
many: '{count} sec.'
TIMEDIFFAGO: 'Il y a {difference}' TIMEDIFFAGO: 'Il y a {difference}'
TIMEDIFFIN: 'Dans {difference}' TIMEDIFFIN: 'Dans {difference}'
YEARS_SHORT_PLURALS: YEARS_SHORT_PLURALS:
one: '{count} année' one: '{count} année'
other: '{count} années' other: '{count} années'
many: '{count} années'
SilverStripe\ORM\FieldType\DBEnum: SilverStripe\ORM\FieldType\DBEnum:
ANY: Tout ANY: Tout
SilverStripe\ORM\Hierarchy: SilverStripe\ORM\Hierarchy:
@ -182,6 +189,7 @@ fr:
PLURALS: PLURALS:
one: 'Un groupe' one: 'Un groupe'
other: '{count} groupes' other: '{count} groupes'
many: '{count} groupes'
Parent: 'Groupe parent' Parent: 'Groupe parent'
ROLES: Rôles ROLES: Rôles
ROLESDESCRIPTION: 'Les rôles sont des ensembles de permissions prédéfinies, et ils peuvent être attribués à des groupes. <br />Si nécessaire, ils peuvent hériter de groupes parents.' ROLESDESCRIPTION: 'Les rôles sont des ensembles de permissions prédéfinies, et ils peuvent être attribués à des groupes. <br />Si nécessaire, ils peuvent hériter de groupes parents.'
@ -198,6 +206,7 @@ fr:
PLURALS: PLURALS:
one: 'Une tentative de connexion' one: 'Une tentative de connexion'
other: '{count} tentatives de connexion' other: '{count} tentatives de connexion'
many: '{count} tentatives de connexion'
SINGULARNAME: 'Tentative de connexion' SINGULARNAME: 'Tentative de connexion'
Status: Statut Status: Statut
SilverStripe\Security\Member: SilverStripe\Security\Member:
@ -228,6 +237,7 @@ fr:
PLURALS: PLURALS:
one: 'Un membre' one: 'Un membre'
other: '{count} membres' other: '{count} membres'
many: '{count} membres'
SINGULARNAME: Membre SINGULARNAME: Membre
SUBJECTPASSWORDCHANGED: 'Votre mot de passe a été changé' SUBJECTPASSWORDCHANGED: 'Votre mot de passe a été changé'
SUBJECTPASSWORDRESET: 'Lien pour modifier votre mot de passe' SUBJECTPASSWORDRESET: 'Lien pour modifier votre mot de passe'
@ -255,6 +265,7 @@ fr:
PLURALS: PLURALS:
one: 'Un mot de passe utilisateur' one: 'Un mot de passe utilisateur'
other: '{count} mots de passe utilisateur' other: '{count} mots de passe utilisateur'
many: '{count} mots de passe utilisateur'
SINGULARNAME: 'Mot de passe utilisateur' SINGULARNAME: 'Mot de passe utilisateur'
SilverStripe\Security\PasswordValidator: SilverStripe\Security\PasswordValidator:
LOWCHARSTRENGTH: 'Veuillez renforcer votre mot de passe en ajoutant certains des caractères suivants : {chars}' LOWCHARSTRENGTH: 'Veuillez renforcer votre mot de passe en ajoutant certains des caractères suivants : {chars}'
@ -271,6 +282,7 @@ fr:
PLURALS: PLURALS:
one: 'Une autorisation' one: 'Une autorisation'
other: '{count} autorisations' other: '{count} autorisations'
many: '{count} autorisations'
SINGULARNAME: Permission SINGULARNAME: Permission
UserPermissionsIntro: "Assigner des groupes à cet utilisateur modifiera les autorisations dont il dispose. Consultez la section «\_Groupes\_» pour plus de détails sur les autorisations associées à chaque groupe." UserPermissionsIntro: "Assigner des groupes à cet utilisateur modifiera les autorisations dont il dispose. Consultez la section «\_Groupes\_» pour plus de détails sur les autorisations associées à chaque groupe."
SilverStripe\Security\PermissionCheckboxSetField: SilverStripe\Security\PermissionCheckboxSetField:
@ -284,6 +296,7 @@ fr:
PLURALS: PLURALS:
one: 'Un rôle' one: 'Un rôle'
other: '{count} rôles' other: '{count} rôles'
many: '{count} rôles'
SINGULARNAME: Rôle SINGULARNAME: Rôle
Title: Titre Title: Titre
SilverStripe\Security\PermissionRoleCode: SilverStripe\Security\PermissionRoleCode:
@ -291,6 +304,7 @@ fr:
PLURALS: PLURALS:
one: 'Un code d''autorisation lié au rôle' one: 'Un code d''autorisation lié au rôle'
other: '{count} codes d''autorisation liés au rôle' other: '{count} codes d''autorisation liés au rôle'
many: '{count} codes d''autorisation liés au rôle'
PermsError: 'Impossible d''attribuer le code "{code}" (requiert un accès en tant qu''administrateur)' PermsError: 'Impossible d''attribuer le code "{code}" (requiert un accès en tant qu''administrateur)'
SINGULARNAME: 'Code d''autorisation lié au rôle' SINGULARNAME: 'Code d''autorisation lié au rôle'
SilverStripe\Security\RememberLoginHash: SilverStripe\Security\RememberLoginHash:
@ -298,6 +312,7 @@ fr:
PLURALS: PLURALS:
one: 'Une signature de mot de passe' one: 'Une signature de mot de passe'
other: '{count} signatures de mot de passe' other: '{count} signatures de mot de passe'
many: '{count} signatures de mot de passe'
SINGULARNAME: 'Signature de mot de passe' SINGULARNAME: 'Signature de mot de passe'
SilverStripe\Security\Security: SilverStripe\Security\Security:
ALREADYLOGGEDIN: 'Vous n''avez pas accès à cette page. Si un autre de vos identifiants vous permet d''accéder à cette page, merci de vous reconnecter ci-dessous en l''utilisant.' ALREADYLOGGEDIN: 'Vous n''avez pas accès à cette page. Si un autre de vos identifiants vous permet d''accéder à cette page, merci de vous reconnecter ci-dessous en l''utilisant.'

View File

@ -149,6 +149,7 @@ it:
PLURALS: PLURALS:
one: 'Un Data Object' one: 'Un Data Object'
other: '{count} Data Object' other: '{count} Data Object'
many: '{count} Data Object'
SINGULARNAME: 'Data Object' SINGULARNAME: 'Data Object'
SilverStripe\ORM\FieldType\DBBoolean: SilverStripe\ORM\FieldType\DBBoolean:
ANY: Qualsiasi ANY: Qualsiasi
@ -158,24 +159,30 @@ it:
DAYS_SHORT_PLURALS: DAYS_SHORT_PLURALS:
one: '{count} giorno' one: '{count} giorno'
other: '{count} giorni' other: '{count} giorni'
many: '{count} giorni'
HOURS_SHORT_PLURALS: HOURS_SHORT_PLURALS:
one: '{count} ora' one: '{count} ora'
other: '{count} ore' other: '{count} ore'
many: '{count} ore'
LessThanMinuteAgo: 'meno di un minuto' LessThanMinuteAgo: 'meno di un minuto'
MINUTES_SHORT_PLURALS: MINUTES_SHORT_PLURALS:
one: '{count} minuto' one: '{count} minuto'
other: '{count} minuti' other: '{count} minuti'
many: '{count} minuti'
MONTHS_SHORT_PLURALS: MONTHS_SHORT_PLURALS:
one: '{count} mese' one: '{count} mese'
other: '{count} mesi' other: '{count} mesi'
many: '{count} mesi'
SECONDS_SHORT_PLURALS: SECONDS_SHORT_PLURALS:
one: '{count} secondo' one: '{count} secondo'
other: '{count} secondi' other: '{count} secondi'
many: '{count} secondi'
TIMEDIFFAGO: '{difference} fa' TIMEDIFFAGO: '{difference} fa'
TIMEDIFFIN: 'in {difference}' TIMEDIFFIN: 'in {difference}'
YEARS_SHORT_PLURALS: YEARS_SHORT_PLURALS:
one: '{count} anno' one: '{count} anno'
other: '{count} anni' other: '{count} anni'
many: '{count} anni'
SilverStripe\ORM\FieldType\DBEnum: SilverStripe\ORM\FieldType\DBEnum:
ANY: Qualsiasi ANY: Qualsiasi
SilverStripe\ORM\FieldType\DBForeignKey: SilverStripe\ORM\FieldType\DBForeignKey:
@ -228,6 +235,7 @@ it:
PLURALS: PLURALS:
one: 'Un Gruppo' one: 'Un Gruppo'
other: '{count} Gruppi' other: '{count} Gruppi'
many: '{count} Gruppi'
Parent: 'Gruppo padre' Parent: 'Gruppo padre'
ROLES: Ruoli ROLES: Ruoli
ROLESDESCRIPTION: 'I ruoli sono insiemi predefiniti di permessi che possono essere assegnati ai gruppi.<br />Se richiesto possono essere ereditati dai gruppi padre.' ROLESDESCRIPTION: 'I ruoli sono insiemi predefiniti di permessi che possono essere assegnati ai gruppi.<br />Se richiesto possono essere ereditati dai gruppi padre.'
@ -236,6 +244,7 @@ it:
Sort: 'Tipo ordinamento' Sort: 'Tipo ordinamento'
has_many_Permissions: Permessi has_many_Permissions: Permessi
many_many_Members: Membri many_many_Members: Membri
ValidationIdentifierAlreadyExists: 'Esiste già un gruppo ({group}) con lo stesso {identifier}'
SilverStripe\Security\LoginAttempt: SilverStripe\Security\LoginAttempt:
Email: 'Indirizzo e-mail' Email: 'Indirizzo e-mail'
EmailHashed: 'Indirizzo email (hash)' EmailHashed: 'Indirizzo email (hash)'
@ -244,6 +253,7 @@ it:
PLURALS: PLURALS:
one: 'Un tentativo d''accesso' one: 'Un tentativo d''accesso'
other: '{count} tentativi d''accesso' other: '{count} tentativi d''accesso'
many: '{count} tentativi d''accesso'
SINGULARNAME: 'Tentativo d''accesso' SINGULARNAME: 'Tentativo d''accesso'
Status: Stato Status: Stato
SilverStripe\Security\Member: SilverStripe\Security\Member:
@ -276,6 +286,7 @@ it:
PLURALS: PLURALS:
one: 'Un Utente' one: 'Un Utente'
other: '{count} Utenti' other: '{count} Utenti'
many: '{count} Utenti'
SINGULARNAME: Utente SINGULARNAME: Utente
SUBJECTPASSWORDCHANGED: 'La tua password è stata cambiata' SUBJECTPASSWORDCHANGED: 'La tua password è stata cambiata'
SUBJECTPASSWORDRESET: 'Link per azzerare la tua password' SUBJECTPASSWORDRESET: 'Link per azzerare la tua password'
@ -305,6 +316,7 @@ it:
PLURALS: PLURALS:
one: 'Una password utente' one: 'Una password utente'
other: '{count} password utente' other: '{count} password utente'
many: '{count} password utente'
SINGULARNAME: 'Password utente' SINGULARNAME: 'Password utente'
SilverStripe\Security\PasswordValidator: SilverStripe\Security\PasswordValidator:
LOWCHARSTRENGTH: 'Perfavore aumenta la sicurezza della password aggiungendo alcuni dei seguenti caratteri: {chars}' LOWCHARSTRENGTH: 'Perfavore aumenta la sicurezza della password aggiungendo alcuni dei seguenti caratteri: {chars}'
@ -321,6 +333,7 @@ it:
PLURALS: PLURALS:
one: 'Un Permesso' one: 'Un Permesso'
other: '{count} Permessi' other: '{count} Permessi'
many: '{count} Permessi'
SINGULARNAME: Permesso SINGULARNAME: Permesso
UserPermissionsIntro: 'Assegnando gruppi a questo utente modificherà i suoi permessi. Vedi la sezione gruppi per dettagli sui permessi dei singoli gruppi.' UserPermissionsIntro: 'Assegnando gruppi a questo utente modificherà i suoi permessi. Vedi la sezione gruppi per dettagli sui permessi dei singoli gruppi.'
SilverStripe\Security\PermissionCheckboxSetField: SilverStripe\Security\PermissionCheckboxSetField:
@ -334,6 +347,7 @@ it:
PLURALS: PLURALS:
one: 'Un Ruolo' one: 'Un Ruolo'
other: '{count} Ruoli' other: '{count} Ruoli'
many: '{count} Ruoli'
SINGULARNAME: Ruolo SINGULARNAME: Ruolo
Title: Titolo Title: Titolo
SilverStripe\Security\PermissionRoleCode: SilverStripe\Security\PermissionRoleCode:
@ -341,6 +355,7 @@ it:
PLURALS: PLURALS:
one: 'Un codice di ruolo' one: 'Un codice di ruolo'
other: '{count} codici di ruolo' other: '{count} codici di ruolo'
many: '{count} codici di ruolo'
PermsError: 'Non posso assegnare permessi privilegiati al codice "{code}" (richiede accesso ADMIN)' PermsError: 'Non posso assegnare permessi privilegiati al codice "{code}" (richiede accesso ADMIN)'
SINGULARNAME: 'Codice di ruolo' SINGULARNAME: 'Codice di ruolo'
SilverStripe\Security\RememberLoginHash: SilverStripe\Security\RememberLoginHash:
@ -348,6 +363,7 @@ it:
PLURALS: PLURALS:
one: 'Un Hash di Login' one: 'Un Hash di Login'
other: '{count} Hash di Login' other: '{count} Hash di Login'
many: '{count} Hash di Login'
SINGULARNAME: 'Hash di Login' SINGULARNAME: 'Hash di Login'
SilverStripe\Security\Security: SilverStripe\Security\Security:
ALREADYLOGGEDIN: 'Non hai accesso a questa pagina. Se hai un altro account che può accederci, puoi autenticarti qui sotto.' ALREADYLOGGEDIN: 'Non hai accesso a questa pagina. Se hai un altro account che può accederci, puoi autenticarti qui sotto.'

View File

@ -7,15 +7,15 @@ nl:
EDITINFO: 'Bewerk dit bestand' EDITINFO: 'Bewerk dit bestand'
REMOVE: Verwijder REMOVE: Verwijder
SilverStripe\Control\ChangePasswordEmail_ss: SilverStripe\Control\ChangePasswordEmail_ss:
CHANGEPASSWORDFOREMAIL: 'Het wachtwoord voor het account met e-mailadres {email} is aangepast. Indien u uw wachtwoord niet heeft aangepast kunt u dat doen met onderstaande link.' CHANGEPASSWORDFOREMAIL: 'Het wachtwoord voor het account met e-mailadres {email} is zojuist aangepast. Heb je geen wachtwoord aangepast, gebruik van onderstaande knop om uit veiligheidsoverwegingen je wachtwoord opnieuw in te stellen.'
CHANGEPASSWORDTEXT1: 'U heeft het wachtwoord veranderd voor' CHANGEPASSWORDTEXT1: 'U heeft het wachtwoord veranderd voor'
CHANGEPASSWORDTEXT3: 'Wachtwoord veranderen' CHANGEPASSWORDTEXT3: 'Wachtwoord opnieuw instellen'
HELLO: Hallo HELLO: Hallo
SilverStripe\Control\Email\ForgotPasswordEmail_ss: SilverStripe\Control\Email\ForgotPasswordEmail_ss:
HELLO: Hallo HELLO: Hallo
TEXT1: 'Hier is uw' TEXT1: 'Je hebt aangegeven je wachtwoord te zijn vergeten. Klik op de'
TEXT2: 'link om uw wachtwoord opnieuw aan te maken' TEXT2: 'onderstaande link'
TEXT3: voor TEXT3: 'om je wachtwoord opnieuw in te stellen voor '
SilverStripe\Control\Middleware\ConfirmationMiddleware\GetParameter: SilverStripe\Control\Middleware\ConfirmationMiddleware\GetParameter:
CONFIRMATION_NAME: '"{key}" GET parameter' CONFIRMATION_NAME: '"{key}" GET parameter'
SilverStripe\Control\Middleware\ConfirmationMiddleware\Url: SilverStripe\Control\Middleware\ConfirmationMiddleware\Url:
@ -39,8 +39,8 @@ nl:
ATLEAST: 'Een wachtwoord moet tenminste {min} karakters hebben.' ATLEAST: 'Een wachtwoord moet tenminste {min} karakters hebben.'
BETWEEN: 'Een wachtwoord moet tussen de {min} en {max} karakters hebben' BETWEEN: 'Een wachtwoord moet tussen de {min} en {max} karakters hebben'
CURRENT_PASSWORD_ERROR: 'Het wachtwoord dat u heeft ingevoerd is niet juist.' CURRENT_PASSWORD_ERROR: 'Het wachtwoord dat u heeft ingevoerd is niet juist.'
CURRENT_PASSWORD_MISSING: 'Voer uw huidige wachtwoord in.' CURRENT_PASSWORD_MISSING: 'Voer je huidige wachtwoord in.'
LOGGED_IN_ERROR: 'U moet ingelogd zijn om uw wachtwoord te kunnen veranderen!' LOGGED_IN_ERROR: 'Je moet ingelogd zijn om je wachtwoord te kunnen veranderen!'
MAXIMUM: 'Een wachtwoord mag maximaal {max} karakters hebben.' MAXIMUM: 'Een wachtwoord mag maximaal {max} karakters hebben.'
SHOWONCLICKTITLE: 'Verander wachtwoord' SHOWONCLICKTITLE: 'Verander wachtwoord'
SilverStripe\Forms\DateField: SilverStripe\Forms\DateField:
@ -63,7 +63,7 @@ nl:
FIELDNOTSET: 'Bestandsinformatie niet gevonden' FIELDNOTSET: 'Bestandsinformatie niet gevonden'
SilverStripe\Forms\Form: SilverStripe\Forms\Form:
BAD_METHOD: 'Dit formulier moet middels {method} verzonden worden' BAD_METHOD: 'Dit formulier moet middels {method} verzonden worden'
CSRF_EXPIRED_MESSAGE: 'Uw sessie is verlopen. Verzend het formulier opnieuw.' CSRF_EXPIRED_MESSAGE: 'De sessie is verlopen. Verzend het formulier opnieuw.'
CSRF_FAILED_MESSAGE: 'Er lijkt een technisch probleem te zijn. Klik op de knop terug, vernieuw uw browser, en probeer het opnieuw.' CSRF_FAILED_MESSAGE: 'Er lijkt een technisch probleem te zijn. Klik op de knop terug, vernieuw uw browser, en probeer het opnieuw.'
FIELDISREQUIRED: '{name} is verplicht' FIELDISREQUIRED: '{name} is verplicht'
VALIDATIONPASSWORDSDONTMATCH: 'Wachtwoorden komen niet overeen' VALIDATIONPASSWORDSDONTMATCH: 'Wachtwoorden komen niet overeen'
@ -194,7 +194,7 @@ nl:
ERRORNOTADMIN: 'Die gebruiker is geen beheerder.' ERRORNOTADMIN: 'Die gebruiker is geen beheerder.'
ERRORNOTREC: 'De gebruikersnaam en/of het wachtwoord wordt niet herkend' ERRORNOTREC: 'De gebruikersnaam en/of het wachtwoord wordt niet herkend'
SilverStripe\Security\CMSMemberLoginForm: SilverStripe\Security\CMSMemberLoginForm:
PASSWORDEXPIRED: '<p>Uw wachtwoord is verlopen. <a target="_top" href="{link}">Kies een nieuw wachtwoord.</a></p>' PASSWORDEXPIRED: 'Je wachtwoord is verlopen. <a target="_top" href="{link}">Kies een nieuw wachtwoord.</a></p>'
SilverStripe\Security\CMSSecurity: SilverStripe\Security\CMSSecurity:
INVALIDUSER: '<p>Ongeldige gebruiker <a target="_top" href="{link}">Log hier opnieuw in</a> om verder te gaan.</p>' INVALIDUSER: '<p>Ongeldige gebruiker <a target="_top" href="{link}">Log hier opnieuw in</a> om verder te gaan.</p>'
LOGIN_MESSAGE: '<p>De browsersessie is verlopen wegens inactiviteit</p>' LOGIN_MESSAGE: '<p>De browsersessie is verlopen wegens inactiviteit</p>'
@ -236,6 +236,7 @@ nl:
Sort: Sorteer-richting Sort: Sorteer-richting
has_many_Permissions: Rechten has_many_Permissions: Rechten
many_many_Members: Leden many_many_Members: Leden
ValidationIdentifierAlreadyExists: 'Er bestaat al een groep ({group}) met eenzelfde {identifier}'
SilverStripe\Security\LoginAttempt: SilverStripe\Security\LoginAttempt:
Email: 'E-mailadres ' Email: 'E-mailadres '
EmailHashed: 'E-mailadres (versleuteld)' EmailHashed: 'E-mailadres (versleuteld)'
@ -259,7 +260,7 @@ nl:
EDIT_PASSWORD: 'Nieuw wachtwoord' EDIT_PASSWORD: 'Nieuw wachtwoord'
EMAIL: E-mail EMAIL: E-mail
EMPTYNEWPASSWORD: 'Het nieuwe wachtwoord mag niet leeg zijn, probeer opnieuw' EMPTYNEWPASSWORD: 'Het nieuwe wachtwoord mag niet leeg zijn, probeer opnieuw'
ENTEREMAIL: 'Typ uw e-mailadres om een link te ontvangen waarmee u uw wachtwoord kunt resetten.' ENTEREMAIL: 'Typ je e-mailadres om een link te ontvangen, waarmee je je wachtwoord opnieuw kan instellen.'
ERRORLOCKEDOUT2: 'Uw account is tijdelijk uitgeschakeld als gevolg van te veel mislukte pogingen om in te loggen. Probeer het over {count} minuten opnieuw.' ERRORLOCKEDOUT2: 'Uw account is tijdelijk uitgeschakeld als gevolg van te veel mislukte pogingen om in te loggen. Probeer het over {count} minuten opnieuw.'
ERRORNEWPASSWORD: 'De nieuwe wachtwoorden komen niet overeen, probeer het nogmaals' ERRORNEWPASSWORD: 'De nieuwe wachtwoorden komen niet overeen, probeer het nogmaals'
ERRORPASSWORDNOTMATCH: 'Uw huidige wachtwoord is niet correct, probeer het nogmaals' ERRORPASSWORDNOTMATCH: 'Uw huidige wachtwoord is niet correct, probeer het nogmaals'
@ -269,20 +270,20 @@ nl:
LOGGEDINAS: 'U bent ingelogd als {name}.' LOGGEDINAS: 'U bent ingelogd als {name}.'
NEWPASSWORD: 'Nieuw wachtwoord' NEWPASSWORD: 'Nieuw wachtwoord'
PASSWORD: Wachtwoord PASSWORD: Wachtwoord
PASSWORDEXPIRED: 'Uw wachtwoord is verlopen. Kies een nieuw wachtwoord.' PASSWORDEXPIRED: 'Je wachtwoord is verlopen. Kies een nieuw wachtwoord.'
PLURALNAME: Leden PLURALNAME: Leden
PLURALS: PLURALS:
one: 'Een lid' one: 'Een lid'
other: '{count} leden' other: '{count} leden'
SINGULARNAME: Lid SINGULARNAME: Lid
SUBJECTPASSWORDCHANGED: 'Uw wachtwoord is veranderd' SUBJECTPASSWORDCHANGED: 'Je wachtwoord is aangepast'
SUBJECTPASSWORDRESET: 'Link om uw wachtwoord opnieuw aan te maken' SUBJECTPASSWORDRESET: 'Je wachtwoord opnieuw instellen'
SURNAME: Achternaam SURNAME: Achternaam
VALIDATIONADMINLOSTACCESS: 'Niet mogelijk om alle admin-groepen te verwijderen van uw profiel' VALIDATIONADMINLOSTACCESS: 'Niet mogelijk om alle admin-groepen te verwijderen van je profiel'
VALIDATIONMEMBEREXISTS: 'Er bestaat al een gebruiker met eenzelfde %s' VALIDATIONMEMBEREXISTS: 'Er bestaat al een gebruiker met dezelfde {identifier}'
ValidationIdentifierFailed: 'Een bestaande gebruiker #{id} kan niet dezelfde unieke velden hebben ({name} = {value}))' ValidationIdentifierFailed: 'Een bestaande gebruiker #{id} kan niet dezelfde unieke velden hebben ({name} = {value}))'
WELCOMEBACK: 'Welkom terug, {firstname}' WELCOMEBACK: 'Welkom terug, {firstname}'
YOUROLDPASSWORD: 'Uw oude wachtwoord' YOUROLDPASSWORD: 'Je oude wachtwoord'
belongs_many_many_Groups: Groepen belongs_many_many_Groups: Groepen
db_Locale: 'Interface taal' db_Locale: 'Interface taal'
db_LockedOutUntil: 'Gesloten tot' db_LockedOutUntil: 'Gesloten tot'
@ -307,8 +308,8 @@ nl:
other: '{count} Gebruikerswachtwoorden' other: '{count} Gebruikerswachtwoorden'
SINGULARNAME: Gebruikerswachtwoord SINGULARNAME: Gebruikerswachtwoord
SilverStripe\Security\PasswordValidator: SilverStripe\Security\PasswordValidator:
LOWCHARSTRENGTH: 'Maak a.u.b. uw wachtwoord sterker door enkele van de volgende karakters te gebruiken: {chars}' LOWCHARSTRENGTH: 'Maak a.u.b. het wachtwoord sterker door enkele van de volgende karakters te gebruiken: {chars}'
PREVPASSWORD: 'U heeft dit wachtwoord in het verleden al gebruikt, kies a.u.b. een nieuw wachtwoord.' PREVPASSWORD: 'Dit wachtwoord is in het verleden al gebruikt, kies a.u.b. een nieuw wachtwoord.'
TOOSHORT: 'Het wachtwoord is te kort, het moet minimaal {minimum} karakters hebben' TOOSHORT: 'Het wachtwoord is te kort, het moet minimaal {minimum} karakters hebben'
SilverStripe\Security\Permission: SilverStripe\Security\Permission:
AdminGroup: Beheerder AdminGroup: Beheerder
@ -352,18 +353,18 @@ nl:
SilverStripe\Security\Security: SilverStripe\Security\Security:
ALREADYLOGGEDIN: 'U hebt geen toegang tot deze pagina. Als u een andere account met de nodige rechten hebt, kan u hieronder opnieuw inloggen.' ALREADYLOGGEDIN: 'U hebt geen toegang tot deze pagina. Als u een andere account met de nodige rechten hebt, kan u hieronder opnieuw inloggen.'
BUTTONSEND: 'Nieuw wachtwoord aanmaken' BUTTONSEND: 'Nieuw wachtwoord aanmaken'
CHANGEPASSWORDBELOW: 'U kunt uw wachtwoord hieronder veranderen.' CHANGEPASSWORDBELOW: 'Je kan hieronder het wachtwoord veranderen.'
CHANGEPASSWORDHEADER: 'Verander uw wachtwoord' CHANGEPASSWORDHEADER: 'Wachtwoord veranderen'
CONFIRMLOGOUT: 'Klik op onderstaande knop om uit te loggen.' CONFIRMLOGOUT: 'Klik op onderstaande knop om uit te loggen.'
ENTERNEWPASSWORD: 'Voer een nieuw wachtwoord in.' ENTERNEWPASSWORD: 'Voer een nieuw wachtwoord in.'
ERRORPASSWORDPERMISSION: 'U moet ingelogd zijn om uw wachtwoord te kunnen veranderen!' ERRORPASSWORDPERMISSION: 'Je moet ingelogd zijn om je wachtwoord te kunnen veranderen!'
LOGIN: Inloggen LOGIN: Inloggen
LOGOUT: Uitloggen LOGOUT: Uitloggen
LOSTPASSWORDHEADER: 'Wachtwoord vergeten' LOSTPASSWORDHEADER: 'Wachtwoord vergeten'
NOTEPAGESECURED: 'Deze pagina is beveiligd. Voer uw gegevens in en u wordt automatisch doorgestuurd.' NOTEPAGESECURED: 'Deze pagina is beveiligd. Voer uw gegevens in en u wordt automatisch doorgestuurd.'
NOTERESETLINKINVALID: '<p>De reset link is ongeldig of verlopen.</p><p>Je kan <a href="{link1}">hier</a> een nieuwe link aanvragen of het wachtwoord veranderen nadat je bent <a href="{link2}">ingelogd</a>.</p>' NOTERESETLINKINVALID: '<p>De reset link is ongeldig of verlopen.</p><p>Je kan <a href="{link1}">hier</a> een nieuwe link aanvragen of het wachtwoord veranderen nadat je bent <a href="{link2}">ingelogd</a>.</p>'
NOTERESETPASSWORD: 'Voer uw e-mailadres in en we sturen een link waarmee u een nieuw wachtwoord kunt instellen.' NOTERESETPASSWORD: 'Voer je e-mailadres in en we sturen een link waarmee je een nieuw wachtwoord kunt instellen.'
PASSWORDRESETSENTHEADER: Verzonden PASSWORDRESETSENTHEADER: Verzonden
PASSWORDRESETSENTTEXT: 'Bedankt! Er is een link verstuurd om uw wachtwoord opnieuw in te stellen (mits het e-mailadres reeds bekend is bij ons).' PASSWORDRESETSENTTEXT: 'Bedankt! Er is een e-mail verstuurd om je wachtwoord opnieuw in te stellen - mits het e-mailadres reeds bekend is bij ons.'
SilverStripe\View\Shortcodes\EmbedShortcodeProvider: SilverStripe\View\Shortcodes\EmbedShortcodeProvider:
INVALID_URL: 'Het inladen van de media-bestanden is mislukt.' INVALID_URL: 'Het inladen van de media-bestanden is mislukt.'

View File

@ -62,6 +62,7 @@ pl:
VALIDATIONSTRONGPASSWORD: 'Hasła muszą mieć przynajmniej jedną cyfrę oraz jeden znak alfanumeryczny.' VALIDATIONSTRONGPASSWORD: 'Hasła muszą mieć przynajmniej jedną cyfrę oraz jeden znak alfanumeryczny.'
VALIDATOR: Walidator VALIDATOR: Walidator
VALIDCURRENCY: 'Proszę podaj prawidłową walutę' VALIDCURRENCY: 'Proszę podaj prawidłową walutę'
FIELDISREQUIRED: 'Pole {name} jest wymagane'
SilverStripe\Forms\FormField: SilverStripe\Forms\FormField:
EXAMPLE: 'na przykład {format}' EXAMPLE: 'na przykład {format}'
NONE: brak NONE: brak
@ -97,10 +98,13 @@ pl:
DeletePermissionsFailure: 'Brak uprawnień do usuwania' DeletePermissionsFailure: 'Brak uprawnień do usuwania'
Deleted: 'Usunięto {type} {name}' Deleted: 'Usunięto {type} {name}'
Save: Zapisz Save: Zapisz
Saved: 'Zapisane {name} {link}'
SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest: SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest:
NEW: Dodaj NEW: Dodaj
NEXT: 'Przejdź do następnego rekordu' NEXT: 'Przejdź do następnego rekordu'
PREVIOUS: 'Przejdź do poprzedniego rekordu' PREVIOUS: 'Przejdź do poprzedniego rekordu'
EditPermissionsFailure: 'Wygląda na to, że nie masz wystarczających uprawnień, aby zmienić {ObjectTitle}'
ViewPermissionsFailure: 'Wygląda na to, że nie masz wystarczających uprawnień, aby zobaczyć {ObjectTitle}'
SilverStripe\Forms\GridField\GridFieldEditButton: SilverStripe\Forms\GridField\GridFieldEditButton:
EDIT: Zmień EDIT: Zmień
SilverStripe\Forms\GridField\GridFieldFilterHeader: SilverStripe\Forms\GridField\GridFieldFilterHeader:
@ -232,6 +236,7 @@ pl:
Sort: 'Kolejność Sortowania' Sort: 'Kolejność Sortowania'
has_many_Permissions: Zezwolenia has_many_Permissions: Zezwolenia
many_many_Members: Użytkownicy many_many_Members: Użytkownicy
ValidationIdentifierAlreadyExists: 'Grupa ({group}) już istnieje z tym samym {identifier}'
SilverStripe\Security\LoginAttempt: SilverStripe\Security\LoginAttempt:
Email: 'Adres e-mail' Email: 'Adres e-mail'
EmailHashed: 'Adres e-mail (hashed)' EmailHashed: 'Adres e-mail (hashed)'
@ -286,6 +291,10 @@ pl:
db_LockedOutUntil: 'Zablokowany do' db_LockedOutUntil: 'Zablokowany do'
db_Password: Hasło db_Password: Hasło
db_PasswordExpiry: 'Data wygaśnięcia hasła' db_PasswordExpiry: 'Data wygaśnięcia hasła'
KEEP_ME_SIGNED_IN: 'Zapamiętaj mnie / Nie wylogowuj mnie przez {count} dni'
KEEP_ME_SIGNED_IN_TOOLTIP: 'Pozostaniesz uwierzytelniony na tym urządzeniu przez {count} dni. Używaj tej funkcji tylko wtedy, gdy ufasz urządzeniu, z którego korzystasz.'
VALIDATIONMEMBEREXISTS: 'Użytkownik z tym adresem już istnieje {identifier}'
WELCOMEBACK: 'Witaj ponownie, {firstname}'
SilverStripe\Security\MemberAuthenticator\CMSMemberLoginForm: SilverStripe\Security\MemberAuthenticator\CMSMemberLoginForm:
AUTHENTICATORNAME: 'Formularz logowania użytkownika CMS' AUTHENTICATORNAME: 'Formularz logowania użytkownika CMS'
BUTTONFORGOTPASSWORD: 'Zapomniałeś hasła?' BUTTONFORGOTPASSWORD: 'Zapomniałeś hasła?'
@ -370,3 +379,22 @@ pl:
NOTERESETPASSWORD: 'Wpisz adres e-mail, na który mamy wysłać link gdzie możesz zresetować swoje hasło' NOTERESETPASSWORD: 'Wpisz adres e-mail, na który mamy wysłać link gdzie możesz zresetować swoje hasło'
PASSWORDRESETSENTHEADER: 'Link resetowania hasła wysłany' PASSWORDRESETSENTHEADER: 'Link resetowania hasła wysłany'
PASSWORDRESETSENTTEXT: 'Dziękujemy! Link resetujący hasło został wysłany do ''{email}'', o ile konto użytkownika dla takiego e-maila istnieje.' PASSWORDRESETSENTTEXT: 'Dziękujemy! Link resetujący hasło został wysłany do ''{email}'', o ile konto użytkownika dla takiego e-maila istnieje.'
NOTERESETLINKINVALID: '<p>Link resetujący hasło wygasł lub jest nieprawidłowy.</p><p>Możesz poprosić o nowy <a href="{link1}">tutaj</a> lub zmień swoje hasło po <a href="{link2}">zalogowaniu się</a>.</p>'
SilverStripe\Control\Middleware\ConfirmationMiddleware\GetParameter:
CONFIRMATION_NAME: 'Parametr GET „{key}”'
SilverStripe\Control\Middleware\ConfirmationMiddleware\Url:
CONFIRMATION_DESCRIPTION: 'Adres URL to: „{url}”'
CONFIRMATION_NAME: 'Adres URL jest chroniony'
SilverStripe\Control\Middleware\ConfirmationMiddleware\UrlPathStartswith:
CONFIRMATION_DESCRIPTION: 'Pełny adres URL to: „{url}”'
CONFIRMATION_NAME: 'URL zaczyna się od „{path}”'
SilverStripe\Forms\HTMLEditor\TinyMCEConfig:
BEST_FIT: 'Dopasuj optymalnie'
ORIGINAL: Oryginał
PIXEL_WIDTH: '{width} pikseli'
SilverStripe\Forms\TextField:
VALIDATEMAXLENGTH: 'Wartość {name} nie może przekraczać {maxLength} znaków długości'
SilverStripe\ORM\FieldType\DBString:
ELLIPSIS: ...
SilverStripe\View\Shortcodes\EmbedShortcodeProvider:
INVALID_URL: 'Podczas ładowania pliku wystąpił problem.'

View File

@ -267,7 +267,7 @@ class HTTPResponse
public function addHeader($header, $value) public function addHeader($header, $value)
{ {
$header = strtolower($header ?? ''); $header = strtolower($header ?? '');
$this->headers[$header] = $value; $this->headers[$header] = $this->sanitiseHeader($value);
return $this; return $this;
} }
@ -310,6 +310,14 @@ class HTTPResponse
return $this; return $this;
} }
/**
* Sanitise header values to avoid possible XSS vectors
*/
private function sanitiseHeader(string $value): string
{
return preg_replace('/\v/', '', $value);
}
public function redirect(string $dest, int $code = 302): static public function redirect(string $dest, int $code = 302): static
{ {
if (!in_array($code, self::$redirect_codes)) { if (!in_array($code, self::$redirect_codes)) {

View File

@ -1485,16 +1485,21 @@ class Form extends ViewableData implements HasRequestHandler
*/ */
public function saveInto(DataObjectInterface $dataObject, $fieldList = null) public function saveInto(DataObjectInterface $dataObject, $fieldList = null)
{ {
$form = $this;
$dataObject->invokeWithExtensions('onBeforeFormSaveInto', $form, $fieldList);
$dataFields = $this->fields->saveableFields(); $dataFields = $this->fields->saveableFields();
$lastField = null; $lastField = null;
if ($dataFields) { if ($dataFields) {
foreach ($dataFields as $field) { foreach ($dataFields as $field) {
// Skip fields that have been excluded // Skip fields that have been excluded
if ($fieldList && is_array($fieldList) && !in_array($field->getName(), $fieldList ?? [])) { if ($fieldList && is_array($fieldList) && !in_array($field->getName(), $fieldList ?? [])) {
continue; continue;
} }
$saveMethod = "save{$field->getName()}"; $saveMethod = "save{$field->getName()}";
if ($field->getName() == "ClassName") { if ($field->getName() == "ClassName") {
$lastField = $field; $lastField = $field;
} elseif ($dataObject->hasMethod($saveMethod)) { } elseif ($dataObject->hasMethod($saveMethod)) {
@ -1504,9 +1509,12 @@ class Form extends ViewableData implements HasRequestHandler
} }
} }
} }
if ($lastField) { if ($lastField) {
$lastField->saveInto($dataObject); $lastField->saveInto($dataObject);
} }
$dataObject->invokeWithExtensions('onAfterFormSaveInto', $form, $fieldList);
} }
/** /**

View File

@ -11,6 +11,7 @@ use SilverStripe\ORM\DataObject;
use SilverStripe\View\ArrayData; use SilverStripe\View\ArrayData;
use SilverStripe\View\SSViewer; use SilverStripe\View\SSViewer;
use LogicException; use LogicException;
use SilverStripe\Core\Injector\Injector;
/** /**
* GridFieldSortableHeader adds column headers to a {@link GridField} that can * GridFieldSortableHeader adds column headers to a {@link GridField} that can
@ -271,6 +272,16 @@ class GridFieldSortableHeader extends AbstractGridFieldComponent implements Grid
return $dataList; return $dataList;
} }
// Prevent SQL Injection by validating that SortColumn exists
/** @var GridFieldDataColumns $columns */
$columns = $gridField->getConfig()->getComponentByType(GridFieldDataColumns::class);
$fields = $columns->getDisplayFields($gridField);
if (!array_key_exists($state->SortColumn, $fields) &&
!in_array($state->SortColumn, $this->getFieldSorting())
) {
throw new LogicException('Invalid SortColumn: ' . $state->SortColumn);
}
return $dataList->sort($state->SortColumn, $state->SortDirection('asc')); return $dataList->sort($state->SortColumn, $state->SortDirection('asc'));
} }

View File

@ -347,9 +347,9 @@ class HTMLEditorSanitiser
} }
// Matches "javascript:" with any arbitrary linebreaks inbetween the characters. // Matches "javascript:" with any arbitrary linebreaks inbetween the characters.
$regex = '/^\s*' . implode('\v*', str_split('javascript:')) . '/'; $regex = '/^\s*' . implode('\s*', str_split('javascript:')) . '/i';
// Strip out javascript execution in href or src attributes. // Strip out javascript execution in href or src attributes.
foreach (['src', 'href'] as $dangerAttribute) { foreach (['src', 'href', 'data'] as $dangerAttribute) {
if ($el->hasAttribute($dangerAttribute)) { if ($el->hasAttribute($dangerAttribute)) {
if (preg_match($regex, $el->getAttribute($dangerAttribute))) { if (preg_match($regex, $el->getAttribute($dangerAttribute))) {
$el->removeAttribute($dangerAttribute); $el->removeAttribute($dangerAttribute);

View File

@ -127,7 +127,7 @@ class DBDecimal extends DBField
return 0; return 0;
} }
if (ctype_digit((string) $value)) { if (abs((float) $value - (int) $value) < PHP_FLOAT_EPSILON) {
return (int)$value; return (int)$value;
} }

View File

@ -16,6 +16,7 @@ use SilverStripe\View\HTML;
use SilverStripe\View\Parsers\ShortcodeHandler; use SilverStripe\View\Parsers\ShortcodeHandler;
use SilverStripe\View\Parsers\ShortcodeParser; use SilverStripe\View\Parsers\ShortcodeParser;
use SilverStripe\Control\Director; use SilverStripe\Control\Director;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\View\Embed\EmbedContainer; use SilverStripe\View\Embed\EmbedContainer;
/** /**
@ -25,6 +26,23 @@ use SilverStripe\View\Embed\EmbedContainer;
*/ */
class EmbedShortcodeProvider implements ShortcodeHandler class EmbedShortcodeProvider implements ShortcodeHandler
{ {
use Configurable;
/**
* A whitelist of shortcode attributes which are allowed in the resultant markup.
* Note that the tinymce plugin restricts attributes on the client-side separately.
*
* @config
* @deprecated 4.12.0 Removed without equivalent functionality to replace it
*/
private static array $attribute_whitelist = [
'url',
'thumbnail',
'class',
'width',
'height',
'caption',
];
/** /**
* Gets the list of shortcodes provided by this handler * Gets the list of shortcodes provided by this handler
@ -180,9 +198,17 @@ class EmbedShortcodeProvider implements ShortcodeHandler
} }
} }
$attributes = static::buildAttributeListFromArguments($arguments, ['width', 'height', 'url', 'caption']);
if (array_key_exists('style', $arguments)) {
$attributes->push(ArrayData::create([
'Name' => 'style',
'Value' => Convert::raw2att($arguments['style']),
]));
}
$data = [ $data = [
'Arguments' => $arguments, 'Arguments' => $arguments,
'Attributes' => static::buildAttributeListFromArguments($arguments, ['width', 'height', 'url', 'caption']), 'Attributes' => $attributes,
'Content' => DBField::create_field('HTMLFragment', $content) 'Content' => DBField::create_field('HTMLFragment', $content)
]; ];
@ -236,6 +262,12 @@ class EmbedShortcodeProvider implements ShortcodeHandler
*/ */
private static function buildAttributeListFromArguments(array $arguments, array $exclude = []): ArrayList private static function buildAttributeListFromArguments(array $arguments, array $exclude = []): ArrayList
{ {
// Clean out any empty arguments and anything not whitelisted
$whitelist = static::config()->get('attribute_whitelist');
$arguments = array_filter($arguments, function ($value, $key) use ($whitelist) {
return in_array($key, $whitelist) && strlen(trim($value ?? ''));
}, ARRAY_FILTER_USE_BOTH);
$attributes = ArrayList::create(); $attributes = ArrayList::create();
foreach ($arguments as $key => $value) { foreach ($arguments as $key => $value) {
if (in_array($key, $exclude ?? [])) { if (in_array($key, $exclude ?? [])) {

View File

@ -45,6 +45,26 @@ class HTTPResponseTest extends SapphireTest
$this->assertEmpty($response->getHeader('X-Animal')); $this->assertEmpty($response->getHeader('X-Animal'));
} }
public function providerSanitiseHeaders()
{
return [
'plain text is retained' => ['some arbitrary value1', 'some arbitrary value1'],
'special chars are retained' => ['`~!@#$%^&*()_+-=,./<>?;\':"[]{}\\|', '`~!@#$%^&*()_+-=,./<>?;\':"[]{}\\|'],
'line breaks are removed' => ['no line breaks', "n\ro line \nbreaks\r\n"],
];
}
/**
* @dataProvider providerSanitiseHeaders
*/
public function testSanitiseHeaders(string $expected, string $value)
{
$response = new HTTPResponse();
$response->addHeader('X-Sanitised', $value);
$this->assertSame($expected, $response->getHeader('X-Sanitised'));
}
public function providerTestValidStatusCodes() public function providerTestValidStatusCodes()
{ {
return [ return [

View File

@ -71,13 +71,14 @@ class GridFieldSortableHeaderTest extends SapphireTest
$list = Team::get()->filter([ 'ClassName' => Team::class ]); $list = Team::get()->filter([ 'ClassName' => Team::class ]);
$config = new GridFieldConfig_RecordEditor(); $config = new GridFieldConfig_RecordEditor();
$gridField = new GridField('testfield', 'testfield', $list, $config); $gridField = new GridField('testfield', 'testfield', $list, $config);
$component = $gridField->getConfig()->getComponentByType(GridFieldSortableHeader::class);
// Test normal sorting // Test normal sorting
$component->setFieldSorting(['Name' => 'City']);
$state = $gridField->State->GridFieldSortableHeader; $state = $gridField->State->GridFieldSortableHeader;
$state->SortColumn = 'City'; $state->SortColumn = 'City';
$state->SortDirection = 'asc'; $state->SortDirection = 'asc';
$component = $gridField->getConfig()->getComponentByType(GridFieldSortableHeader::class);
$listA = $component->getManipulatedData($gridField, $list); $listA = $component->getManipulatedData($gridField, $list);
$state->SortDirection = 'desc'; $state->SortDirection = 'desc';
@ -93,6 +94,7 @@ class GridFieldSortableHeaderTest extends SapphireTest
); );
// Test one relation 'deep' // Test one relation 'deep'
$component->setFieldSorting(['Name' => 'Cheerleader.Name']);
$state->SortColumn = 'Cheerleader.Name'; $state->SortColumn = 'Cheerleader.Name';
$state->SortDirection = 'asc'; $state->SortDirection = 'asc';
$relationListA = $component->getManipulatedData($gridField, $list); $relationListA = $component->getManipulatedData($gridField, $list);
@ -110,6 +112,7 @@ class GridFieldSortableHeaderTest extends SapphireTest
); );
// Test two relations 'deep' // Test two relations 'deep'
$component->setFieldSorting(['Name' => 'Cheerleader.Hat.Colour']);
$state->SortColumn = 'Cheerleader.Hat.Colour'; $state->SortColumn = 'Cheerleader.Hat.Colour';
$state->SortDirection = 'asc'; $state->SortDirection = 'asc';
$relationListC = $component->getManipulatedData($gridField, $list); $relationListC = $component->getManipulatedData($gridField, $list);
@ -139,6 +142,7 @@ class GridFieldSortableHeaderTest extends SapphireTest
$component = $gridField->getConfig()->getComponentByType(GridFieldSortableHeader::class); $component = $gridField->getConfig()->getComponentByType(GridFieldSortableHeader::class);
// Test that inherited dataobjects will work correctly // Test that inherited dataobjects will work correctly
$component->setFieldSorting(['Name' => 'Cheerleader.Hat.Colour']);
$state->SortColumn = 'Cheerleader.Hat.Colour'; $state->SortColumn = 'Cheerleader.Hat.Colour';
$state->SortDirection = 'asc'; $state->SortDirection = 'asc';
$relationListA = $component->getManipulatedData($gridField, $list); $relationListA = $component->getManipulatedData($gridField, $list);
@ -179,6 +183,7 @@ class GridFieldSortableHeaderTest extends SapphireTest
); );
// Test subclasses of tables // Test subclasses of tables
$component->setFieldSorting(['Name' => 'CheerleadersMom.Hat.Colour']);
$state->SortColumn = 'CheerleadersMom.Hat.Colour'; $state->SortColumn = 'CheerleadersMom.Hat.Colour';
$state->SortDirection = 'asc'; $state->SortDirection = 'asc';
$relationListB = $component->getManipulatedData($gridField, $list); $relationListB = $component->getManipulatedData($gridField, $list);
@ -229,4 +234,21 @@ class GridFieldSortableHeaderTest extends SapphireTest
$relationListBdesc->column('City') $relationListBdesc->column('City')
); );
} }
public function testSortColumnValidation()
{
$this->expectException(\LogicException::class);
$this->expectExceptionMessage('Invalid SortColumn: INVALID');
$list = Team::get()->filter([ 'ClassName' => Team::class ]);
$config = new GridFieldConfig_RecordEditor();
$gridField = new GridField('testfield', 'testfield', $list, $config);
$component = $gridField->getConfig()->getComponentByType(GridFieldSortableHeader::class);
$state = $gridField->State->GridFieldSortableHeader;
$state->SortColumn = 'INVALID';
$state->SortDirection = 'asc';
$component->getManipulatedData($gridField, $list);
}
} }

View File

@ -98,6 +98,36 @@ class HTMLEditorSanitiserTest extends FunctionalTest
'<iframe></iframe>', '<iframe></iframe>',
'Javascript in the src attribute of an iframe is completely removed' 'Javascript in the src attribute of an iframe is completely removed'
], ],
[
'iframe[src]',
'<iframe src="jAvAsCrIpT:alert(0);"></iframe>',
'<iframe></iframe>',
'Mixed case javascript in the src attribute of an iframe is completely removed'
],
[
'iframe[src]',
"<iframe src=\"java\tscript:alert(0);\"></iframe>",
'<iframe></iframe>',
'Javascript with tab elements the src attribute of an iframe is completely removed'
],
[
'object[data]',
'<object data="OK"></object>',
'<object data="OK"></object>',
'Object with OK content in the data attribute is retained'
],
[
'object[data]',
'<object data=javascript:alert()>',
'<object></object>',
'Object with dangerous content in data attribute is completely removed'
],
[
'img[src]',
'<img src="https://owasp.org/myimage.jpg" style="url:xss" onerror="alert(1)">',
'<img src="https://owasp.org/myimage.jpg">',
'XSS vulnerable attributes starting with on or style are removed via configuration'
],
]; ];
$config = HTMLEditorConfig::get('htmleditorsanitisertest'); $config = HTMLEditorConfig::get('htmleditorsanitisertest');

View File

@ -61,6 +61,35 @@ class DecimalTest extends SapphireTest
); );
} }
public function testLongValueStoredCorrectly()
{
$this->assertEquals(
$this->testDataObject->MyDecimal5,
1.0,
'Long default long decimal value is rounded correctly'
);
$this->assertEqualsWithDelta(
$this->testDataObject->MyDecimal5,
0.99999999999999999999,
PHP_FLOAT_EPSILON,
'Long default long decimal value is correct within float epsilon'
);
$this->assertEquals(
$this->testDataObject->MyDecimal6,
8.0,
'Long decimal value with a default value is rounded correctly'
);
$this->assertEqualsWithDelta(
$this->testDataObject->MyDecimal6,
7.99999999999999999999,
PHP_FLOAT_EPSILON,
'Long decimal value is within epsilon if longer than allowed number of float digits'
);
}
public function testScaffoldFormField() public function testScaffoldFormField()
{ {
/** @var DBDecimal $decimal */ /** @var DBDecimal $decimal */

View File

@ -14,10 +14,13 @@ class TestObject extends DataObject implements TestOnly
'MyDecimal1' => 'Decimal', 'MyDecimal1' => 'Decimal',
'MyDecimal2' => 'Decimal(5,3,2.5)', 'MyDecimal2' => 'Decimal(5,3,2.5)',
'MyDecimal3' => 'Decimal(4,2,"Invalid default value")', 'MyDecimal3' => 'Decimal(4,2,"Invalid default value")',
'MyDecimal4' => 'Decimal' 'MyDecimal4' => 'Decimal',
'MyDecimal5' => 'Decimal(20,18,0.99999999999999999999)',
'MyDecimal6' => 'Decimal',
]; ];
private static $defaults = [ private static $defaults = [
'MyDecimal4' => 4 'MyDecimal4' => 4,
'MyDecimal6' => 7.99999999999999999999,
]; ];
} }

View File

@ -3,6 +3,7 @@
namespace SilverStripe\View\Tests\Shortcodes; namespace SilverStripe\View\Tests\Shortcodes;
use Psr\SimpleCache\CacheInterface; use Psr\SimpleCache\CacheInterface;
use SilverStripe\Core\Config\Config;
use SilverStripe\View\Parsers\ShortcodeParser; use SilverStripe\View\Parsers\ShortcodeParser;
use SilverStripe\View\Shortcodes\EmbedShortcodeProvider; use SilverStripe\View\Shortcodes\EmbedShortcodeProvider;
use SilverStripe\Dev\SapphireTest; use SilverStripe\Dev\SapphireTest;
@ -186,4 +187,67 @@ class EmbedShortcodeProviderTest extends EmbedUnitTest
EmbedShortcodeProvider::flushCachedShortcodes($parser, $content); EmbedShortcodeProvider::flushCachedShortcodes($parser, $content);
$this->assertFalse($cache->has($key)); $this->assertFalse($cache->has($key));
} }
public function testOnlyWhitelistedAttributesAllowed()
{
$url = 'https://www.youtube.com/watch?v=dM15HfUYwF0';
$html = $this->getShortcodeHtml(
$url,
$url,
<<<EOT
<link rel="alternate" type="application/json+oembed" href="https://www.youtube.com/oembed?format=json&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Da2tDOYkFCYo" title="The flying car completes first ever inter-city flight (Official Video)">
EOT,
<<<EOT
{"title":"The flying car completes first ever inter-city flight (Official Video)","author_name":"KleinVision","author_url":"https://www.youtube.com/channel/UCCHAHvcO7KSNmgXVRIJLNkw","type":"video","height":113,"width":200,"version":"1.0","provider_name":"YouTube","provider_url":"https://www.youtube.com/","thumbnail_height":360,"thumbnail_width":480,"thumbnail_url":"https://i.ytimg.com/vi/a2tDOYkFCYo/hqdefault.jpg","html":"\u003ciframe width=\u0022200\u0022 height=\u0022113\u0022 src=\u0022https://www.youtube.com/embed/a2tDOYkFCYo?feature=oembed\u0022 frameborder=\u00220\u0022 allow=\u0022accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\u0022 allowfullscreen\u003e\u003c/iframe\u003e"}
EOT,
[
'url' => $url,
'caption' => 'A nice video',
'width' => 778,
'height' => 437,
'data-some-value' => 'my-data',
'onmouseover' => 'alert(2)',
'style' => 'background-color:red;',
],
);
$this->assertEqualIgnoringWhitespace(
<<<EOT
<div style="width:778px;"><iframe width="778" height="437" src="https://www.youtube.com/embed/a2tDOYkFCYo?feature=oembed" frameborder="0" allow="accelerometer;autoplay;clipboard-write;encrypted-media;gyroscope;picture-in-picture" allowfullscreen></iframe><p class="caption">A nice video</p></div>
EOT,
$html
);
}
public function testWhitelistIsConfigurable()
{
// Allow new whitelisted attribute
Config::modify()->merge(EmbedShortcodeProvider::class, 'attribute_whitelist', ['data-some-value']);
$url = 'https://www.youtube.com/watch?v=dM15HfUYwF0';
$html = $this->getShortcodeHtml(
$url,
$url,
<<<EOT
<link rel="alternate" type="application/json+oembed" href="https://www.youtube.com/oembed?format=json&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Da2tDOYkFCYo" title="The flying car completes first ever inter-city flight (Official Video)">
EOT,
<<<EOT
{"title":"The flying car completes first ever inter-city flight (Official Video)","author_name":"KleinVision","author_url":"https://www.youtube.com/channel/UCCHAHvcO7KSNmgXVRIJLNkw","type":"video","height":113,"width":200,"version":"1.0","provider_name":"YouTube","provider_url":"https://www.youtube.com/","thumbnail_height":360,"thumbnail_width":480,"thumbnail_url":"https://i.ytimg.com/vi/a2tDOYkFCYo/hqdefault.jpg","html":"\u003ciframe width=\u0022200\u0022 height=\u0022113\u0022 src=\u0022https://www.youtube.com/embed/a2tDOYkFCYo?feature=oembed\u0022 frameborder=\u00220\u0022 allow=\u0022accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\u0022 allowfullscreen\u003e\u003c/iframe\u003e"}
EOT,
[
'url' => $url,
'caption' => 'A nice video',
'width' => 779,
'height' => 437,
'data-some-value' => 'my-data',
'onmouseover' => 'alert(2)',
'style' => 'background-color:red;',
],
);
$this->assertEqualIgnoringWhitespace(
<<<EOT
<div data-some-value="my-data" style="width:779px;"><iframe width="779" height="437" src="https://www.youtube.com/embed/a2tDOYkFCYo?feature=oembed" frameborder="0" allow="accelerometer;autoplay;clipboard-write;encrypted-media;gyroscope;picture-in-picture" allowfullscreen></iframe><p class="caption">A nice video</p></div>
EOT,
$html
);
}
} }