package org.archive.wayback.archivalurl; import java.io.ByteArrayOutputStream; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.archive.wayback.ResultURIConverter; import org.archive.wayback.core.CaptureSearchResult; import org.archive.wayback.core.CaptureSearchResults; import org.archive.wayback.core.Resource; import org.archive.wayback.core.UIResults; import org.archive.wayback.core.WaybackRequest; import org.archive.wayback.replay.HttpHeaderProcessor; import org.archive.wayback.replay.JSPExecutor; import org.archive.wayback.replay.TextDocument; import org.archive.wayback.replay.TextReplayRenderer; import org.archive.wayback.replay.html.ContextResultURIConverterFactory; import org.archive.wayback.replay.html.IdentityResultURIConverterFactory; import org.archive.wayback.replay.html.ReplayParseContext; import org.archive.wayback.replay.html.StringTransformer; import org.archive.wayback.webapp.AccessPoint; /** * {@link TextReplayRenderer} that uses {@link StringTransformer} as an underlining * rewrite engine. * <p><code>transformer</code> can be any <code>StringTransformer</code> such as * <code>JSStringTransformer</code> or <code>MultiRegexReplaceStringTransformer</code>.</p> * <p>This class itself is not specific to either JavaScript rewriting or archival-URL mode. * It is all up to <code>transformer</code> how URLs in resource is rewritten. * As such, this class is also used for rewriting {@code https://} URLs in proxy-mode * in spite of its name. * </p> * <p>TODO: * @see org.archive.wayback.replay.html.transformer.JSStringTransformer * @see org.archive.wayback.replay.html.transformer.MultiRegexReplaceStringTransformer * @author ilya * */ public class ArchivalURLJSStringTransformerReplayRenderer extends TextReplayRenderer { public ArchivalURLJSStringTransformerReplayRenderer(HttpHeaderProcessor httpHeaderProcessor) { super(httpHeaderProcessor); } private StringTransformer transformer; private ContextResultURIConverterFactory converterFactory = null; private boolean rewriteHttpsOnly; public StringTransformer getTransformer() { return transformer; } public void setTransformer(StringTransformer transformer) { this.transformer = transformer; } public boolean isRewriteHttpsOnly() { return rewriteHttpsOnly; } public void setRewriteHttpsOnly(boolean rewriteHttpsOnly) { this.rewriteHttpsOnly = rewriteHttpsOnly; } @Override protected void updatePage(TextDocument page, HttpServletRequest httpRequest, HttpServletResponse httpResponse, WaybackRequest wbRequest, CaptureSearchResult result, Resource resource, ResultURIConverter uriConverter, CaptureSearchResults results) throws ServletException, IOException { // same code in ArchivalUrlSAXRewriteReplayRenderer ContextResultURIConverterFactory fact = null; if (uriConverter instanceof ArchivalUrlResultURIConverter) { fact = new ArchivalUrlContextResultURIConverterFactory( (ArchivalUrlResultURIConverter) uriConverter); } else if (converterFactory != null) { fact = converterFactory; } else { fact = new IdentityResultURIConverterFactory(uriConverter); } // set up the context: ReplayParseContext context = new ReplayParseContext(fact, result); context.setRewriteHttpsOnly(rewriteHttpsOnly); UIResults uiResults = new UIResults(wbRequest, uriConverter, results, result, resource); JSPExecutor jspExec = new JSPExecutor(httpRequest, httpResponse, uiResults); // To make sure we get the length, we have to buffer it all up... ByteArrayOutputStream baos = new ByteArrayOutputStream(); context.setOutputCharset("utf-8"); context.setOutputStream(baos); context.setJspExec(jspExec); context.setInJS(true); //for https://webarchive.jira.com/browse/ARI-3762 // XXX same code in ArchivalUrlSAXReplayRenderer, and probably other // custom Archival-URL ReplayRenderers needs this, too. // We should move this code somewhere reusable (ReplayParseContext? - // which would push us to define new interface for rewriting). String policy = result.getOraclePolicy(); if (policy == null) { AccessPoint accessPoint = wbRequest.getAccessPoint(); if (accessPoint != null) { policy = accessPoint.getRewriteDirective(result); } } if (policy != null) { context.setOraclePolicy(policy); } //RewriteReplayParseEventHandler.addRewriteParseContext(context); String replaced = transformer.transform(context, page.sb.toString()); page.sb.setLength(0); page.sb.ensureCapacity(replaced.length()); page.sb.append(replaced); // if any JS-specific jsp inserts are configured, run and insert... page.insertAtStartOfDocument(buildInsertText(page, httpRequest, httpResponse, wbRequest, results, result, resource)); } public ContextResultURIConverterFactory getConverterFactory() { return converterFactory; } public void setConverterFactory( ContextResultURIConverterFactory converterFactory) { this.converterFactory = converterFactory; } }