aboutsummaryrefslogtreecommitdiffstats
path: root/fop-core/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'fop-core/src/main')
-rw-r--r--fop-core/src/main/java/org/apache/fop/pdf/PDFFactory.java146
-rw-r--r--fop-core/src/main/java/org/apache/fop/pdf/PDFFileSpec.java2
-rw-r--r--fop-core/src/main/java/org/apache/fop/pdf/PDFLaunch.java16
3 files changed, 128 insertions, 36 deletions
diff --git a/fop-core/src/main/java/org/apache/fop/pdf/PDFFactory.java b/fop-core/src/main/java/org/apache/fop/pdf/PDFFactory.java
index 09debe179..4e9a58cdf 100644
--- a/fop-core/src/main/java/org/apache/fop/pdf/PDFFactory.java
+++ b/fop-core/src/main/java/org/apache/fop/pdf/PDFFactory.java
@@ -25,6 +25,8 @@ import java.awt.geom.Rectangle2D;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.BitSet;
@@ -548,8 +550,6 @@ public class PDFFactory {
return link;
}
- private static final String EMBEDDED_FILE = "embedded-file:";
-
/**
* Create/find and return the appropriate external PDFAction according to the target
*
@@ -560,39 +560,113 @@ public class PDFFactory {
* @return the PDFAction thus created or found
*/
public PDFAction getExternalAction(String target, boolean newWindow) {
+ URI uri = getTargetUri(target);
+ if (uri != null) {
+ String scheme = uri.getScheme();
+ String filename = uri.getPath();
+ if (filename == null) {
+ filename = uri.getSchemeSpecificPart();
+ }
+ if (scheme == null) {
+ return new PDFUri(uri.toASCIIString());
+ } else if (scheme.equalsIgnoreCase("embedded-file")) {
+ return getActionForEmbeddedFile(filename, newWindow);
+ } else if (scheme.equalsIgnoreCase("file")) {
+ if (filename.startsWith("//")) {
+ filename = filename.replace("/", "\\");
+ } else if (filename.matches("^/[A-z]:/.*")) {
+ filename = filename.substring(1);
+ }
+ if (filename.toLowerCase().endsWith(".pdf")) {
+ int page = -1;
+ String dest = null;
+ String fragment = uri.getFragment();
+ if (fragment != null) {
+ String fragmentLo = fragment.toLowerCase();
+ if (fragmentLo.startsWith("page=")) {
+ page = Integer.parseInt(fragmentLo.substring(5));
+ } else if (fragmentLo.startsWith("dest=")) {
+ dest = fragment.substring(5);
+ }
+ }
+ return getGoToPDFAction(filename, dest, page, newWindow);
+ } else {
+ if (uri.getQuery() != null || uri.getFragment() != null) {
+ return new PDFUri(uri.toASCIIString());
+ } else {
+ return getLaunchAction(filename, newWindow);
+ }
+ }
+ } else {
+ return new PDFUri(uri.toASCIIString());
+ }
+ }
+ return new PDFUri(target);
+ }
+
+ private URI getTargetUri(String target) {
+ URI uri;
+ try {
+ uri = new URI(target);
+ String scheme = uri.getScheme();
+ String schemeSpecificPart = uri.getSchemeSpecificPart();
+ String authority = uri.getAuthority();
+ if (scheme == null && schemeSpecificPart.matches("//.*")) {
+ uri = getFileUri(target);
+ } else if ((scheme == null) && schemeSpecificPart.matches("/.*")) {
+ uri = getFileUri(target);
+ } else if (scheme != null && scheme.matches("[A-z]")) {
+ uri = getFileUri(target);
+ } else if (scheme != null && scheme.equalsIgnoreCase("file") && authority != null) {
+ uri = getFileUri(target);
+ }
+ } catch (URISyntaxException e) {
+ uri = getFileUri(target);
+ }
+ return uri;
+ }
+
+ private URI getFileUri(String target) {
+ URI uri;
+ String scheme = null;
+ String fragment = null;
+ String filename = target;
int index;
String targetLo = target.toLowerCase();
- if (target.startsWith(EMBEDDED_FILE)) {
- // File Attachments (Embedded Files)
- String filename = target.substring(EMBEDDED_FILE.length());
- return getActionForEmbeddedFile(filename, newWindow);
- } else if (targetLo.startsWith("http://")) {
- // HTTP URL?
- return new PDFUri(target);
- } else if (targetLo.startsWith("https://")) {
- // HTTPS URL?
- return new PDFUri(target);
- } else if (targetLo.startsWith("file://")) {
- // Non PDF files. Try to /Launch them.
- target = target.substring("file://".length());
- return getLaunchAction(target);
- } else if (targetLo.endsWith(".pdf")) {
- // Bare PDF file name?
- return getGoToPDFAction(target, null, -1, newWindow);
- } else if ((index = targetLo.indexOf(".pdf#page=")) > 0) {
- // PDF file + page?
- String filename = target.substring(0, index + 4);
- int page = Integer.parseInt(target.substring(index + 10));
- return getGoToPDFAction(filename, null, page, newWindow);
- } else if ((index = targetLo.indexOf(".pdf#dest=")) > 0) {
- // PDF file + destination?
- String filename = target.substring(0, index + 4);
- String dest = target.substring(index + 10);
- return getGoToPDFAction(filename, dest, -1, newWindow);
- } else {
- // None of the above? Default to URI:
- return new PDFUri(target);
+ if (((index = targetLo.indexOf(".pdf#page=")) > 0)
+ || ((index = targetLo.indexOf(".pdf#dest=")) > 0)) {
+ filename = target.substring(0, index + 4);
+ fragment = target.substring(index + 5);
+ }
+
+ if (targetLo.startsWith("file://")) {
+ scheme = "file";
+ filename = filename.substring("file://".length());
+ } else if (targetLo.startsWith("embedded-file:")) {
+ scheme = "embedded-file";
+ filename = filename.substring("embedded-file:".length());
+ } else if (targetLo.startsWith("file:")) {
+ scheme = "file";
+ filename = filename.substring("file:".length());
+ }
+
+ try {
+ filename = filename.replace("\\", "/");
+ if (filename.matches("[A-z]:.*")) {
+ scheme = (scheme == null) ? "file" : scheme;
+ filename = "/" + filename;
+ } else if (filename.matches("//.*")) {
+ scheme = (scheme == null) ? "file" : scheme;
+ filename = "//" + filename;
+ } else if (filename.matches("/.*")) {
+ scheme = (scheme == null) ? "file" : scheme;
+ }
+ uri = new URI(scheme, filename, fragment);
+ } catch (URISyntaxException e) {
+ throw new IllegalStateException(e);
}
+
+ return uri;
}
private PDFAction getActionForEmbeddedFile(String filename, boolean newWindow) {
@@ -723,13 +797,15 @@ public class PDFFactory {
/**
* Creates and returns a launch pdf document action using
- * <code>file</code> to create a file spcifiaciton for
+ * <code>file</code> to create a file specification for
* the document/file to be opened with an external application.
*
* @param file the pdf file name
+ * @param newWindow boolean indicating whether the target should be
+ * displayed in a new window
* @return the pdf launch object
*/
- private PDFLaunch getLaunchAction(String file) {
+ private PDFLaunch getLaunchAction(String file, boolean newWindow) {
getDocument().getProfile().verifyActionAllowed();
PDFFileSpec fileSpec = new PDFFileSpec(file);
@@ -740,7 +816,7 @@ public class PDFFactory {
} else {
fileSpec = oldSpec;
}
- PDFLaunch launch = new PDFLaunch(fileSpec);
+ PDFLaunch launch = new PDFLaunch(fileSpec, newWindow);
PDFLaunch oldLaunch = getDocument().findLaunch(launch);
if (oldLaunch == null) {
diff --git a/fop-core/src/main/java/org/apache/fop/pdf/PDFFileSpec.java b/fop-core/src/main/java/org/apache/fop/pdf/PDFFileSpec.java
index b9a46c8b8..f9f990c95 100644
--- a/fop-core/src/main/java/org/apache/fop/pdf/PDFFileSpec.java
+++ b/fop-core/src/main/java/org/apache/fop/pdf/PDFFileSpec.java
@@ -35,6 +35,7 @@ public class PDFFileSpec extends PDFDictionary {
super();
put("Type", new PDFName("Filespec"));
put("F", filename);
+ put("UF", filename); // for non-ascii filenames, since PDF 1.7, 3.10.2
}
private String getFilename() {
@@ -77,4 +78,3 @@ public class PDFFileSpec extends PDFDictionary {
return true;
}
}
-
diff --git a/fop-core/src/main/java/org/apache/fop/pdf/PDFLaunch.java b/fop-core/src/main/java/org/apache/fop/pdf/PDFLaunch.java
index 7d80ddb43..935eb11a9 100644
--- a/fop-core/src/main/java/org/apache/fop/pdf/PDFLaunch.java
+++ b/fop-core/src/main/java/org/apache/fop/pdf/PDFLaunch.java
@@ -25,6 +25,7 @@ package org.apache.fop.pdf;
public class PDFLaunch extends PDFAction {
private PDFReference externalFileSpec;
+ private boolean newWindow;
/**
* Creates a new /Launch action.
@@ -32,6 +33,18 @@ public class PDFLaunch extends PDFAction {
*/
public PDFLaunch(PDFFileSpec fileSpec) {
this(fileSpec.makeReference());
+ this.newWindow = false;
+ }
+
+ /**
+ * Creates a new /Launch action.
+ * @param fileSpec the file specification to launch
+ * @param newWindow boolean indicating whether the target should be
+ * displayed in a new window
+ */
+ public PDFLaunch(PDFFileSpec fileSpec, boolean newWindow) {
+ this(fileSpec.makeReference());
+ this.newWindow = newWindow;
}
/**
@@ -56,6 +69,9 @@ public class PDFLaunch extends PDFAction {
StringBuffer sb = new StringBuffer(64);
sb.append("<<\n/S /Launch\n/F ");
sb.append(externalFileSpec.toString());
+ if (newWindow) {
+ sb.append("\n/NewWindow true");
+ }
sb.append("\n>>");
return sb.toString();