From: <bra...@us...> - 2010-10-21 17:34:47
|
Revision: 3290 http://archive-access.svn.sourceforge.net/archive-access/?rev=3290&view=rev Author: bradtofel Date: 2010-10-21 17:34:40 +0000 (Thu, 21 Oct 2010) Log Message: ----------- INITIAL REV: very early but somewhat functional SWF URL rewriting. Added Paths: ----------- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/replay/swf/ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/replay/swf/RobustMovieDecoder.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/replay/swf/SWFReplayRenderer.java Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/replay/swf/RobustMovieDecoder.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/replay/swf/RobustMovieDecoder.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/replay/swf/RobustMovieDecoder.java 2010-10-21 17:34:40 UTC (rev 3290) @@ -0,0 +1,88 @@ +/* + * This file is part of the Wayback archival access software + * (http://archive-access.sourceforge.net/projects/wayback/). + * + * Licensed to the Internet Archive (IA) by one or more individual + * contributors. + * + * The IA 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.archive.wayback.replay.swf; + +import java.io.IOException; +import java.util.List; + +import com.flagstone.transform.MovieTag; +import com.flagstone.transform.coder.CoderException; +import com.flagstone.transform.coder.Context; +import com.flagstone.transform.coder.SWFDecoder; +import com.flagstone.transform.coder.SWFFactory; + +/** + * @author brad + * + */ +public class RobustMovieDecoder implements SWFFactory<MovieTag> { + private SWFFactory<MovieTag> delegate = null; + private int decodeRule = DECODE_RULE_STRICT; + + /** Decoding robustness/sloppiness factor. */ + public static final int DECODE_RULE = 19; + /** Allow no unparsed data - very strict decoding. */ + public static final int DECODE_RULE_STRICT = 0; + /** Allow trailing NULL values in decoded tags. */ + public static final int DECODE_RULE_NULLS = 1; + /** Allow arbitrary trailing values in decoded tags - attempt anything. */ + public static final int DECODE_RULE_LAX = 2; + + public void setDecodeRule(int decodeRule) { + this.decodeRule = decodeRule; + } + + public void setDelegate(SWFFactory<MovieTag> delegate) { + this.delegate = delegate; + } + + public void getObject(List<MovieTag> list, SWFDecoder coder, Context context) + throws IOException { + try { + delegate.getObject(list, coder, context); + } catch(CoderException e) { + int delta = coder.getDelta(); + switch (decodeRule) { + case DECODE_RULE_LAX: + // just eat the next 'delta' bytes and hope for the best.. + while(delta-- > 0) { + coder.readByte(); + } + break; + case DECODE_RULE_NULLS: + // make sure next 'delta' bytes are null: + while(delta-- > 0) { + if(coder.readByte() != 0) { + throw new CoderException(coder.getLocation(), + coder.getExpected(), coder.getDelta()); + } + } + break; + case DECODE_RULE_STRICT: + default: + throw new CoderException(coder.getLocation(), + coder.getExpected(), coder.getDelta()); + } + + } + + } + +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/replay/swf/RobustMovieDecoder.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/replay/swf/SWFReplayRenderer.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/replay/swf/SWFReplayRenderer.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/replay/swf/SWFReplayRenderer.java 2010-10-21 17:34:40 UTC (rev 3290) @@ -0,0 +1,247 @@ +/* + * This file is part of the Wayback archival access software + * (http://archive-access.sourceforge.net/projects/wayback/). + * + * Licensed to the Internet Archive (IA) by one or more individual + * contributors. + * + * The IA 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.archive.wayback.replay.swf; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.zip.DataFormatException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.httpclient.URIException; +import org.archive.net.UURI; +import org.archive.net.UURIFactory; +import org.archive.wayback.ReplayRenderer; +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.WaybackRequest; +import org.archive.wayback.exception.BadContentException; +import org.archive.wayback.exception.WaybackException; +import org.archive.wayback.replay.HttpHeaderOperation; +import org.archive.wayback.replay.HttpHeaderProcessor; + +import com.flagstone.transform.DoAction; +import com.flagstone.transform.EventHandler; +import com.flagstone.transform.Movie; +import com.flagstone.transform.MovieTag; +import com.flagstone.transform.action.Action; +import com.flagstone.transform.action.GetUrl; +import com.flagstone.transform.action.Push; +import com.flagstone.transform.action.Table; +import com.flagstone.transform.button.DefineButton2; +import com.flagstone.transform.coder.DecoderRegistry; + +/** + * @author brad + * + */ +public class SWFReplayRenderer implements ReplayRenderer { + private HttpHeaderProcessor httpHeaderProcessor; + public SWFReplayRenderer(HttpHeaderProcessor httpHeaderProcessor) { + this.httpHeaderProcessor = httpHeaderProcessor; + } + + public void renderResource(HttpServletRequest httpRequest, + HttpServletResponse httpResponse, WaybackRequest wbRequest, + CaptureSearchResult result, Resource resource, + ResultURIConverter uriConverter, CaptureSearchResults results) + throws ServletException, IOException, WaybackException { + + // copy HTTP response code: + HttpHeaderOperation.copyHTTPMessageHeader(resource, httpResponse); + + // load and process original headers: + Map<String,String> headers = HttpHeaderOperation.processHeaders( + resource, result, uriConverter, httpHeaderProcessor); + + // The URL of the resource, for resolving embedded relative URLs: + URL url = null; + try { + url = new URL(result.getOriginalUrl()); + } catch (MalformedURLException e1) { + e1.printStackTrace(); + throw new IOException(e1.getMessage()); + } + // the date to associate with the embedded, rewritten URLs: + String datespec = result.getCaptureTimestamp(); + SWFUrlRewriter rw = new SWFUrlRewriter(uriConverter, url, datespec); + + + // OK, try to read the input movie: + Movie movie = getRobustMovie(RobustMovieDecoder.DECODE_RULE_NULLS); + + try { + movie.decodeFromStream(resource); + } catch (DataFormatException e1) { + throw new BadContentException(e1.getLocalizedMessage()); + } + Movie outMovie = new Movie(movie); + + List<MovieTag> inTags = movie.getObjects(); + ArrayList<MovieTag> outTags = new ArrayList<MovieTag>(); + for(MovieTag tag : inTags) { + outTags.add(rewriteTag(rw,tag)); + } + outMovie.setObjects(outTags); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + outMovie.encodeToStream(baos); + } catch (DataFormatException e) { + throw new BadContentException(e.getLocalizedMessage()); + } + + // put the new corrected length: + headers.put(HttpHeaderOperation.HTTP_LENGTH_HEADER, + String.valueOf(baos.size())); + + // send the new headers: + HttpHeaderOperation.sendHeaders(headers, httpResponse); + + // and copy the stored up byte-stream: + baos.writeTo(httpResponse.getOutputStream()); + + } + public Movie getRobustMovie(int decodeRule) { + Movie movie = new Movie(); + + DecoderRegistry registry = DecoderRegistry.getDefault(); + RobustMovieDecoder decoder = new RobustMovieDecoder(); + decoder.setDelegate(registry.getMovieDecoder()); + decoder.setDecodeRule(decodeRule); + registry.setMovieDecoder(decoder); + movie.setRegistry(registry); + + return movie; + } + + public MovieTag rewriteTag(SWFUrlRewriter rw, MovieTag tag) { + if(tag instanceof DoAction) { + DoAction doAction = (DoAction) tag; + doAction.setActions(rewriteActions(rw, doAction.getActions())); + } else if(tag instanceof DefineButton2) { + + DefineButton2 defButton2 = (DefineButton2) tag; + defButton2.setEvents(rewriteEventHandlers(rw, defButton2.getEvents())); + } + return tag; + } + + public List<EventHandler> rewriteEventHandlers(SWFUrlRewriter rw, List<EventHandler> handlers) { + ArrayList<EventHandler> newActions = new ArrayList<EventHandler>(); + for(EventHandler handler : handlers) { + handler.setActions(rewriteActions(rw, handler.getActions())); + newActions.add(handler); + } + return newActions; + } + + public List<Action> rewriteActions(SWFUrlRewriter rw, List<Action> actions) { + ArrayList<Action> newActions = new ArrayList<Action>(); + for(Action action : actions) { + if(action instanceof Table) { + + Table table = (Table) action; + table.setValues(rewriteStringValues(rw, table.getValues())); + newActions.add(table); + + } else if(action instanceof Push) { + + Push push = (Push) action; + + newActions.add(new Push(rewriteObjectValues(rw, push.getValues()))); + + } else if(action instanceof GetUrl) { + + GetUrl getUrl = (GetUrl) action; + newActions.add(new GetUrl(rewriteString(rw, getUrl.getUrl()),getUrl.getTarget())); + + } else { + newActions.add(action); + } + } + return newActions; + } + + public List<Object> rewriteObjectValues(SWFUrlRewriter rw, List<Object> values) { + ArrayList<Object> nvals = new ArrayList<Object>(); + for(int i = 0; i < values.size(); i++) { + Object orig = values.get(i); + if(orig instanceof String) { + nvals.add(rewriteString(rw, (String)orig)); + } else { + nvals.add(orig); + } + } + return nvals; + } + public List<String> rewriteStringValues(SWFUrlRewriter rw, List<String> values) { + ArrayList<String> nvals = new ArrayList<String>(); + for(int i = 0; i < values.size(); i++) { + nvals.add(rewriteString(rw, values.get(i))); + } + return nvals; + } + public String rewriteString(SWFUrlRewriter rw, String original) { + if(original.startsWith("http://")) { +// System.err.format("Rewrite(%s)\n",original); + return rw.rewrite(original); + } + return original; + } + private class SWFUrlRewriter { + UURI baseUrl = null; + ResultURIConverter converter; + String datespec; + public SWFUrlRewriter(ResultURIConverter converter, URL baseUrl, + String datespec) { + this.datespec = datespec; + this.converter = converter; + try { + this.baseUrl = UURIFactory.getInstance(baseUrl.toExternalForm()); + } catch (URIException e) { + e.printStackTrace(); + } + + + } + public String rewrite(String url) { + try { + String resolved = url; + if(baseUrl != null) { + resolved = UURIFactory.getInstance(baseUrl, url).toString(); + } + return converter.makeReplayURI(datespec, resolved); + } catch (URIException e) { + e.printStackTrace(); + } + return url; + } + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/replay/swf/SWFReplayRenderer.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |