From c4953d686f4761a4ba31d4cf7e92c090055dc031 Mon Sep 17 00:00:00 2001 From: Andrew Kondratev Date: Fri, 27 Sep 2019 15:40:33 +1200 Subject: [PATCH 1/4] WICKET-6703 replace eval with jQuery.globalEval; add suspend/notify --- .../wicket/ajax/AjaxRequestHandler.java | 6 + .../wicket/ajax/res/js/wicket-ajax-jquery.js | 177 +++++++++--------- .../handler/IPartialPageRequestHandler.java | 9 + .../head/filter/CspNonceHeaderResponse.java | 5 +- .../apache/wicket/page/PartialPageUpdate.java | 32 +++- .../wicket/page/XmlPartialPageUpdate.java | 10 + .../head/filter/CspNoncePageExpected.html | 2 +- .../examples/ajax/builtin/EffectsPage.html | 29 ++- .../examples/ajax/builtin/EffectsPage.java | 49 ++++- .../examples/ajax/builtin/EffectsPage.js | 26 +++ .../wicket/examples/csp/CspApplication.java | 41 +++- .../wicket/examples/csp/NonceDemoPage.java | 4 +- .../ws/api/WebSocketRequestHandler.java | 6 + 13 files changed, 291 insertions(+), 105 deletions(-) create mode 100644 wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/EffectsPage.js diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestHandler.java b/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestHandler.java index 1dad0487e2e..63cb4a0bfec 100644 --- a/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestHandler.java +++ b/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestHandler.java @@ -266,6 +266,12 @@ public final void appendJavaScript(CharSequence javascript) update.appendJavaScript(javascript); } + @Override + public void addMeta(CharSequence name, CharSequence value) + { + update.addMeta(name, value); + } + /** * @see org.apache.wicket.core.request.handler.IPageRequestHandler#detach(org.apache.wicket.request.IRequestCycle) */ diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js index 70dd69dca7d..2cd28edd3fb 100644 --- a/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js +++ b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js @@ -187,7 +187,7 @@ * Logging functionality. */ Wicket.Log = { - + enabled: false, log: function () { @@ -350,6 +350,44 @@ */ Wicket.Ajax.Call = Wicket.Class.create(); + Wicket.Ajax.Call._suspended = 0; + + Wicket.Ajax.Call.currentNotify = undefined; + + Wicket.Ajax.Call.suspend = function () { + if (typeof (Wicket.Ajax.Call.currentNotify) != "function") { + Wicket.Log.error("Can't suspend: no evaluation in process"); + return; + } + Wicket.Ajax.Call._suspended++; + var notify = Wicket.Ajax.Call.currentNotify; + var released = false; + + return function () { + // release only once + if (released === false) { + released = true; + Wicket.Ajax.Call._suspended--; + if (Wicket.Ajax.Call._suspended === 0) { + notify(); + } + } + } + }; + + Wicket.Ajax.Call.getFunctionsExecuterStatus = function() { + if (Wicket.Ajax.Call._suspended) { + // suspended + return FunctionsExecuter.ASYNC; + } else { + // execution finished, cleanup the last notify + Wicket.Ajax.Call.currentNotify = undefined; + Wicket.Ajax.Call._suspended = 0; + // continue to next step + return FunctionsExecuter.DONE; + } + }; + Wicket.Ajax.Call.prototype = { initialize: jQuery.noop, @@ -529,20 +567,20 @@ }, /** - * Is an element still present for Ajax requests. + * Is an element still present for Ajax requests. */ _isPresent: function(id) { if (isUndef(id)) { // no id so no check whether present return true; } - + var element = Wicket.$(id); if (isUndef(element)) { // not present return false; } - + // present if no attributes at all or not a placeholder return (!element.hasAttribute || !element.hasAttribute('data-wicket-placeholder')); }, @@ -560,7 +598,7 @@ 'Wicket-Ajax': 'true', 'Wicket-Ajax-BaseURL': getAjaxBaseUrl() }, - + url = attrs.u, // the request (extra) parameters @@ -570,7 +608,7 @@ // the precondition to use if there are no explicit ones defaultPrecondition = [ function (attributes) { - return self._isPresent(attributes.c) && self._isPresent(attributes.f); + return self._isPresent(attributes.c) && self._isPresent(attributes.f); }], // a context that brings the common data for the success/fialure/complete handlers @@ -631,7 +669,7 @@ var el = Wicket.$(attrs.c); data = data.concat(Wicket.Form.serializeElement(el, attrs.sr)); } - + // collect the dynamic extra parameters if (jQuery.isArray(attrs.dep)) { var dynamicData = this._calculateDynamicParameters(attrs); @@ -650,7 +688,7 @@ for (var i = 0; i < data.length; i++) { formData.append(data[i].name, data[i].value || ""); } - + data = formData; wwwFormUrlEncoded = false; } catch (exception) { @@ -668,7 +706,7 @@ context: self, processData: wwwFormUrlEncoded, contentType: wwwFormUrlEncoded, - + beforeSend: function (jqXHR, settings) { self._executeHandlers(attrs.bsh, attrs, jqXHR, settings); we.publish(topic.AJAX_CALL_BEFORE_SEND, attrs, jqXHR, settings); @@ -823,15 +861,25 @@ return; } + var nonce; + var meta = root.getElementsByTagName("meta")[0]; + if (!isUndef(meta)) { + // var nonceEl = meta.getElementsByTagName("wicket-nonce")[0]; + // if (!isUndef(nonceEl)) { + // nonce = Wicket.DOM.text(nonceEl); + // } + nonce = Wicket.DOM.text(meta.getElementsByTagName("wicket-nonce")[0]); + } + var steps = context.steps; // go through the ajax response and execute all priority-invocations first for (var i = 0; i < root.childNodes.length; ++i) { var childNode = root.childNodes[i]; if (childNode.tagName === "header-contribution") { - this.processHeaderContribution(context, childNode); + this.processHeaderContribution(context, childNode, nonce); } else if (childNode.tagName === "priority-evaluate") { - this.processEvaluation(context, childNode); + this.processEvaluation(context, childNode, nonce); } } @@ -848,7 +896,7 @@ stepIndexOfLastReplacedComponent = steps.length; this.processComponent(context, node); } else if (node.tagName === "evaluate") { - this.processEvaluation(context, node); + this.processEvaluation(context, node, nonce); } else if (node.tagName === "redirect") { this.processRedirect(context, node); } @@ -929,19 +977,10 @@ /** * Adds a closure that evaluates javascript code. * @param context {Object} - the object that brings the executer's steps and the attributes - * @param node {XmlElement} - the <[priority-]evaluate> element with the script to evaluate + * @param node {Element} - the <[priority-]evaluate> element with the script to evaluate + * @param nonce {String} - optional CSP nonce */ - processEvaluation: function (context, node) { - - // used to match evaluation scripts which manually call FunctionsExecuter's notify() when ready - var scriptWithIdentifierR = new RegExp("\\(function\\(\\)\\{([a-zA-Z_]\\w*)\\|((.|\\n)*)?\\}\\)\\(\\);$"); - - /** - * A regex used to split the text in (priority-)evaluate elements in the Ajax response - * when there are scripts which require manual call of 'FunctionExecutor#notify()' - * @type {RegExp} - */ - var scriptSplitterR = new RegExp("\\(function\\(\\)\\{[\\s\\S]*?}\\)\\(\\);", 'gi'); + processEvaluation: function (context, node, nonce) { // get the javascript body var text = Wicket.DOM.text(node); @@ -950,67 +989,28 @@ var steps = context.steps; var log = Wicket.Log; - var evaluateWithManualNotify = function (parameters, body) { - return function(notify) { - var toExecute = "(function(" + parameters + ") {" + body + "})"; - - try { - // do the evaluation in global scope - var f = window.eval(toExecute); - f(notify); - } catch (exception) { - log.error("Wicket.Ajax.Call.processEvaluation: Exception evaluating javascript: %s", text, exception); - } - return FunctionsExecuter.ASYNC; - }; - }; - var evaluate = function (script) { return function(notify) { // just evaluate the javascript + Wicket.Ajax.Call.currentNotify = notify; try { // do the evaluation in global scope - window.eval(script); + jQuery.globalEval(script, {nonce: nonce}); } catch (exception) { log.error("Ajax.Call.processEvaluation: Exception evaluating javascript: %s", text, exception); } // continue to next step - return FunctionsExecuter.DONE; + return Wicket.Ajax.Call.getFunctionsExecuterStatus(); }; }; - // test if the javascript is in form of identifier|code - // if it is, we allow for letting the javascript decide when the rest of processing will continue - // by invoking identifier();. This allows usage of some asynchronous/deferred logic before the next script - // See WICKET-5039 - if (scriptWithIdentifierR.test(text)) { - var scripts = []; - var scr; - while ( (scr = scriptSplitterR.exec(text) ) !== null ) { - scripts.push(scr[0]); - } - - for (var s = 0; s < scripts.length; s++) { - var script = scripts[s]; - if (script) { - var scriptWithIdentifier = script.match(scriptWithIdentifierR); - if (scriptWithIdentifier) { - steps.push(evaluateWithManualNotify(scriptWithIdentifier[1], scriptWithIdentifier[2])); - } - else { - steps.push(evaluate(script)); - } - } - } - } else { - steps.push(evaluate(text)); - } + steps.push(evaluate(text)); }, // Adds a closure that processes a header contribution - processHeaderContribution: function (context, node) { + processHeaderContribution: function (context, node, nonce) { var c = Wicket.Head.Contributor; - c.processContribution(context, node); + c.processContribution(context, node, nonce); }, // Adds a closure that processes a redirect @@ -1231,7 +1231,7 @@ var result = []; if (input && input.type) { var $input = jQuery(input); - + if (input.type === 'file') { for (var f = 0; f < input.files.length; f++) { result.push({"name" : input.name, "value" : input.files[f]}); @@ -1608,7 +1608,7 @@ * Reads the text from the node's children nodes. * Used instead of jQuery.text() because it is very slow in IE10/11. * WICKET-5132, WICKET-5510 - * @param node {DOMElement} the root node + * @param node {Element} the root node */ text: function (node) { if (isUndef(node)) { @@ -1730,7 +1730,7 @@ }, null, attrs.sel); }); }, - + process: function(data) { var call = new Wicket.Ajax.Call(); call.process(data); @@ -1766,7 +1766,7 @@ parse: function (headerNode) { // the header contribution is stored as CDATA section in the header-contribution element, // we need to parse it since each header contribution needs to be treated separately - + // get the header contribution text and unescape it if necessary var text = Wicket.DOM.text(headerNode); @@ -1789,7 +1789,7 @@ }, // Processes the parsed header contribution - processContribution: function (context, headerNode) { + processContribution: function (context, headerNode, nonce) { var xmldoc = this.parse(headerNode); var rootNode = xmldoc.documentElement; @@ -1828,9 +1828,9 @@ if (name === "link") { this.processLink(context, node); } else if (name === "script") { - this.processScript(context, node); + this.processScript(context, node, nonce); } else if (name === "style") { - this.processStyle(context, node); + this.processStyle(context, node, nonce); } else if (name === "meta") { this.processMeta(context, node); } @@ -1891,7 +1891,7 @@ }, // Process an inline style element - processStyle: function (context, node) { + processStyle: function (context, node, nonce) { context.steps.push(function (notify) { // if element with same id is already in document, skip it if (Wicket.DOM.containsElement(node)) { @@ -1905,6 +1905,7 @@ // copy id attribute style.id = node.getAttribute("id"); + style.nonce = nonce; var textNode = document.createTextNode(content); style.appendChild(textNode); @@ -1917,7 +1918,7 @@ }, // Process a script element (both inline and external) - processScript: function (context, node) { + processScript: function (context, node, nonce) { context.steps.push(function (notify) { if (!node.getAttribute("src") && Wicket.DOM.containsElement(node)) { @@ -1982,11 +1983,11 @@ if (typeof(id) === "string" && id.length > 0) { // add javascript to document head - Wicket.Head.addJavascript(text, id, "", type); + Wicket.Head.addJavascript(text, id, "", type, nonce); } else { try { // do the evaluation in global scope - window.eval(text); + jQuery.globalEval(text, {nonce: nonce}); } catch (e) { Wicket.Log.error("Wicket.Head.Contributor.processScript: %s", text, e); } @@ -2003,9 +2004,12 @@ var meta = Wicket.Head.createElement("meta"), $meta = jQuery(meta), attrs = jQuery(node).prop("attributes"), - name = node.getAttribute("name"); + name = node.getAttribute("name"), + id = node.getAttribute("id"); - if(name) { + if (id) { + jQuery('meta[id="' + id + '"]').remove(); + } else if (name) { jQuery('meta[name="' + name + '"]').remove(); } jQuery.each(attrs, function() { @@ -2109,7 +2113,7 @@ // attribute to filter out duplicates. However, since we set the body of the element, we can't assign // also a src value. Therefore we put the url to the src_ (notice the underscore) attribute. // Wicket.Head.containsElement is aware of that and takes also the underscored attributes into account. - addJavascript: function (content, id, fakeSrc, type) { + addJavascript: function (content, id, fakeSrc, type, nonce) { var script = Wicket.Head.createElement("script"); if (id) { script.id = id; @@ -2124,6 +2128,9 @@ script.setAttribute("src_", fakeSrc); script.setAttribute("type", type); + if (nonce) { + script.setAttribute("nonce", nonce) + } // set the javascript as element content if (null === script.canHaveChildren || script.canHaveChildren) { @@ -2346,7 +2353,7 @@ delete Wicket.TimerHandles[timerId]; } }, - + /** * Clear all remaining timers. */ @@ -2361,7 +2368,7 @@ } } }, - + /** * Events related code * Based on code from Mootools (http://mootools.net) diff --git a/wicket-core/src/main/java/org/apache/wicket/core/request/handler/IPartialPageRequestHandler.java b/wicket-core/src/main/java/org/apache/wicket/core/request/handler/IPartialPageRequestHandler.java index da126a290df..cb2d9b8200e 100644 --- a/wicket-core/src/main/java/org/apache/wicket/core/request/handler/IPartialPageRequestHandler.java +++ b/wicket-core/src/main/java/org/apache/wicket/core/request/handler/IPartialPageRequestHandler.java @@ -78,6 +78,15 @@ public interface IPartialPageRequestHandler extends IPageRequestHandler */ void appendJavaScript(CharSequence javascript); + /** + * Add extra meta data to partial page response. + * This is the response meta data, not HTML meta data. + * + * @param name meta datum name + * @param value meta datum value + */ + void addMeta(CharSequence name, CharSequence value); + /** * Adds javascript that will be evaluated on the client side before components are replaced. * diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/head/filter/CspNonceHeaderResponse.java b/wicket-core/src/main/java/org/apache/wicket/markup/head/filter/CspNonceHeaderResponse.java index 7a911ca6cd8..9422c9bfa3f 100644 --- a/wicket-core/src/main/java/org/apache/wicket/markup/head/filter/CspNonceHeaderResponse.java +++ b/wicket-core/src/main/java/org/apache/wicket/markup/head/filter/CspNonceHeaderResponse.java @@ -67,7 +67,7 @@ public void render(HeaderItem item) String policy = getContentSecurityPolicy(nonce); - super.render(MetaDataHeaderItem.forHttpEquiv(CONTENT_SECURITY_POLICY, policy)); + super.render(MetaDataHeaderItem.forHttpEquiv(CONTENT_SECURITY_POLICY, policy).addTagAttribute("id", "meta-csp")); } ((AbstractCspHeaderItem)item).setNonce(nonce); @@ -80,7 +80,6 @@ public void render(HeaderItem item) * Get the Content-Security-Policy (CSP). *

* There is a variety of CSP configurations, this default implementation uses the nonce for scripts and styles - * and allows unsafe-evals (needed for Wicket Ajax). * * @param nonce * the nonce @@ -88,6 +87,6 @@ public void render(HeaderItem item) */ protected String getContentSecurityPolicy(String nonce) { - return String.format("script-src 'unsafe-eval' 'nonce-%1$s'; style-src 'nonce-%1$s';", nonce); + return String.format("script-src 'nonce-%1$s'; style-src 'nonce-%1$s';", nonce); } } diff --git a/wicket-core/src/main/java/org/apache/wicket/page/PartialPageUpdate.java b/wicket-core/src/main/java/org/apache/wicket/page/PartialPageUpdate.java index 2e026bd6247..cdeba73e1bb 100644 --- a/wicket-core/src/main/java/org/apache/wicket/page/PartialPageUpdate.java +++ b/wicket-core/src/main/java/org/apache/wicket/page/PartialPageUpdate.java @@ -48,6 +48,7 @@ import org.apache.wicket.util.lang.Args; import org.apache.wicket.util.lang.Generics; import org.apache.wicket.util.string.AppendingStringBuffer; +import org.apache.wicket.util.string.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -68,6 +69,12 @@ public abstract class PartialPageUpdate { private static final Logger LOG = LoggerFactory.getLogger(PartialPageUpdate.class); + /** + * Meta data to be added to the partial page response. + * This is the response meta data, not HTML meta data. + */ + protected final List meta = Generics.newArrayList(); + /** * A list of scripts (JavaScript) which should be executed on the client side before the * components' replacement @@ -92,6 +99,7 @@ public abstract class PartialPageUpdate */ protected final Map markupIdToComponent = new LinkedHashMap(); + /** * A flag that indicates that components cannot be added anymore. * See https://issues.apache.org/jira/browse/WICKET-3564 @@ -160,6 +168,8 @@ public void writeTo(final Response response, final String encoding) onAfterRespond(response); + writeMeta(response, meta); + // queue up prepend javascripts. unlike other steps these are executed out of order so that // components can contribute them from inside their onbeforerender methods. writePriorityEvaluations(response, prependJavaScripts); @@ -205,6 +215,15 @@ protected void onAfterRespond(Response response) { */ protected abstract void writeFooter(Response response, String encoding); + /** + * + * @param response + * the response to write to + * @param meta + * the collection of prepared meta data (with tags) + */ + protected abstract void writeMeta(Response response, final Collection meta); + /** * * @param response @@ -382,6 +401,17 @@ public int hashCode() return result; } + /** + * Add meta datum to partial page update. + * This is the response meta data, not HTML meta data. + * + * @param name + * @param value + */ + public final void addMeta(CharSequence name, CharSequence value) { + meta.add(String.format("<%1$s>%2$s", Strings.escapeMarkup(name), Strings.escapeMarkup(value))); + } + /** * Adds script to the ones which are executed after the component replacement. * @@ -612,7 +642,7 @@ private static class PartialHtmlHeaderContainer extends HtmlHeaderContainer /** * Constructor. * - * @param update + * @param pageUpdate * the partial page update */ public PartialHtmlHeaderContainer(PartialPageUpdate pageUpdate) diff --git a/wicket-core/src/main/java/org/apache/wicket/page/XmlPartialPageUpdate.java b/wicket-core/src/main/java/org/apache/wicket/page/XmlPartialPageUpdate.java index 0af43424d65..79697d65f53 100644 --- a/wicket-core/src/main/java/org/apache/wicket/page/XmlPartialPageUpdate.java +++ b/wicket-core/src/main/java/org/apache/wicket/page/XmlPartialPageUpdate.java @@ -101,6 +101,16 @@ protected void writeFooter(Response response, String encoding) response.write(END_ROOT_ELEMENT); } + @Override + protected void writeMeta(final Response response, final Collection meta) { + if (meta.size() > 0) + { + response.write(""); + response.write(String.join("", meta)); + response.write(""); + } + } + @Override protected void writeHeaderContribution(Response response) { diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/head/filter/CspNoncePageExpected.html b/wicket-core/src/test/java/org/apache/wicket/markup/head/filter/CspNoncePageExpected.html index baa33bac5de..7d0994970f7 100644 --- a/wicket-core/src/test/java/org/apache/wicket/markup/head/filter/CspNoncePageExpected.html +++ b/wicket-core/src/test/java/org/apache/wicket/markup/head/filter/CspNoncePageExpected.html @@ -1,5 +1,5 @@ - + "; + private static Logger log = LoggerFactory.getLogger(AjaxServerAndClientTimeFilter.class); /** @@ -66,34 +71,62 @@ public AppendingStringBuffer filter(AppendingStringBuffer responseBuffer) int ajaxStart = responseBuffer.indexOf(""); int ajaxEnd = responseBuffer.indexOf(""); long timeTaken = System.currentTimeMillis() - RequestCycle.get().getStartTime(); - if (headIndex != -1 && bodyIndex != -1) - { - AppendingStringBuffer endScript = new AppendingStringBuffer(150); - endScript.append("\n").append(JavaScriptUtils.SCRIPT_OPEN_TAG); - endScript.append("\nwindow.defaultStatus='"); - endScript.append(getStatusString(timeTaken, "ServerAndClientTimeFilter.statustext")); - endScript.append("';\n").append(JavaScriptUtils.SCRIPT_CLOSE_TAG).append("\n"); - responseBuffer.insert(bodyIndex - 1, endScript); - responseBuffer.insert(headIndex + 6, "\n" + JavaScriptUtils.SCRIPT_OPEN_TAG + - "\nvar clientTimeVariable = new Date().getTime();\n" + - JavaScriptUtils.SCRIPT_CLOSE_TAG + "\n"); - } - else if (ajaxStart != -1 && ajaxEnd != -1) + String nonce = getNonce(); + boolean hasBody = headIndex != -1 && bodyIndex != -1; + boolean hasAjaxResponse = ajaxStart != -1 && ajaxEnd != -1; + + if (hasBody || hasAjaxResponse) { AppendingStringBuffer startScript = new AppendingStringBuffer(250); - startScript.append(""); - responseBuffer.insert(ajaxEnd, startScript.toString()); - responseBuffer.insert(ajaxStart + 15, - ""); + startScript.append(createScriptOpenTag(false, nonce)); + startScript.append(JavaScriptUtils.SCRIPT_CONTENT_PREFIX); + startScript.append("clientTimeVariable = new Date().getTime();"); + startScript.append(CDATA_SCRIPT_END); + AppendingStringBuffer endScript = new AppendingStringBuffer(300); + endScript.append(createScriptOpenTag(true, nonce)); + endScript.append(JavaScriptUtils.SCRIPT_CONTENT_PREFIX); + endScript.append("\nwindow.defaultStatus='" + getStatusString(timeTaken, "ajax.ServerAndClientTimeFilter.statustext")); + endScript.append(CDATA_SCRIPT_END); + + if (hasBody) + { + responseBuffer.insert(bodyIndex, endScript); + responseBuffer.insert(headIndex + 6, startScript); + } + else + { + AppendingStringBuffer headerContributionStartBuffer = new AppendingStringBuffer(500); + headerContributionStartBuffer.append(HEADER_CONTRIBUTION_START); + headerContributionStartBuffer.append(startScript); + headerContributionStartBuffer.append(HEADER_CONTRIBUTION_END); + AppendingStringBuffer headerContributionEndBuffer = new AppendingStringBuffer(500); + headerContributionEndBuffer.append(HEADER_CONTRIBUTION_START); + headerContributionEndBuffer.append(endScript); + headerContributionEndBuffer.append(HEADER_CONTRIBUTION_END); + responseBuffer.insert(ajaxEnd, headerContributionEndBuffer); + responseBuffer.insert(ajaxStart + 15, headerContributionStartBuffer); + } } log.info(timeTaken + "ms server time taken for request " + RequestCycle.get().getRequest().getUrl() + " response size: " + responseBuffer.length()); return responseBuffer; } + private String createScriptOpenTag(boolean isAfterDomRender, String nonce) + { + AttributeMap attrs = new AttributeMap(); + attrs.putAttribute(JavaScriptUtils.ATTR_TYPE, "text/javascript"); + if (isAfterDomRender) + { + attrs.putAttribute("data-wicket-evaluation", "after"); + } + if (nonce != null) + { + attrs.putAttribute(JavaScriptUtils.ATTR_CSP_NONCE, "nonce"); + } + return ""; + } + /** * Returns a locale specific status message about the server and client time. * @@ -111,8 +144,16 @@ private String getStatusString(long timeTaken, String resourceKey) .getString(resourceKey, null, "Server parsetime: ${servertime}, Client parsetime: ${clienttime}"); final Map map = new HashMap(4); - map.put("clienttime", "' + (new Date().getTime() - clientTimeVariable)/1000 + 's"); + map.put("clienttime", "' + (new Date().getTime() - clientTimeVariable)/1000 + 's';"); map.put("servertime", ((double)timeTaken) / 1000 + "s"); return MapVariableInterpolator.interpolate(txt, map); } + + /** + * Get CSP nonce + */ + protected String getNonce() { + return null; + } + } \ No newline at end of file diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/csp/CspApplication.java b/wicket-examples/src/main/java/org/apache/wicket/examples/csp/CspApplication.java index 213c38b47f3..b952b94fc84 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/csp/CspApplication.java +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/csp/CspApplication.java @@ -55,15 +55,6 @@ protected void init() setHeaderResponseDecorator(response -> new ResourceAggregator( isCspApplicable() ? new CspNonceHeaderResponse(response, getNonce()) : response )); - // add nonce to ajax response - getAjaxRequestTargetListeners().add((new AjaxRequestTarget.IListener() - { - @Override - public void onBeforeRespond(Map map, AjaxRequestTarget target) - { - target.addMeta("wicket-nonce", getNonce()); - } - })); mountPage("noncedemo", NonceDemoPage.class); } diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java index 5b5e6357180..641844f52cd 100644 --- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java +++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java @@ -154,12 +154,6 @@ public void appendJavaScript(CharSequence javascript) getUpdate().appendJavaScript(javascript); } - @Override - public void addMeta(CharSequence name, CharSequence value) - { - getUpdate().addMeta(name, value); - } - @Override public void prependJavaScript(CharSequence javascript) {