diff options
Diffstat (limited to 'core/js')
-rw-r--r-- | core/js/contactsmenu/jquery_entry.handlebars | 6 | ||||
-rw-r--r-- | core/js/contactsmenu_templates.js | 17 | ||||
-rw-r--r-- | core/js/files/client.js | 2 | ||||
-rw-r--r-- | core/js/jquery-showpassword.js | 2 | ||||
-rw-r--r-- | core/js/jquery.contactsmenu.js | 11 | ||||
-rw-r--r-- | core/js/js.js | 16 | ||||
-rw-r--r-- | core/js/l10n.js | 218 | ||||
-rw-r--r-- | core/js/placeholder.js | 2 | ||||
-rw-r--r-- | core/js/setupchecks.js | 19 | ||||
-rw-r--r-- | core/js/sharedialoglinkshareview.js | 6 | ||||
-rw-r--r-- | core/js/tests/specs/jquery.contactsmenuSpec.js | 12 | ||||
-rw-r--r-- | core/js/tests/specs/l10nSpec.js | 22 | ||||
-rw-r--r-- | core/js/tests/specs/setupchecksSpec.js | 131 |
13 files changed, 334 insertions, 130 deletions
diff --git a/core/js/contactsmenu/jquery_entry.handlebars b/core/js/contactsmenu/jquery_entry.handlebars new file mode 100644 index 00000000000..cbd97056e5c --- /dev/null +++ b/core/js/contactsmenu/jquery_entry.handlebars @@ -0,0 +1,6 @@ +<li> + <a href="{{hyperlink}}"> + {{#if icon}}<img src="{{icon}}">{{/if}} + <span>{{title}}</span> + </a> +</li> diff --git a/core/js/contactsmenu_templates.js b/core/js/contactsmenu_templates.js index 973d93a74f0..af96a133ece 100644 --- a/core/js/contactsmenu_templates.js +++ b/core/js/contactsmenu_templates.js @@ -74,6 +74,23 @@ templates['error'] = template({"compiler":[7,">= 4.0.0"],"main":function(contain + container.escapeExpression(((helper = (helper = helpers.couldNotLoadText || (depth0 != null ? depth0.couldNotLoadText : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"couldNotLoadText","hash":{},"data":data}) : helper))) + "</h2>\n</div>\n"; },"useData":true}); +templates['jquery_entry'] = template({"1":function(container,depth0,helpers,partials,data) { + var helper; + + return "<img src=\"" + + container.escapeExpression(((helper = (helper = helpers.icon || (depth0 != null ? depth0.icon : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"icon","hash":{},"data":data}) : helper))) + + "\">"; +},"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return "<li>\n <a href=\"" + + alias4(((helper = (helper = helpers.hyperlink || (depth0 != null ? depth0.hyperlink : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"hyperlink","hash":{},"data":data}) : helper))) + + "\">\n " + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.icon : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "\n <span>" + + alias4(((helper = (helper = helpers.title || (depth0 != null ? depth0.title : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"title","hash":{},"data":data}) : helper))) + + "</span>\n </a>\n</li>\n"; +},"useData":true}); templates['list'] = template({"1":function(container,depth0,helpers,partials,data) { var helper; diff --git a/core/js/files/client.js b/core/js/files/client.js index aa450df1773..f3838dd359a 100644 --- a/core/js/files/client.js +++ b/core/js/files/client.js @@ -281,8 +281,6 @@ path = path.substr(0, path.length - 1); } - path = decodeURIComponent(path); - if (response.propStat.length === 0 || response.propStat[0].status !== 'HTTP/1.1 200 OK') { return null; } diff --git a/core/js/jquery-showpassword.js b/core/js/jquery-showpassword.js index 5d518c78bcb..de18c8068be 100644 --- a/core/js/jquery-showpassword.js +++ b/core/js/jquery-showpassword.js @@ -25,7 +25,7 @@ var $element = $(element); - $clone = $("<input />"); + var $clone = $("<input />"); // Name added for JQuery Validation compatibility // Element name is required to avoid script warning. diff --git a/core/js/jquery.contactsmenu.js b/core/js/jquery.contactsmenu.js index e3f24dfff52..4b443d5e3b3 100644 --- a/core/js/jquery.contactsmenu.js +++ b/core/js/jquery.contactsmenu.js @@ -6,13 +6,6 @@ */ (function ($) { - var ENTRY = '' - + '<li>' - + ' <a href="{{hyperlink}}">' - + ' {{#if icon}}<img src="{{icon}}">{{/if}}' - + ' <span>{{title}}</span>' - + ' </a>' - + '</li>'; var LIST = '' + '<div class="menu popovermenu menu-left hidden contactsmenu-popover">' @@ -71,7 +64,7 @@ } actions.forEach(function(action) { - var template = Handlebars.compile(ENTRY); + var template = OC.ContactsMenu.Templates['jquery_entry']; $list.find('ul').append(template(action)); }); @@ -88,7 +81,7 @@ title = t('core', 'Error fetching contact actions'); } - var template = Handlebars.compile(ENTRY); + var template = OC.ContactsMenu.Templates['jquery_entry']; $list.find('ul').append(template({ hyperlink: '#', title: title diff --git a/core/js/js.js b/core/js/js.js index e7e1c301bb5..12c47d546c1 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -368,15 +368,9 @@ var OCP = {}, addScript:function(app,script,ready){ var deferred, path=OC.filePath(app,'js',script+'.js'); if(!OC.addScript.loaded[path]) { - deferred = jQuery.ajax({ - url: path, - cache: true, - success: function (content) { - window.eval(content); - if(ready) { - ready(); - } - } + deferred = $.Deferred(); + $.getScript(path, function() { + deferred.resolve(); }); OC.addScript.loaded[path] = deferred; } else { @@ -1383,10 +1377,12 @@ function initCore() { */ function initSessionHeartBeat() { // interval in seconds - var interval = 900; + var interval = NaN; if (oc_config.session_lifetime) { interval = Math.floor(oc_config.session_lifetime / 2); } + interval = isNaN(interval)? 900: interval; + // minimum one minute interval = Math.max(60, interval); // max interval in seconds set to 24 hours diff --git a/core/js/l10n.js b/core/js/l10n.js index 77f771a20b3..6027d42dca0 100644 --- a/core/js/l10n.js +++ b/core/js/l10n.js @@ -70,12 +70,8 @@ OC.L10N = { if (_.isUndefined(this._bundles[appName])) { this._bundles[appName] = bundle || {}; - if (_.isFunction(pluralForm)) { - this._pluralFunctions[appName] = pluralForm; - } else { - // generate plural function based on form - this._pluralFunctions[appName] = this._generatePluralFunction(pluralForm); - } + // generate plural function based on form + this._pluralFunctions[appName] = this._getPlural; } else { // Theme overwriting the default language _.extend(self._bundles[appName], bundle); @@ -83,53 +79,6 @@ OC.L10N = { }, /** - * Generates a plural function based on the given plural form. - * If an invalid form has been given, returns a default function. - * - * @param {String} pluralForm plural form - */ - _generatePluralFunction: function(pluralForm) { - // default func - var func = function (n) { - var p = (n !== 1) ? 1 : 0; - return { 'nplural' : 2, 'plural' : p }; - }; - - if (!pluralForm) { - console.warn('Missing plural form in language file'); - return func; - } - - /** - * code below has been taken from jsgettext - which is LGPL licensed - * https://developer.berlios.de/projects/jsgettext/ - * http://cvs.berlios.de/cgi-bin/viewcvs.cgi/jsgettext/jsgettext/lib/Gettext.js - */ - var pf_re = new RegExp('^(\\s*nplurals\\s*=\\s*[0-9]+\\s*;\\s*plural\\s*=\\s*(?:\\s|[-\\?\\|&=!<>+*/%:;a-zA-Z0-9_\\(\\)])+)', 'm'); - if (pf_re.test(pluralForm)) { - //ex english: "Plural-Forms: nplurals=2; plural=(n != 1);\n" - //pf = "nplurals=2; plural=(n != 1);"; - //ex russian: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10< =4 && (n%100<10 or n%100>=20) ? 1 : 2) - //pf = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)"; - var pf = pluralForm; - if (! /;\s*$/.test(pf)) { - pf = pf.concat(';'); - } - /* We used to use eval, but it seems IE has issues with it. - * We now use "new Function", though it carries a slightly - * bigger performance hit. - var code = 'function (n) { var plural; var nplurals; '+pf+' return { "nplural" : nplurals, "plural" : (plural === true ? 1 : plural ? plural : 0) }; };'; - Gettext._locale_data[domain].head.plural_func = eval("("+code+")"); - */ - var code = 'var plural; var nplurals; '+pf+' return { "nplural" : nplurals, "plural" : (plural === true ? 1 : plural ? plural : 0) };'; - func = new Function("n", code); - } else { - console.warn('Invalid plural form in language file: "' + pluralForm + '"'); - } - return func; - }, - - /** * Translate a string * @param {string} app the id of the app for which to translate the string * @param {string} text the string to translate @@ -198,7 +147,7 @@ OC.L10N = { var translation = value; if ($.isArray(translation)) { var plural = this._pluralFunctions[app](count); - return this.translate(app, translation[plural.plural], vars, count, options); + return this.translate(app, translation[plural], vars, count, options); } } @@ -208,6 +157,167 @@ OC.L10N = { else{ return this.translate(app, textPlural, vars, count, options); } + }, + + /** + * The plural function taken from symfony + * + * @param {number} number + * @returns {number} + * @private + */ + _getPlural: function(number) { + var locale = OC.getLocale(); + if ('pt_BR' === locale) { + // temporary set a locale for brazilian + locale = 'xbr'; + } + + if (typeof locale === 'undefined') { + return (1 == number) ? 0 : 1; + } + + if (locale.length > 3) { + locale = locale.substring(0, locale.lastIndexOf('_')); + } + + /* + * The plural rules are derived from code of the Zend Framework (2010-09-25), + * which is subject to the new BSD license (http://framework.zend.com/license/new-bsd). + * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + */ + switch (locale) { + case 'az': + case 'bo': + case 'dz': + case 'id': + case 'ja': + case 'jv': + case 'ka': + case 'km': + case 'kn': + case 'ko': + case 'ms': + case 'th': + case 'tr': + case 'vi': + case 'zh': + return 0; + + case 'af': + case 'bn': + case 'bg': + case 'ca': + case 'da': + case 'de': + case 'el': + case 'en': + case 'eo': + case 'es': + case 'et': + case 'eu': + case 'fa': + case 'fi': + case 'fo': + case 'fur': + case 'fy': + case 'gl': + case 'gu': + case 'ha': + case 'he': + case 'hu': + case 'is': + case 'it': + case 'ku': + case 'lb': + case 'ml': + case 'mn': + case 'mr': + case 'nah': + case 'nb': + case 'ne': + case 'nl': + case 'nn': + case 'no': + case 'oc': + case 'om': + case 'or': + case 'pa': + case 'pap': + case 'ps': + case 'pt': + case 'so': + case 'sq': + case 'sv': + case 'sw': + case 'ta': + case 'te': + case 'tk': + case 'ur': + case 'zu': + return (1 == number) ? 0 : 1; + + case 'am': + case 'bh': + case 'fil': + case 'fr': + case 'gun': + case 'hi': + case 'hy': + case 'ln': + case 'mg': + case 'nso': + case 'xbr': + case 'ti': + case 'wa': + return ((0 == number) || (1 == number)) ? 0 : 1; + + case 'be': + case 'bs': + case 'hr': + case 'ru': + case 'sh': + case 'sr': + case 'uk': + return ((1 == number % 10) && (11 != number % 100)) ? 0 : (((number % 10 >= 2) && (number % 10 <= 4) && ((number % 100 < 10) || (number % 100 >= 20))) ? 1 : 2); + + case 'cs': + case 'sk': + return (1 == number) ? 0 : (((number >= 2) && (number <= 4)) ? 1 : 2); + + case 'ga': + return (1 == number) ? 0 : ((2 == number) ? 1 : 2); + + case 'lt': + return ((1 == number % 10) && (11 != number % 100)) ? 0 : (((number % 10 >= 2) && ((number % 100 < 10) || (number % 100 >= 20))) ? 1 : 2); + + case 'sl': + return (1 == number % 100) ? 0 : ((2 == number % 100) ? 1 : (((3 == number % 100) || (4 == number % 100)) ? 2 : 3)); + + case 'mk': + return (1 == number % 10) ? 0 : 1; + + case 'mt': + return (1 == number) ? 0 : (((0 == number) || ((number % 100 > 1) && (number % 100 < 11))) ? 1 : (((number % 100 > 10) && (number % 100 < 20)) ? 2 : 3)); + + case 'lv': + return (0 == number) ? 0 : (((1 == number % 10) && (11 != number % 100)) ? 1 : 2); + + case 'pl': + return (1 == number) ? 0 : (((number % 10 >= 2) && (number % 10 <= 4) && ((number % 100 < 12) || (number % 100 > 14))) ? 1 : 2); + + case 'cy': + return (1 == number) ? 0 : ((2 == number) ? 1 : (((8 == number) || (11 == number)) ? 2 : 3)); + + case 'ro': + return (1 == number) ? 0 : (((0 == number) || ((number % 100 > 0) && (number % 100 < 20))) ? 1 : 2); + + case 'ar': + return (0 == number) ? 0 : ((1 == number) ? 1 : ((2 == number) ? 2 : (((number % 100 >= 3) && (number % 100 <= 10)) ? 3 : (((number % 100 >= 11) && (number % 100 <= 99)) ? 4 : 5)))); + + default: + return 0; + } } }; diff --git a/core/js/placeholder.js b/core/js/placeholder.js index 7c1bd724550..04c2ca88401 100644 --- a/core/js/placeholder.js +++ b/core/js/placeholder.js @@ -91,7 +91,7 @@ var palette = new Array(); palette.push(color1); var step = stepCalc(steps, [color1, color2]) - for (i = 1; i < steps; i++) { + for (var i = 1; i < steps; i++) { var r = parseInt(color1.r + (step[0] * i)); var g = parseInt(color1.g + (step[1] * i)); var b = parseInt(color1.b + (step[2] * i)); diff --git a/core/js/setupchecks.js b/core/js/setupchecks.js index 1fe9e770777..ca7d979f5f3 100644 --- a/core/js/setupchecks.js +++ b/core/js/setupchecks.js @@ -427,7 +427,6 @@ if (xhr.status === 200) { var securityHeaders = { - 'X-XSS-Protection': ['1; mode=block'], 'X-Content-Type-Options': ['nosniff'], 'X-Robots-Tag': ['none'], 'X-Frame-Options': ['SAMEORIGIN', 'DENY'], @@ -448,19 +447,33 @@ } } + var xssfields = xhr.getResponseHeader('X-XSS-Protection') ? xhr.getResponseHeader('X-XSS-Protection').split(';').map(function(item) { return item.trim(); }) : []; + if (xssfields.length === 0 || xssfields.indexOf('1') === -1 || xssfields.indexOf('mode=block') === -1) { + messages.push({ + msg: t('core', 'The "{header}" HTTP header doesn\'t contain "{expected}". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.', + { + header: 'X-XSS-Protection', + expected: '1; mode=block' + }), + type: OC.SetupChecks.MESSAGE_TYPE_WARNING + }); + } + if (!xhr.getResponseHeader('Referrer-Policy') || (xhr.getResponseHeader('Referrer-Policy').toLowerCase() !== 'no-referrer' && xhr.getResponseHeader('Referrer-Policy').toLowerCase() !== 'no-referrer-when-downgrade' && xhr.getResponseHeader('Referrer-Policy').toLowerCase() !== 'strict-origin' && - xhr.getResponseHeader('Referrer-Policy').toLowerCase() !== 'strict-origin-when-cross-origin')) { + xhr.getResponseHeader('Referrer-Policy').toLowerCase() !== 'strict-origin-when-cross-origin' && + xhr.getResponseHeader('Referrer-Policy').toLowerCase() !== 'same-origin')) { messages.push({ - msg: t('core', 'The "{header}" HTTP header is not set to "{val1}", "{val2}", "{val3}" or "{val4}". This can leak referer information. See the <a target="_blank" rel="noreferrer noopener" href="{link}">W3C Recommendation ↗</a>.', + msg: t('core', 'The "{header}" HTTP header is not set to "{val1}", "{val2}", "{val3}", "{val4}" or "{val5}". This can leak referer information. See the <a target="_blank" rel="noreferrer noopener" href="{link}">W3C Recommendation ↗</a>.', { header: 'Referrer-Policy', val1: 'no-referrer', val2: 'no-referrer-when-downgrade', val3: 'strict-origin', val4: 'strict-origin-when-cross-origin', + val5: 'same-origin', link: 'https://www.w3.org/TR/referrer-policy/' }), type: OC.SetupChecks.MESSAGE_TYPE_INFO diff --git a/core/js/sharedialoglinkshareview.js b/core/js/sharedialoglinkshareview.js index 995ff480aa6..aac4843c8e0 100644 --- a/core/js/sharedialoglinkshareview.js +++ b/core/js/sharedialoglinkshareview.js @@ -114,7 +114,7 @@ }); clipboard.on('error', function (e) { var $menu = $(e.trigger); - var $linkTextMenu = $menu.parent().next('li.linkTextMenu') + var $linkTextMenu = $menu.parent().next('li.linkTextMenu'); var $input = $linkTextMenu.find('.linkText'); var actionMsg = ''; @@ -393,8 +393,8 @@ var isLinkShare = this.model.get('linkShare').isLinkShare; var isPasswordSet = !!this.model.get('linkShare').password; - var isPasswordEnforced = this.configModel.get('enforcePasswordForPublicLink') - var isPasswordEnabledByDefault = this.configModel.get('enableLinkPasswordByDefault') === true + var isPasswordEnforced = this.configModel.get('enforcePasswordForPublicLink'); + var isPasswordEnabledByDefault = this.configModel.get('enableLinkPasswordByDefault') === true; var showPasswordCheckBox = isLinkShare && ( !this.configModel.get('enforcePasswordForPublicLink') || !this.model.get('linkShare').password); diff --git a/core/js/tests/specs/jquery.contactsmenuSpec.js b/core/js/tests/specs/jquery.contactsmenuSpec.js index 80d08150c3f..9cad302a998 100644 --- a/core/js/tests/specs/jquery.contactsmenuSpec.js +++ b/core/js/tests/specs/jquery.contactsmenuSpec.js @@ -45,7 +45,7 @@ describe('jquery.contactsMenu tests', function() { it('append list if shareType supported', function() { $selector1.contactsMenu('user', 0, $appendTo); expect($appendTo.children().length).toEqual(1); - expect($appendTo.html()).toEqual('<div class="menu popovermenu menu-left hidden contactsmenu-popover"> <ul> <li> <a> <span class="icon-loading-small"></span> </a> </li> </ul></div>'); + expect($appendTo.html().replace(/[\r\n\t]?(\ \ +)?/g, '')).toEqual('<div class="menu popovermenu menu-left hidden contactsmenu-popover"><ul><li><a><span class="icon-loading-small"></span></a></li></ul></div>'); }); }); @@ -120,7 +120,7 @@ describe('jquery.contactsMenu tests', function() { expect(fakeServer.requests[0].method).toEqual('POST'); expect(fakeServer.requests[0].url).toEqual('http://localhost/index.php/contactsmenu/findOne'); - expect($appendTo.html()).toEqual('<div class="menu popovermenu menu-left contactsmenu-popover loaded" style="display: block;"> <ul> <li class="hidden"> <a> <span class="icon-loading-small"></span> </a> </li> <li> <a href="mailto:bar%40baz.wtf"> <img src="foo.svg"> <span>bar@baz.wtf</span> </a></li></ul></div>'); + expect($appendTo.html().replace(/[\r\n\t]?(\ \ +)?/g, '')).toEqual('<div class="menu popovermenu menu-left contactsmenu-popover loaded" style="display: block;"><ul><li class="hidden"><a><span class="icon-loading-small"></span></a></li><li><a href="mailto:bar%40baz.wtf"><img src="foo.svg"><span>bar@baz.wtf</span></a></li></ul></div>'); }); it('load topaction and more actions', function() { @@ -147,7 +147,7 @@ describe('jquery.contactsMenu tests', function() { expect(fakeServer.requests[0].method).toEqual('POST'); expect(fakeServer.requests[0].url).toEqual('http://localhost/index.php/contactsmenu/findOne'); - expect($appendTo.html()).toEqual('<div class="menu popovermenu menu-left contactsmenu-popover loaded" style="display: block;"> <ul> <li class="hidden"> <a> <span class="icon-loading-small"></span> </a> </li> <li> <a href="mailto:bar%40baz.wtf"> <img src="foo.svg"> <span>bar@baz.wtf</span> </a></li><li> <a href="http://localhost/index.php/apps/contacts"> <img src="details.svg"> <span>Details</span> </a></li></ul></div>'); + expect($appendTo.html().replace(/[\r\n\t]?(\ \ +)?/g, '')).toEqual('<div class="menu popovermenu menu-left contactsmenu-popover loaded" style="display: block;"><ul><li class="hidden"><a><span class="icon-loading-small"></span></a></li><li><a href="mailto:bar%40baz.wtf"><img src="foo.svg"><span>bar@baz.wtf</span></a></li><li><a href="http://localhost/index.php/apps/contacts"><img src="details.svg"><span>Details</span></a></li></ul></div>'); }); it('load no actions', function() { @@ -167,7 +167,7 @@ describe('jquery.contactsMenu tests', function() { expect(fakeServer.requests[0].method).toEqual('POST'); expect(fakeServer.requests[0].url).toEqual('http://localhost/index.php/contactsmenu/findOne'); - expect($appendTo.html()).toEqual('<div class="menu popovermenu menu-left contactsmenu-popover loaded" style="display: block;"> <ul> <li class="hidden"> <a> <span class="icon-loading-small"></span> </a> </li> <li> <a href="#"> <span>No action available</span> </a></li></ul></div>'); + expect($appendTo.html().replace(/[\r\n\t]?(\ \ +)?/g, '')).toEqual('<div class="menu popovermenu menu-left contactsmenu-popover loaded" style="display: block;"><ul><li class="hidden"><a><span class="icon-loading-small"></span></a></li><li><a href="#"><span>No action available</span></a></li></ul></div>'); }); it('should throw an error', function() { @@ -182,7 +182,7 @@ describe('jquery.contactsMenu tests', function() { expect(fakeServer.requests[0].method).toEqual('POST'); expect(fakeServer.requests[0].url).toEqual('http://localhost/index.php/contactsmenu/findOne'); - expect($appendTo.html()).toEqual('<div class="menu popovermenu menu-left contactsmenu-popover loaded" style="display: block;"> <ul> <li class="hidden"> <a> <span class="icon-loading-small"></span> </a> </li> <li> <a href="#"> <span>Error fetching contact actions</span> </a></li></ul></div>'); + expect($appendTo.html().replace(/[\r\n\t]?(\ \ +)?/g, '')).toEqual('<div class="menu popovermenu menu-left contactsmenu-popover loaded" style="display: block;"><ul><li class="hidden"><a><span class="icon-loading-small"></span></a></li><li><a href="#"><span>Error fetching contact actions</span></a></li></ul></div>'); }); it('should handle 404', function() { @@ -197,7 +197,7 @@ describe('jquery.contactsMenu tests', function() { expect(fakeServer.requests[0].method).toEqual('POST'); expect(fakeServer.requests[0].url).toEqual('http://localhost/index.php/contactsmenu/findOne'); - expect($appendTo.html()).toEqual('<div class="menu popovermenu menu-left contactsmenu-popover loaded" style="display: block;"> <ul> <li class="hidden"> <a> <span class="icon-loading-small"></span> </a> </li> <li> <a href="#"> <span>No action available</span> </a></li></ul></div>'); + expect($appendTo.html().replace(/[\r\n\t]?(\ \ +)?/g, '')).toEqual('<div class="menu popovermenu menu-left contactsmenu-popover loaded" style="display: block;"><ul><li class="hidden"><a><span class="icon-loading-small"></span></a></li><li><a href="#"><span>No action available</span></a></li></ul></div>'); }); }); diff --git a/core/js/tests/specs/l10nSpec.js b/core/js/tests/specs/l10nSpec.js index 219c9348717..01ec69aaf43 100644 --- a/core/js/tests/specs/l10nSpec.js +++ b/core/js/tests/specs/l10nSpec.js @@ -87,7 +87,6 @@ describe('OC.L10N tests', function() { spyOn(console, 'warn'); OC.L10N.register(TEST_APP, { }); - expect(console.warn).toHaveBeenCalled(); expect( n(TEST_APP, 'download %n file', 'download %n files', 0) ).toEqual('download 0 files'); @@ -107,26 +106,6 @@ describe('OC.L10N tests', function() { '_download %n file_::_download %n files_': ['%n Datei herunterladen', '%n Dateien herunterladen'] }); - expect(console.warn).toHaveBeenCalled(); - checkPlurals(); - }); - it('generates plural with generated function when forms is specified', function() { - OC.L10N.register(TEST_APP, { - '_download %n file_::_download %n files_': - ['%n Datei herunterladen', '%n Dateien herunterladen'] - }, 'nplurals=2; plural=(n != 1);'); - checkPlurals(); - }); - it('generates plural with function when forms is specified as function', function() { - OC.L10N.register(TEST_APP, { - '_download %n file_::_download %n files_': - ['%n Datei herunterladen', '%n Dateien herunterladen'] - }, function(n) { - return { - nplurals: 2, - plural: (n !== 1) ? 1 : 0 - }; - }); checkPlurals(); }); }); @@ -164,7 +143,6 @@ describe('OC.L10N tests', function() { OC.L10N.register(TEST_APP, { 'Hello world!': 'Hallo Welt!' }); - expect(console.warn).toHaveBeenCalled(); OC.L10N.load(TEST_APP, callbackStub).then(promiseStub); expect(callbackStub.calledOnce).toEqual(true); expect(promiseStub.calledOnce).toEqual(true); diff --git a/core/js/tests/specs/setupchecksSpec.js b/core/js/tests/specs/setupchecksSpec.js index a058a689ed2..47443e5e727 100644 --- a/core/js/tests/specs/setupchecksSpec.js +++ b/core/js/tests/specs/setupchecksSpec.js @@ -822,9 +822,6 @@ describe('OC.SetupChecks tests', function() { async.done(function( data, s, x ){ expect(data).toEqual([ { - msg: 'The "X-XSS-Protection" HTTP header is not set to "1; mode=block". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.', - type: OC.SetupChecks.MESSAGE_TYPE_WARNING - }, { msg: 'The "X-Content-Type-Options" HTTP header is not set to "nosniff". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.', type: OC.SetupChecks.MESSAGE_TYPE_WARNING }, { @@ -841,7 +838,10 @@ describe('OC.SetupChecks tests', function() { msg: 'The "X-Permitted-Cross-Domain-Policies" HTTP header is not set to "none". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.', type: OC.SetupChecks.MESSAGE_TYPE_WARNING }, { - msg: 'The "Referrer-Policy" HTTP header is not set to "no-referrer", "no-referrer-when-downgrade", "strict-origin" or "strict-origin-when-cross-origin". This can leak referer information. See the <a href="https://www.w3.org/TR/referrer-policy/" rel="noreferrer noopener">W3C Recommendation ↗</a>.', + msg: 'The "X-XSS-Protection" HTTP header doesn\'t contain "1; mode=block". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.', + type: OC.SetupChecks.MESSAGE_TYPE_WARNING + }, { + msg: 'The "Referrer-Policy" HTTP header is not set to "no-referrer", "no-referrer-when-downgrade", "strict-origin", "strict-origin-when-cross-origin" or "same-origin". This can leak referer information. See the <a href="https://www.w3.org/TR/referrer-policy/" rel="noreferrer noopener">W3C Recommendation ↗</a>.', type: OC.SetupChecks.MESSAGE_TYPE_INFO } ]); @@ -866,13 +866,15 @@ describe('OC.SetupChecks tests', function() { ); async.done(function( data, s, x ){ - expect(data).toEqual([{ - msg: 'The "X-XSS-Protection" HTTP header is not set to "1; mode=block". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.', - type: OC.SetupChecks.MESSAGE_TYPE_WARNING, - }, { + expect(data).toEqual([ + { msg: 'The "X-Content-Type-Options" HTTP header is not set to "nosniff". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.', type: OC.SetupChecks.MESSAGE_TYPE_WARNING - }]); + }, { + msg: 'The "X-XSS-Protection" HTTP header doesn\'t contain "1; mode=block". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.', + type: OC.SetupChecks.MESSAGE_TYPE_WARNING, + } + ]); done(); }); }); @@ -901,6 +903,102 @@ describe('OC.SetupChecks tests', function() { }); }); + describe('check X-XSS-Protection header', function() { + it('should return no message if X-XSS-Protection is set to 1; mode=block; report=https://example.com', function(done) { + protocolStub.returns('https'); + var result = OC.SetupChecks.checkGeneric(); + + suite.server.requests[0].respond(200, { + 'Strict-Transport-Security': 'max-age=15768000', + 'X-XSS-Protection': '1; mode=block; report=https://example.com', + 'X-Content-Type-Options': 'nosniff', + 'X-Robots-Tag': 'none', + 'X-Frame-Options': 'SAMEORIGIN', + 'X-Download-Options': 'noopen', + 'X-Permitted-Cross-Domain-Policies': 'none', + 'Referrer-Policy': 'no-referrer', + }); + + result.done(function( data, s, x ){ + expect(data).toEqual([]); + done(); + }); + }); + + it('should return no message if X-XSS-Protection is set to 1; mode=block', function(done) { + protocolStub.returns('https'); + var result = OC.SetupChecks.checkGeneric(); + + suite.server.requests[0].respond(200, { + 'Strict-Transport-Security': 'max-age=15768000', + 'X-XSS-Protection': '1; mode=block', + 'X-Content-Type-Options': 'nosniff', + 'X-Robots-Tag': 'none', + 'X-Frame-Options': 'SAMEORIGIN', + 'X-Download-Options': 'noopen', + 'X-Permitted-Cross-Domain-Policies': 'none', + 'Referrer-Policy': 'no-referrer', + }); + + result.done(function( data, s, x ){ + expect(data).toEqual([]); + done(); + }); + }); + + it('should return a message if X-XSS-Protection is set to 1', function(done) { + protocolStub.returns('https'); + var result = OC.SetupChecks.checkGeneric(); + + suite.server.requests[0].respond(200, { + 'Strict-Transport-Security': 'max-age=15768000', + 'X-XSS-Protection': '1', + 'X-Content-Type-Options': 'nosniff', + 'X-Robots-Tag': 'none', + 'X-Frame-Options': 'SAMEORIGIN', + 'X-Download-Options': 'noopen', + 'X-Permitted-Cross-Domain-Policies': 'none', + 'Referrer-Policy': 'no-referrer', + }); + + result.done(function( data, s, x ){ + expect(data).toEqual([ + { + msg: 'The "X-XSS-Protection" HTTP header doesn\'t contain "1; mode=block". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.', + type: OC.SetupChecks.MESSAGE_TYPE_WARNING + } + ]); + done(); + }); + }); + + it('should return a message if X-XSS-Protection is set to 0', function(done) { + protocolStub.returns('https'); + var result = OC.SetupChecks.checkGeneric(); + + suite.server.requests[0].respond(200, { + 'Strict-Transport-Security': 'max-age=15768000', + 'X-XSS-Protection': '0', + 'X-Content-Type-Options': 'nosniff', + 'X-Robots-Tag': 'none', + 'X-Frame-Options': 'SAMEORIGIN', + 'X-Download-Options': 'noopen', + 'X-Permitted-Cross-Domain-Policies': 'none', + 'Referrer-Policy': 'no-referrer', + }); + + result.done(function( data, s, x ){ + expect(data).toEqual([ + { + msg: 'The "X-XSS-Protection" HTTP header doesn\'t contain "1; mode=block". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.', + type: OC.SetupChecks.MESSAGE_TYPE_WARNING + } + ]); + done(); + }); + }); + }); + describe('check Referrer-Policy header', function() { it('should return no message if Referrer-Policy is set to no-referrer', function(done) { protocolStub.returns('https'); @@ -986,7 +1084,7 @@ describe('OC.SetupChecks tests', function() { }); }); - it('should return a message if Referrer-Policy is set to same-origin', function(done) { + it('should return no message if Referrer-Policy is set to same-origin', function(done) { protocolStub.returns('https'); var result = OC.SetupChecks.checkGeneric(); @@ -1002,12 +1100,7 @@ describe('OC.SetupChecks tests', function() { }); result.done(function( data, s, x ){ - expect(data).toEqual([ - { - msg: 'The "Referrer-Policy" HTTP header is not set to "no-referrer", "no-referrer-when-downgrade", "strict-origin" or "strict-origin-when-cross-origin". This can leak referer information. See the <a href="https://www.w3.org/TR/referrer-policy/" rel="noreferrer noopener">W3C Recommendation ↗</a>.', - type: OC.SetupChecks.MESSAGE_TYPE_INFO - } - ]); + expect(data).toEqual([]); done(); }); }); @@ -1030,7 +1123,7 @@ describe('OC.SetupChecks tests', function() { result.done(function( data, s, x ){ expect(data).toEqual([ { - msg: 'The "Referrer-Policy" HTTP header is not set to "no-referrer", "no-referrer-when-downgrade", "strict-origin" or "strict-origin-when-cross-origin". This can leak referer information. See the <a href="https://www.w3.org/TR/referrer-policy/" rel="noreferrer noopener">W3C Recommendation ↗</a>.', + msg: 'The "Referrer-Policy" HTTP header is not set to "no-referrer", "no-referrer-when-downgrade", "strict-origin", "strict-origin-when-cross-origin" or "same-origin". This can leak referer information. See the <a href="https://www.w3.org/TR/referrer-policy/" rel="noreferrer noopener">W3C Recommendation ↗</a>.', type: OC.SetupChecks.MESSAGE_TYPE_INFO } ]); @@ -1056,7 +1149,7 @@ describe('OC.SetupChecks tests', function() { result.done(function( data, s, x ){ expect(data).toEqual([ { - msg: 'The "Referrer-Policy" HTTP header is not set to "no-referrer", "no-referrer-when-downgrade", "strict-origin" or "strict-origin-when-cross-origin". This can leak referer information. See the <a href="https://www.w3.org/TR/referrer-policy/" rel="noreferrer noopener">W3C Recommendation ↗</a>.', + msg: 'The "Referrer-Policy" HTTP header is not set to "no-referrer", "no-referrer-when-downgrade", "strict-origin", "strict-origin-when-cross-origin" or "same-origin". This can leak referer information. See the <a href="https://www.w3.org/TR/referrer-policy/" rel="noreferrer noopener">W3C Recommendation ↗</a>.', type: OC.SetupChecks.MESSAGE_TYPE_INFO } ]); @@ -1082,7 +1175,7 @@ describe('OC.SetupChecks tests', function() { result.done(function( data, s, x ){ expect(data).toEqual([ { - msg: 'The "Referrer-Policy" HTTP header is not set to "no-referrer", "no-referrer-when-downgrade", "strict-origin" or "strict-origin-when-cross-origin". This can leak referer information. See the <a href="https://www.w3.org/TR/referrer-policy/" rel="noreferrer noopener">W3C Recommendation ↗</a>.', + msg: 'The "Referrer-Policy" HTTP header is not set to "no-referrer", "no-referrer-when-downgrade", "strict-origin", "strict-origin-when-cross-origin" or "same-origin". This can leak referer information. See the <a href="https://www.w3.org/TR/referrer-policy/" rel="noreferrer noopener">W3C Recommendation ↗</a>.', type: OC.SetupChecks.MESSAGE_TYPE_INFO } ]); |