+ * @param {string=} overlay.size Sets an alias for the size of the overlay to be opened. If set to `small` (default), an `umb-overlay--small` class name will be appended the the class list of the main overlay element in the DOM.
+ *
+ * Umbraco does not support any more sizes by default, but if you wish to introduce a `medium` size, you could do so by adding a CSS rule simlar to:
+ *
+ *
+ * @param {booean=} overlay.disableBackdropClick A boolean value indicating whether the click event on the backdrop should be disabled.
+ * @param {string=} overlay.title The overall title of the overlay. The title will be omitted if not specified.
+ * @param {string=} overlay.subtitle The sub title of the overlay. The sub title will be omitted if not specified.
+ * @param {object=} overlay.itemDetails An item that will replace the header of the overlay.
+ * @param {string=} overlay.itemDetails.icon The icon of the item - eg. `icon-book`.
+ * @param {string=} overlay.itemDetails.title The title of the item.
+ * @param {string=} overlay.itemDetails.description Sets the description of the item. *
+ * @param {string=} overlay.submitButtonLabel The label of the submit button. To support localized values, it's recommended to use the `submitButtonLabelKey` instead.
+ * @param {string=} overlay.submitButtonLabelKey The key to be used for the submit button label. Defaults to `general_submit` if not specified.
+ * @param {string=} overlay.submitButtonState The state of the submit button. Possible values are inherited from the [umbButton directive](#/api/umbraco.directives.directive:umbButton) and are `init`, `busy", `success`, `error`.
+ * @param {string=} overlay.submitButtonStyle The styling of the submit button. Possible values are inherited from the [umbButton directive](#/api/umbraco.directives.directive:umbButton) and are `primary`, `info`, `success`, `warning`, `danger`, `inverse`, `link` and `block`. Defaults to `success` if not specified specified.
+ * @param {string=} overlay.hideSubmitButton A boolean value indicating whether the submit button should be hidden. Default is `false`.
+ * @param {string=} overlay.disableSubmitButton A boolean value indicating whether the submit button should be disabled, preventing the user from submitting the overlay. Default is `false`.
+ * @param {string=} overlay.closeButtonLabel The label of the close button. To support localized values, it's recommended to use the `closeButtonLabelKey` instead.
+ * @param {string=} overlay.closeButtonLabelKey The key to be used for the close button label. Defaults to `general_close` if not specified.
+ * @param {string=} overlay.submit A callback function that is invoked when the user submits the overlay.
+ * @param {string=} overlay.close A callback function that is invoked when the user closes the overlay.
+ */
function open(newOverlay) {
// prevent two open overlays at the same time
@@ -49,6 +101,14 @@
eventsService.emit("appState.overlay", overlay);
}
+ /**
+ * @ngdoc method
+ * @name umbraco.services.overlayService#close
+ * @methodOf umbraco.services.overlayService
+ *
+ * @description
+ * Closes the current overlay.
+ */
function close() {
focusLockService.removeInertAttribute();
@@ -61,6 +121,16 @@
eventsService.emit("appState.overlay", null);
}
+ /**
+ * @ngdoc method
+ * @name umbraco.services.overlayService#ysod
+ * @methodOf umbraco.services.overlayService
+ *
+ * @description
+ * Opens a new overlay with an error message.
+ *
+ * @param {object} error The error to be shown.
+ */
function ysod(error) {
const overlay = {
view: "views/common/overlays/ysod/ysod.html",
@@ -72,6 +142,36 @@
open(overlay);
}
+ /**
+ * @ngdoc method
+ * @name umbraco.services.overlayService#confirm
+ * @methodOf umbraco.services.overlayService
+ *
+ * @description
+ * Opens a new overlay prompting the user to confirm the overlay.
+ *
+ * @param {object} overlay The options for the overlay.
+ * @param {string=} overlay.confirmType The type of the confirm dialog, which helps define standard styling and labels of the overlay. Supported values are `delete` and `remove`.
+ * @param {string=} overlay.closeButtonLabelKey The key to be used for the cancel button label. Defaults to `general_cancel` if not specified.
+ * @param {string=} overlay.view The URL to the view. Defaults to `views/common/overlays/confirm/confirm.html` if nothing is specified.
+ * @param {string=} overlay.confirmMessageStyle The styling of the confirm message. If `overlay.confirmType` is `delete`, the fallback value is `danger` - otherwise a message style isn't explicitly specified.
+ * @param {string=} overlay.submitButtonStyle The styling of the confirm button. Possible values are inherited from the [umbButton directive](#/api/umbraco.directives.directive:umbButton) and are `primary`, `info`, `success`, `warning`, `danger`, `inverse`, `link` and `block`.
+ *
+ * If not specified, the fallback value depends on the value specified for the `overlay.confirmType` parameter:
+ *
+ * - `delete`: fallback key is `danger`
+ * - `remove`: fallback key is `primary`
+ * - anything else: no fallback AKA default button style
+ * @param {string=} overlay.submitButtonLabelKey The key to be used for the confirm button label.
+ *
+ * If not specified, the fallback value depends on the value specified for the `overlay.confirmType` parameter:
+ *
+ * - `delete`: fallback key is `actions_delete`
+ * - `remove`: fallback key is `actions_remove`
+ * - anything else: fallback is `general_confirm`
+ * @param {function=} overlay.close A callback function that is invoked when the user closes the overlay.
+ * @param {function=} overlay.submit A callback function that is invoked when the user confirms the overlay.
+ */
function confirm(overlay) {
if (!overlay.closeButtonLabelKey) overlay.closeButtonLabelKey = "general_cancel";
@@ -99,11 +199,45 @@
open(overlay);
}
+ /**
+ * @ngdoc method
+ * @name umbraco.services.overlayService#confirmDelete
+ * @methodOf umbraco.services.overlayService
+ *
+ * @description
+ * Opens a new overlay prompting the user to confirm the overlay. The overlay will have styling and labels useful for when the user needs to confirm a delete action.
+ *
+ * @param {object} overlay The options for the overlay.
+ * @param {string=} overlay.closeButtonLabelKey The key to be used for the cancel button label. Defaults to `general_cancel` if not specified.
+ * @param {string=} overlay.view The URL to the view. Defaults to `views/common/overlays/confirm/confirm.html` if nothing is specified.
+ * @param {string=} overlay.confirmMessageStyle The styling of the confirm message. Defaults to `delete` if not specified specified.
+ * @param {string=} overlay.submitButtonStyle The styling of the confirm button. Possible values are inherited from the [umbButton directive](#/api/umbraco.directives.directive:umbButton) and are `primary`, `info`, `success`, `warning`, `danger`, `inverse`, `link` and `block`. Defaults to `danger` if not specified specified.
+ * @param {string=} overlay.submitButtonLabelKey The key to be used for the confirm button label. Defaults to `actions_delete` if not specified.
+ * @param {function=} overlay.close A callback function that is invoked when the user closes the overlay.
+ * @param {function=} overlay.submit A callback function that is invoked when the user confirms the overlay.
+ */
function confirmDelete(overlay) {
overlay.confirmType = "delete";
confirm(overlay);
}
+ /**
+ * @ngdoc method
+ * @name umbraco.services.overlayService#confirmRemove
+ * @methodOf umbraco.services.overlayService
+ *
+ * @description
+ * Opens a new overlay prompting the user to confirm the overlay. The overlay will have styling and labels useful for when the user needs to confirm a remove action.
+ *
+ * @param {object} overlay The options for the overlay.
+ * @param {string=} overlay.closeButtonLabelKey The key to be used for the cancel button label. Defaults to `general_cancel` if not specified.
+ * @param {string=} overlay.view The URL to the view. Defaults to `views/common/overlays/confirm/confirm.html` if nothing is specified.
+ * @param {string=} overlay.confirmMessageStyle The styling of the confirm message - eg. `danger`.
+ * @param {string=} overlay.submitButtonStyle The styling of the confirm button. Possible values are inherited from the [umbButton directive](#/api/umbraco.directives.directive:umbButton) and are `primary`, `info`, `success`, `warning`, `danger`, `inverse`, `link` and `block`. Defaults to `primary` if not specified specified.
+ * @param {string=} overlay.submitButtonLabelKey The key to be used for the confirm button label. Defaults to `actions_remove` if not specified.
+ * @param {function=} overlay.close A callback function that is invoked when the user closes the overlay.
+ * @param {function=} overlay.submit A callback function that is invoked when the user confirms the overlay.
+ */
function confirmRemove(overlay) {
overlay.confirmType = "remove";
confirm(overlay);
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js
index 4556641eca76..6c6237263f49 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js
@@ -1502,6 +1502,19 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
});
}
+
+ if(Umbraco.Sys.ServerVariables.umbracoSettings.sanitizeTinyMce === true){
+ /** prevent injecting arbitrary JavaScript execution in on-attributes. */
+ const allNodes = Array.prototype.slice.call(args.editor.dom.doc.getElementsByTagName("*"));
+ allNodes.forEach(node => {
+ for (var i = 0; i < node.attributes.length; i++) {
+ if(node.attributes[i].name.indexOf("on") === 0) {
+ node.removeAttribute(node.attributes[i].name)
+ }
+ }
+ });
+ }
+
});
args.editor.on('init', function (e) {
@@ -1513,6 +1526,60 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
//enable browser based spell checking
args.editor.getBody().setAttribute('spellcheck', true);
+
+ /** Setup sanitization for preventing injecting arbitrary JavaScript execution in attributes:
+ * https://github.com/advisories/GHSA-w7jx-j77m-wp65
+ * https://github.com/advisories/GHSA-5vm8-hhgr-jcjp
+ */
+ const uriAttributesToSanitize = ['src', 'href', 'data', 'background', 'action', 'formaction', 'poster', 'xlink:href'];
+ const parseUri = function() {
+ // Encapsulated JS logic.
+ const safeSvgDataUrlElements = [ 'img', 'video' ];
+ const scriptUriRegExp = /((java|vb)script|mhtml):/i;
+ const trimRegExp = /[\s\u0000-\u001F]+/g;
+ const isInvalidUri = (uri, tagName) => {
+ if (/^data:image\//i.test(uri)) {
+ return safeSvgDataUrlElements.indexOf(tagName) !== -1 && /^data:image\/svg\+xml/i.test(uri);
+ } else {
+ return /^data:/i.test(uri);
+ }
+ };
+
+ return function parseUri(uri, tagName) {
+ uri = uri.replace(trimRegExp, '');
+ try {
+ // Might throw malformed URI sequence
+ uri = decodeURIComponent(uri);
+ } catch (ex) {
+ // Fallback to non UTF-8 decoder
+ uri = unescape(uri);
+ }
+
+ if (scriptUriRegExp.test(uri)) {
+ return;
+ }
+
+ if (isInvalidUri(uri, tagName)) {
+ return;
+ }
+
+ return uri;
+ }
+ }();
+
+ if(Umbraco.Sys.ServerVariables.umbracoSettings.sanitizeTinyMce === true){
+ args.editor.serializer.addAttributeFilter(uriAttributesToSanitize, function (nodes) {
+ nodes.forEach(function(node) {
+ node.attributes.forEach(function(attr) {
+ const attrName = attr.name.toLowerCase();
+ if(uriAttributesToSanitize.indexOf(attrName) !== -1) {
+ attr.value = parseUri(attr.value, node.name);
+ }
+ });
+ });
+ });
+ }
+
//start watching the value
startWatch();
});
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less
index d0427cad0a3d..6c1e5058d267 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less
@@ -55,6 +55,11 @@ input.umb-table__input {
color: @ui-disabled-type;
}
+.umb-table-head__icon {
+ position: relative;
+ top: 2px;
+}
+
.umb-table-head__link {
background: transparent;
border: 0 none;
@@ -111,7 +116,7 @@ input.umb-table__input {
.umb-table-body .umb-table-row.-selectable {
cursor: pointer;
}
-.umb-table-row.-selected,
+.umb-table-row.-selected,
.umb-table-body .umb-table-row.-selectable:hover {
&::before {
content: "";
@@ -226,7 +231,7 @@ input.umb-table__input {
&.umb-table-body__checkicon {
display: inline-block;
}
- }
+ }
}
// Table Row Styles
@@ -309,8 +314,8 @@ input.umb-table__input {
.umb-table__loading-overlay {
position: absolute;
- width: 100%;
- height: 100%;
+ width: 100%;
+ height: 100%;
background-color: rgba(255, 255, 255, 0.7);
z-index: 1;
}
@@ -330,7 +335,7 @@ input.umb-table__input {
}
.umb-table--condensed {
-
+
.umb-table-cell:first-of-type:not(.not-fixed) {
padding-top: 10px;
padding-bottom: 10px;
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html
index e8f174516c13..77ace4af7004 100644
--- a/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html
+++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html
@@ -60,20 +60,20 @@
ng-click="vm.selectAll($event)"
ng-checked="vm.isSelectedAll()">
-
-
+
+
+ The selected element type does not contain any supported groups (tabs are not supported by this editor, either change them to groups or use the Block List editor).
+
+
diff --git a/src/Umbraco.Web.UI.Docs/umb-docs.css b/src/Umbraco.Web.UI.Docs/umb-docs.css
index 850e0d4aa45b..80d1bbbd2a0d 100644
--- a/src/Umbraco.Web.UI.Docs/umb-docs.css
+++ b/src/Umbraco.Web.UI.Docs/umb-docs.css
@@ -34,7 +34,8 @@ a:hover {
color: rgba(0, 0, 0, .8);
}
-.content p code {
+.content p code,
+.content li code {
font-size: 85%;
font-family: inherit;
background-color: #f7f7f9;
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
index 72ad387baed4..f1a879cb0160 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
@@ -282,6 +282,7 @@
name. Use
to display the item index
+ The selected element type does not contain any supported groups (tabs are not supported by this editor, either change them to groups or use the Block List editor).Add another text boxRemove this text boxContent root
@@ -325,6 +326,7 @@
Click to uploador click here to choose filesCannot upload this file, it does not have an approved file type
+ Cannot upload this file, it does not have a valid file nameMax file size isMedia rootFailed to create a folder under parent id %0%
@@ -848,6 +850,7 @@
Avatar forHeadersystem field
+ Last UpdatedBlue
@@ -1168,7 +1171,6 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
%6%
Have a nice day!
-
Cheers from the Umbraco robot
]]>
The following languages have been modified %0%
@@ -1906,7 +1908,6 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
http://%3%
Have a nice day!
-
Cheers from the Umbraco robot
]]>
No translator users found. Please create a translator user before you start sending
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
index eb8538af2078..8664cfb5587c 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
@@ -286,6 +286,7 @@
name. Use
to display the item index
+ The selected element type does not contain any supported groups (tabs are not supported by this editor, either change them to groups or use the Block List editor).Add another text boxRemove this text boxContent root
@@ -329,6 +330,7 @@
Click to uploador click here to choose filesCannot upload this file, it does not have an approved file type
+ Cannot upload this file, it does not have a valid file nameMax file size isMedia rootParent and destination folders cannot be the same
@@ -869,6 +871,7 @@
Avatar forHeadersystem field
+ Last UpdatedBlue
diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Configurations/LanguageXmlTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Configurations/LanguageXmlTests.cs
new file mode 100644
index 000000000000..623d207687c5
--- /dev/null
+++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Configurations/LanguageXmlTests.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using NUnit.Framework;
+
+namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Configurations
+{
+ [TestFixture]
+ public class LanguageXmlTests
+ {
+ [Test]
+ [Platform("Win")] //TODO figure out why Path.GetFullPath("/mnt/c/...") is not considered an absolute path on linux + mac
+ public void Can_Load_Language_Xml_Files()
+ {
+ var languageDirectoryPath = GetLanguageDirectory();
+ var readFilesCount = 0;
+ var xmlDocument = new XmlDocument();
+
+ var directoryInfo = new DirectoryInfo(languageDirectoryPath);
+
+ foreach (var languageFile in directoryInfo.GetFiles("*.xml", SearchOption.TopDirectoryOnly))
+ {
+ // Load will throw an exception if the XML isn't valid.
+ xmlDocument.Load(languageFile.FullName);
+ readFilesCount++;
+ }
+
+ // Ensure that at least one file was read.
+ Assert.AreNotEqual(0, readFilesCount);
+ }
+
+ private static string GetLanguageDirectory()
+ {
+ var testDirectoryPathParts = Path.GetDirectoryName(TestContext.CurrentContext.TestDirectory)
+ .Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
+
+ var solutionDirectoryPathParts = testDirectoryPathParts
+ .Take(Array.IndexOf(testDirectoryPathParts, "tests"));
+ var languageFolderPathParts = new List(solutionDirectoryPathParts);
+ var additionalPathParts = new[] { "Umbraco.Web.UI", "umbraco", "config", "lang" };
+ languageFolderPathParts.AddRange(additionalPathParts);
+
+ // Hack for build-server - when this path is generated in that envrionment it's missing the "src" folder.
+ // Not sure why, but if it's missing we'll add it in the right place.
+ if (!languageFolderPathParts.Contains("src"))
+ {
+ languageFolderPathParts.Insert(languageFolderPathParts.Count - additionalPathParts.Length, "src");
+ }
+
+ return string.Join(Path.DirectorySeparatorChar.ToString(), languageFolderPathParts);
+ }
+ }
+}