/*
- * Copyright 2005 The Apache Software Foundation.
+ * Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*/
-/* $Id: $ */
+/* $Id$ */
package org.apache.fop.apps;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+// base64 support for "data" urls
+import org.apache.batik.util.Base64DecodeStream;
+
/**
* Provides FOP specific URI resolution.
* This is the default URIResolver {@link FOUserAgent} will use unless overidden.
} catch (MalformedURLException mfue) {
log.error("Could not convert filename to URL: " + mfue.getMessage(), mfue);
}
+ } else if (href.startsWith("data:")) {
+ return parseDataURI(href);
} else {
URL baseURL = toBaseURL(base);
if (baseURL == null) {
}
return null;
}
-
+
+ /**
+ * Parses inline data URIs as generated by MS Word's XML export and FO stylesheet.
+ * @see <a href="http://www.ietf.org/rfc/rfc2397">RFC 2397</a>
+ */
+ private Source parseDataURI(String href) {
+ int commaPos = href.indexOf(',');
+ // header is of the form data:[<mediatype>][;base64]
+ String header = href.substring(0, commaPos);
+ String data = href.substring(commaPos + 1);
+ if (header.endsWith(";base64")) {
+ byte[] bytes = data.getBytes();
+ ByteArrayInputStream encodedStream = new ByteArrayInputStream(bytes);
+ Base64DecodeStream decodedStream = new Base64DecodeStream(encodedStream);
+ return new StreamSource(decodedStream);
+ } else {
+ //Note that this is not quite the full story here. But since we are only interested
+ //in base64-encoded binary data, the next line will probably never be called.
+ return new StreamSource(new java.io.StringReader(data));
+ }
+ }
}
<changes>
<release version="FOP Trunk">
+ <action context="Code" dev="JM" type="add" fixes-bug="38132" due-to="Richard Wheeldon">
+ Added support for RFC2397 "data" URLs.
+ </action>
<action context="Code" dev="JM" type="fix" fixes-bug="38132">
Bugfix: Certain border styles could lead to a NullPointerException.
</action>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2006 The Apache Software Foundation
+
+ Licensed 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.
+-->
+<!-- $Id$ -->
+<testcase>
+ <info>
+ <p>
+ This test checks external-graphics with RFC2397 "data" URLs.
+ </p>
+ </info>
+ <fo>
+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="normal" page-width="8in" page-height="8in">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="normal">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block>Image referenced by RFC 2397 "data" URL:</fo:block>
+ <fo:block>
+ <fo:external-graphic src="url("data:image/gif;base64, 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
")"/>EOG
+ </fo:block>
+ <fo:block>EOF</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+ </fo:root>
+ </fo>
+ <checks>
+ <eval expected="537000" xpath="//flow/block[2]/lineArea/viewport/@ipd"/>
+ <eval expected="537000" xpath="//flow/block[2]/lineArea/viewport/@ipda"/>
+ <eval expected="51000" xpath="//flow/block[2]/lineArea/viewport/@bpd"/>
+ <eval expected="51000" xpath="//flow/block[2]/lineArea/viewport/@bpda"/>
+ </checks>
+</testcase>