This is an automated email from the ASF dual-hosted git repository. jeb pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git
commit e676fe64ca90e1db52691c6baed2a7ec25e2d340 Author: JE Bailey <[email protected]> AuthorDate: Tue Aug 27 14:37:27 2019 -0400 incorporating buffer between the transformation layer --- transformer/README.md | 4 +- .../sling/transformer/TransformationContext.java | 20 +---- .../sling/transformer/TransformationStep.java | 3 + .../sling/transformer/impl/LinkTransformer.java | 95 ---------------------- .../sling/transformer/impl/NonceTransformer.java | 52 ++++++++++++ .../impl/TransformationContextImpl.java | 12 +-- .../transformer/impl/TransformationFilter.java | 3 + .../transformer/impl/TransformationResponse.java | 6 +- .../transformer/impl/TransformationWriter.java | 40 +++++++-- 9 files changed, 106 insertions(+), 129 deletions(-) diff --git a/transformer/README.md b/transformer/README.md index 40e71e8..c4ba357 100644 --- a/transformer/README.md +++ b/transformer/README.md @@ -2,8 +2,6 @@ [](https://builds.apache.org/job/Sling/job/sling-org-apache-sling-rewriter/job/master) [](https://builds.apache.org/job/Sling/job/sling-org-apache-sling-rewriter/job/master/test_results_analyzer/) [ project. - -[More details](http://sling.apache.org/documentation/bundles/output-rewriting-pipelines-org-apache-sling-rewriter.html) diff --git a/transformer/src/main/java/org/apache/sling/transformer/TransformationContext.java b/transformer/src/main/java/org/apache/sling/transformer/TransformationContext.java index fb355f4..245517d 100644 --- a/transformer/src/main/java/org/apache/sling/transformer/TransformationContext.java +++ b/transformer/src/main/java/org/apache/sling/transformer/TransformationContext.java @@ -17,8 +17,8 @@ package org.apache.sling.transformer; import java.io.IOException; -import java.io.OutputStream; import java.io.PrintWriter; +import java.util.List; import java.util.Map; import java.util.stream.Stream; @@ -31,29 +31,17 @@ import org.apache.sling.commons.html.HtmlElement; */ public interface TransformationContext { - /** - * The current request. - */ SlingHttpServletRequest getRequest(); - /** - * The current response. - */ SlingHttpServletResponse getResponse(); - /** - * The writer. - */ PrintWriter getWriter() throws IOException; - /** - * The output stream. - */ - OutputStream getOutputStream() throws IOException; - - Map<String, Object> getStateMap(); + Map<String, Object> getState(); void next(HtmlElement... elements); Stream<HtmlElement> getElements(); + + List<TransformationStep> getSteps(); } diff --git a/transformer/src/main/java/org/apache/sling/transformer/TransformationStep.java b/transformer/src/main/java/org/apache/sling/transformer/TransformationStep.java index ed1c134..d343ba5 100644 --- a/transformer/src/main/java/org/apache/sling/transformer/TransformationStep.java +++ b/transformer/src/main/java/org/apache/sling/transformer/TransformationStep.java @@ -20,6 +20,9 @@ import org.apache.sling.commons.html.HtmlElement; public interface TransformationStep { + default void init(TransformationContext context) { + } + public void handle(HtmlElement element, TransformationContext context); } diff --git a/transformer/src/main/java/org/apache/sling/transformer/impl/LinkTransformer.java b/transformer/src/main/java/org/apache/sling/transformer/impl/LinkTransformer.java deleted file mode 100644 index d193d62..0000000 --- a/transformer/src/main/java/org/apache/sling/transformer/impl/LinkTransformer.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.sling.transformer.impl; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Base64; -import java.util.Map; - -import org.apache.sling.commons.html.HtmlElement; -import org.apache.sling.commons.html.HtmlElementType; -import org.apache.sling.commons.html.util.ElementFactory; -import org.apache.sling.transformer.TransformationContext; -import org.apache.sling.transformer.TransformationStep; -import org.osgi.service.component.annotations.Component; - -@Component(property = { "extension=html", "path=/content/*", "type=REQUEST" }) -public class LinkTransformer implements TransformationStep { - - private enum State { - IN, OUT - } - - public void handle(HtmlElement element, TransformationContext process) { - - Map<String, Object> context = process.getStateMap(); - State current = (State) context.getOrDefault("currentState", State.OUT); - - MessageDigest d = (MessageDigest) context.computeIfAbsent("hash", (value) -> { - MessageDigest digest = null; - try { - digest = MessageDigest.getInstance("SHA-256"); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } - return digest; - }); - - switch (current) { - case IN: - switch (element.getType()) { - case END_TAG: - context.put("currentState", State.OUT); - break; - case TEXT: - d.update(element.getValue().getBytes()); - break; - default: - break; - } - break; - case OUT: - switch (element.getType()) { - case START_TAG: - String tag = element.getValue(); - if (tag.equals("script") || tag.equals("style")) { - context.put("currentState", State.IN); - } - break; - case END_TAG: - if (element.getValue().equalsIgnoreCase("body")) { - String headerValue = Base64.getEncoder().encodeToString(d.digest()); - process.getResponse().setHeader("Sucks", headerValue); - HtmlElement br = ElementFactory.create(HtmlElementType.START_TAG, "br"); - br.setAttribute("data-hash",headerValue ); - process.next(br); - } - break; - default: - break; - } - break; - default: - break; - - } - - process.next(element); - } - -} diff --git a/transformer/src/main/java/org/apache/sling/transformer/impl/NonceTransformer.java b/transformer/src/main/java/org/apache/sling/transformer/impl/NonceTransformer.java new file mode 100644 index 0000000..b5be4d1 --- /dev/null +++ b/transformer/src/main/java/org/apache/sling/transformer/impl/NonceTransformer.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sling.transformer.impl; + +import java.util.Map; +import java.util.UUID; + +import org.apache.sling.commons.html.HtmlElement; +import org.apache.sling.commons.html.HtmlElementType; +import org.apache.sling.transformer.TransformationContext; +import org.apache.sling.transformer.TransformationStep; +import org.osgi.service.component.annotations.Component; + +@Component(property = { "extension=html", "path=/content/*", "type=REQUEST" }) +public class NonceTransformer implements TransformationStep { + + @Override + public void init(TransformationContext context) { + String nonce = UUID.randomUUID().toString().replace("-", ""); + context.getState().put("nonce", nonce); + context.getResponse().setHeader("X-nonce", nonce); + } + + public void handle(HtmlElement element, TransformationContext context) { + + Map<String, Object> state = context.getState(); + String nonce = (String)state.get("nonce"); + + if (element.getType()== HtmlElementType.START_TAG) { + if (element.getValue().equals("script")) { + element.setAttribute("nonce", nonce); + } + } + + context.next(element); + } + +} diff --git a/transformer/src/main/java/org/apache/sling/transformer/impl/TransformationContextImpl.java b/transformer/src/main/java/org/apache/sling/transformer/impl/TransformationContextImpl.java index b62d343..601348b 100644 --- a/transformer/src/main/java/org/apache/sling/transformer/impl/TransformationContextImpl.java +++ b/transformer/src/main/java/org/apache/sling/transformer/impl/TransformationContextImpl.java @@ -14,7 +14,6 @@ package org.apache.sling.transformer.impl; import java.io.IOException; -import java.io.OutputStream; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; @@ -50,7 +49,8 @@ public class TransformationContextImpl implements TransformationContext { private boolean reset; private List<TransformationStep> steps; - public TransformationContextImpl(SlingHttpServletRequest request, SlingHttpServletResponse response, List<TransformationStep> steps) { + public TransformationContextImpl(SlingHttpServletRequest request, SlingHttpServletResponse response, + List<TransformationStep> steps) { this.request = request; this.response = response; this.steps = steps; @@ -82,7 +82,7 @@ public class TransformationContextImpl implements TransformationContext { return list.stream(); } - public Map<String, Object> getStateMap() { + public Map<String, Object> getState() { return context; } @@ -95,13 +95,13 @@ public class TransformationContextImpl implements TransformationContext { } @Override - public PrintWriter getWriter() throws IOException { + public PrintWriter getWriter() throws IOException { return response.getWriter(); } @Override - public OutputStream getOutputStream() throws IOException { - return response.getOutputStream(); + public List<TransformationStep> getSteps() { + return steps; } } diff --git a/transformer/src/main/java/org/apache/sling/transformer/impl/TransformationFilter.java b/transformer/src/main/java/org/apache/sling/transformer/impl/TransformationFilter.java index 1787500..0f21d19 100644 --- a/transformer/src/main/java/org/apache/sling/transformer/impl/TransformationFilter.java +++ b/transformer/src/main/java/org/apache/sling/transformer/impl/TransformationFilter.java @@ -80,6 +80,9 @@ public class TransformationFilter implements Filter { if (slingRequest.getRequestURI().endsWith(".html")){ TransformationContext context = new TransformationContextImpl(slingRequest, slingResponse, steps); + steps.forEach(transformer -> + transformer.init(context) + ); response = new TransformationResponse(context); } diff --git a/transformer/src/main/java/org/apache/sling/transformer/impl/TransformationResponse.java b/transformer/src/main/java/org/apache/sling/transformer/impl/TransformationResponse.java index 62b70d5..820bbe1 100644 --- a/transformer/src/main/java/org/apache/sling/transformer/impl/TransformationResponse.java +++ b/transformer/src/main/java/org/apache/sling/transformer/impl/TransformationResponse.java @@ -29,12 +29,12 @@ class TransformationResponse private PrintWriter writer; - private TransformationContext process; + private TransformationContext context; public TransformationResponse(TransformationContext context) { super(context.getResponse()); - this.process = context; + this.context = context; } /** @@ -44,7 +44,7 @@ class TransformationResponse */ public PrintWriter getWriter() throws IOException { if ( this.writer == null ) { - this.writer = new PrintWriter(new TransformationWriter(process)); + this.writer = new PrintWriter(new TransformationWriter(context)); } return writer; } diff --git a/transformer/src/main/java/org/apache/sling/transformer/impl/TransformationWriter.java b/transformer/src/main/java/org/apache/sling/transformer/impl/TransformationWriter.java index 5510b64..ce3a271 100644 --- a/transformer/src/main/java/org/apache/sling/transformer/impl/TransformationWriter.java +++ b/transformer/src/main/java/org/apache/sling/transformer/impl/TransformationWriter.java @@ -18,11 +18,15 @@ package org.apache.sling.transformer.impl; import java.io.IOException; import java.io.Writer; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.util.List; import java.util.stream.Collectors; import org.apache.sling.commons.html.Html; import org.apache.sling.commons.html.util.HtmlElements; import org.apache.sling.transformer.TransformationContext; +import org.apache.sling.transformer.TransformationStep; public class TransformationWriter extends Writer { @@ -30,22 +34,46 @@ public class TransformationWriter extends Writer { private TransformationStepWrapper wrapper; + private CharBuffer buffer; + + private List<TransformationStep> steps; + public TransformationWriter(TransformationContext context) throws IOException { + super(); this.originalWriter = context.getWriter(); - this.wrapper = new TransformationStepWrapper(new LinkTransformer(), context); + this.wrapper = new TransformationStepWrapper(new NonceTransformer(), context); + this.buffer = ByteBuffer.allocate(1024).asCharBuffer(); + this.steps = context.getSteps(); + + } @Override public void write(char[] cbuf, int off, int len) throws IOException { - String foo = Html.stream(String.valueOf(cbuf, off, len)) - .flatMap(wrapper) - .map(HtmlElements.TO_HTML) - .collect(Collectors.joining()); - originalWriter.write(foo.toCharArray(), 0, foo.toCharArray().length); + if (len + buffer.position() > buffer.limit()) { + flushLocal(); + } + if (len < buffer.limit()) { + buffer.put(cbuf, off, len); + } else { + writeLocal(String.valueOf(cbuf, off, len)); + } + } + + private void flushLocal() throws IOException { + buffer.flip(); + writeLocal(buffer.toString()); + buffer.clear(); + } + + private void writeLocal(String string) throws IOException { + String cache = Html.stream(string).flatMap(wrapper).map(HtmlElements.TO_HTML).collect(Collectors.joining()); + originalWriter.write(cache.toCharArray(), 0, cache.toCharArray().length); } @Override public void flush() throws IOException { + flushLocal(); originalWriter.flush(); }
