git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1863870 13f79535-47bb-0310-9956-ffa450edef68tags/fop-2_4
@@ -41,7 +41,7 @@ public abstract class PDFAction extends PDFObject { | |||
byte[] enc = getDocument().getEncryption().encrypt(buf, this); | |||
return PDFText.toHex(enc, true); | |||
} else { | |||
return "(" + text + ")"; | |||
return PDFText.escapeText(text, false); | |||
} | |||
} | |||
@@ -686,21 +686,20 @@ public class PDFFactory { | |||
} | |||
//Find filespec reference for the embedded file | |||
filename = PDFText.toPDFString(filename, '_'); | |||
PDFArray files = embeddedFiles.getNames(); | |||
PDFReference embeddedFileRef = null; | |||
PDFFileSpec fileSpec = null; | |||
int i = 0; | |||
while (i < files.length()) { | |||
String name = (String)files.get(i); | |||
i++; | |||
PDFReference ref = (PDFReference)files.get(i); | |||
if (name.equals(filename)) { | |||
embeddedFileRef = ref; | |||
if (ref.getObject() instanceof PDFFileSpec | |||
&& ((PDFFileSpec)ref.getObject()).getUnicodeFilename().equals(filename)) { | |||
fileSpec = (PDFFileSpec)ref.getObject(); | |||
break; | |||
} | |||
i++; | |||
} | |||
if (embeddedFileRef == null) { | |||
if (fileSpec == null) { | |||
throw new IllegalStateException( | |||
"No embedded file with name " + filename + " present."); | |||
} | |||
@@ -716,7 +715,7 @@ public class PDFFactory { | |||
//This finally seems to work: | |||
StringBuffer scriptBuffer = new StringBuffer(); | |||
scriptBuffer.append("this.exportDataObject({cName:\""); | |||
scriptBuffer.append(filename); | |||
scriptBuffer.append(fileSpec.getFilename()); | |||
scriptBuffer.append("\", nLaunch:2});"); | |||
PDFJavaScriptLaunchAction action = new PDFJavaScriptLaunchAction(scriptBuffer.toString()); |
@@ -30,18 +30,37 @@ public class PDFFileSpec extends PDFDictionary { | |||
* @param filename the filename represented by this object | |||
*/ | |||
public PDFFileSpec(String filename) { | |||
this(filename, filename); | |||
} | |||
/* generic creation of object */ | |||
super(); | |||
/** | |||
* create a /FileSpec object. | |||
* | |||
* @param filename the filename represented by this object | |||
* @param unicodeFilename the unicode filename represented by this object | |||
*/ | |||
public PDFFileSpec(String filename, String unicodeFilename) { | |||
put("Type", new PDFName("Filespec")); | |||
put("F", filename); | |||
put("UF", filename); // for non-ascii filenames, since PDF 1.7, 3.10.2 | |||
put("UF", unicodeFilename); // for non-ascii filenames, since PDF 1.7, 3.10.2 | |||
} | |||
private String getFilename() { | |||
/** | |||
* Gets the filename. | |||
* @return filename | |||
*/ | |||
public String getFilename() { | |||
return (String)get("F"); | |||
} | |||
/** | |||
* Gets the unicode filename | |||
* @return unicode filename | |||
*/ | |||
public String getUnicodeFilename() { | |||
return (String)get("UF"); | |||
} | |||
/** | |||
* Associates an dictionary with pointers to embedded file streams with this file spec. | |||
* @param embeddedFileDict the dictionary with pointers to embedded file streams |
@@ -334,13 +334,12 @@ public class PDFRoot extends PDFDictionary { | |||
return dPartRoot; | |||
} | |||
public void addAF(PDFFileSpec fileSpec, String filename) { | |||
public void addAF(PDFFileSpec fileSpec) { | |||
if (af == null) { | |||
af = new PDFArray(); | |||
put("AF", af); | |||
} | |||
af.add(fileSpec); | |||
fileSpec.put("UF", filename); | |||
fileSpec.put("AFRelationship", new PDFName("Data")); | |||
} | |||
} |
@@ -73,7 +73,6 @@ import org.apache.fop.pdf.PDFPage; | |||
import org.apache.fop.pdf.PDFPageLabels; | |||
import org.apache.fop.pdf.PDFReference; | |||
import org.apache.fop.pdf.PDFSetOCGStateAction; | |||
import org.apache.fop.pdf.PDFText; | |||
import org.apache.fop.pdf.PDFTransitionAction; | |||
import org.apache.fop.pdf.PDFXMode; | |||
import org.apache.fop.pdf.Version; | |||
@@ -677,9 +676,9 @@ class PDFRenderingUtil { | |||
} | |||
PDFDictionary dict = new PDFDictionary(); | |||
dict.put("F", file); | |||
String filename = PDFText.toPDFString(embeddedFile.getFilename(), '_'); | |||
PDFFileSpec fileSpec = new PDFFileSpec(filename); | |||
pdfDoc.getRoot().addAF(fileSpec, filename); | |||
PDFFileSpec fileSpec = new PDFFileSpec(embeddedFile.getFilename(), embeddedFile.getUnicodeFilename()); | |||
String filename = fileSpec.getFilename(); | |||
pdfDoc.getRoot().addAF(fileSpec); | |||
fileSpec.setEmbeddedFile(dict); | |||
if (embeddedFile.getDesc() != null) { | |||
fileSpec.setDescription(embeddedFile.getDesc()); | |||
@@ -701,8 +700,7 @@ class PDFRenderingUtil { | |||
nameArray = new PDFArray(); | |||
embeddedFiles.setNames(nameArray); | |||
} | |||
String name = PDFText.toPDFString(filename); | |||
nameArray.add(name); | |||
nameArray.add(filename); | |||
nameArray.add(new PDFReference(fileSpec)); | |||
} | |||
@@ -23,6 +23,8 @@ import org.xml.sax.ContentHandler; | |||
import org.xml.sax.SAXException; | |||
import org.xml.sax.helpers.AttributesImpl; | |||
import org.apache.fop.pdf.PDFText; | |||
/** | |||
* This is the pass-through value object for the PDF extension. | |||
*/ | |||
@@ -45,6 +47,9 @@ public class PDFEmbeddedFileAttachment extends PDFExtensionAttachment { | |||
/** filename attribute */ | |||
private String filename; | |||
/** unicode filename attribute */ | |||
private String unicodeFilename; | |||
/** description attribute (optional) */ | |||
private String desc; | |||
@@ -66,7 +71,7 @@ public class PDFEmbeddedFileAttachment extends PDFExtensionAttachment { | |||
*/ | |||
public PDFEmbeddedFileAttachment(String filename, String src, String desc) { | |||
super(); | |||
this.filename = filename; | |||
this.setFilename(filename); | |||
this.src = src; | |||
this.desc = desc; | |||
} | |||
@@ -79,12 +84,26 @@ public class PDFEmbeddedFileAttachment extends PDFExtensionAttachment { | |||
return filename; | |||
} | |||
/** | |||
* Returns the unicode file name. | |||
* @return the file name | |||
*/ | |||
public String getUnicodeFilename() { | |||
return unicodeFilename; | |||
} | |||
/** | |||
* Sets the file name. | |||
* @param name The file name to set. | |||
*/ | |||
public void setFilename(String name) { | |||
this.filename = name; | |||
if (!PDFText.toPDFString(name).equals(name)) { | |||
// replace with auto generated filename, because non-ascii chars are used. | |||
this.filename = "att" + name.hashCode(); | |||
} else { | |||
this.filename = name; | |||
} | |||
this.unicodeFilename = name; | |||
} | |||
/** |
@@ -58,6 +58,52 @@ public class PDFAttachmentTestCase { | |||
Assert.assertTrue(out.toString().contains( | |||
"<<\n /Type /Filespec\n /F (filename)\n /UF (filename)\n /AFRelationship /Data")); | |||
Assert.assertTrue(out.toString().contains("<<\n/S /JavaScript\n" | |||
+ "/JS (this.exportDataObject({cName:\"filename\", nLaunch:2});)\n>>")); | |||
+ "/JS (this.exportDataObject\\({cName:\"filename\", nLaunch:2}\\);)\n>>")); | |||
} | |||
@Test | |||
public void testAddEmbeddedFileGermanUmlaut() throws IFException { | |||
PDFDocumentHandler docHandler = new PDFDocumentHandler(new IFContext(ua)); | |||
docHandler.setFontInfo(new FontInfo()); | |||
ByteArrayOutputStream out = new ByteArrayOutputStream(); | |||
docHandler.setResult(new StreamResult(out)); | |||
docHandler.startDocument(); | |||
docHandler.startPage(0, "", "", new Dimension()); | |||
String germanAe = "\u00E4"; | |||
String unicodeFilename = "t" + germanAe + "st"; | |||
PDFEmbeddedFileAttachment fileAtt = new PDFEmbeddedFileAttachment(unicodeFilename, | |||
"src", "desc"); | |||
docHandler.handleExtensionObject(fileAtt); | |||
docHandler.getDocumentNavigationHandler().renderLink(new Link( | |||
new URIAction("embedded-file:" + unicodeFilename, false), new Rectangle())); | |||
docHandler.endDocument(); | |||
Assert.assertTrue(out.toString().contains( | |||
"<<\n /Type /Filespec\n /F (" + fileAtt.getFilename() + ")\n /UF " | |||
+ PDFText.escapeText(fileAtt.getUnicodeFilename()) + "\n /AFRelationship /Data")); | |||
Assert.assertTrue(out.toString().contains("<<\n/S /JavaScript\n" | |||
+ "/JS (this.exportDataObject\\({cName:\"" + fileAtt.getFilename() + "\", nLaunch:2}\\);)\n>>")); | |||
} | |||
@Test | |||
public void testAddEmbeddedFileParenthesis() throws IFException { | |||
PDFDocumentHandler docHandler = new PDFDocumentHandler(new IFContext(ua)); | |||
docHandler.setFontInfo(new FontInfo()); | |||
ByteArrayOutputStream out = new ByteArrayOutputStream(); | |||
docHandler.setResult(new StreamResult(out)); | |||
docHandler.startDocument(); | |||
docHandler.startPage(0, "", "", new Dimension()); | |||
String unicodeFilename = "t(st"; | |||
PDFEmbeddedFileAttachment fileAtt = new PDFEmbeddedFileAttachment(unicodeFilename, | |||
"src", "desc"); | |||
docHandler.handleExtensionObject(fileAtt); | |||
docHandler.getDocumentNavigationHandler().renderLink(new Link( | |||
new URIAction("embedded-file:" + unicodeFilename, false), new Rectangle())); | |||
docHandler.endDocument(); | |||
Assert.assertTrue(out.toString().contains( | |||
"<<\n /Type /Filespec\n /F (t\\(st)\n /UF (t\\(st)\n /AFRelationship /Data")); | |||
Assert.assertTrue(out.toString().contains("<<\n/S /JavaScript\n" | |||
+ "/JS (this.exportDataObject\\({cName:\"t\\(st\", nLaunch:2}\\);)\n>>")); | |||
} | |||
} |
@@ -167,4 +167,48 @@ public class PDFFactoryTestCase { | |||
assertTrue(bos.toString().contains("/Subtype /Type1\n")); | |||
assertTrue(bos.toString().contains("/Subtype /Type1C")); | |||
} | |||
@Test | |||
public void testGetExternalAction() { | |||
String germanAe = "\u00E4"; | |||
String filename = "test"; | |||
String unicodeFilename = "t" + germanAe + "st.pdf"; | |||
PDFFileSpec fileSpec = new PDFFileSpec(filename, unicodeFilename); | |||
PDFDocument doc = new PDFDocument(""); | |||
doc.registerObject(fileSpec); | |||
PDFNames names = doc.getRoot().getNames(); | |||
if (names == null) { | |||
//Add Names if not already present | |||
names = doc.getFactory().makeNames(); | |||
doc.getRoot().setNames(names); | |||
} | |||
PDFEmbeddedFiles embeddedFiles = names.getEmbeddedFiles(); | |||
if (embeddedFiles == null) { | |||
embeddedFiles = new PDFEmbeddedFiles(); | |||
doc.assignObjectNumber(embeddedFiles); | |||
doc.addTrailerObject(embeddedFiles); | |||
names.setEmbeddedFiles(embeddedFiles); | |||
} | |||
PDFArray nameArray = embeddedFiles.getNames(); | |||
if (nameArray == null) { | |||
nameArray = new PDFArray(); | |||
embeddedFiles.setNames(nameArray); | |||
} | |||
nameArray.add(fileSpec.getFilename()); | |||
nameArray.add(new PDFReference(fileSpec)); | |||
PDFFactory pdfFactory = new PDFFactory(doc); | |||
String target = "embedded-file:" + unicodeFilename; | |||
PDFJavaScriptLaunchAction pdfAction = (PDFJavaScriptLaunchAction) | |||
pdfFactory.getExternalAction(target, false); | |||
String expectedString = "<<\n/S /JavaScript\n/JS (this.exportDataObject\\({cName:\"" | |||
+ fileSpec.getFilename() + "\", nLaunch:2}\\);)\n>>"; | |||
assertEquals(expectedString, pdfAction.toPDFString()); | |||
} | |||
} |
@@ -0,0 +1,37 @@ | |||
/* | |||
* 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. | |||
*/ | |||
/* $Id: PDFFactoryTestCase.java 1823552 2018-02-08 12:26:33Z ssteiner $ */ | |||
package org.apache.fop.pdf; | |||
import org.junit.Test; | |||
import static org.junit.Assert.assertEquals; | |||
public class PDFFileSpecTestCase { | |||
@Test | |||
public void testPDFFileSpec() { | |||
String germanAe = "\u00E4"; | |||
String filename = "test"; | |||
String unicodeFilename = "t" + germanAe + "st"; | |||
PDFFileSpec fileSpec = new PDFFileSpec(filename, unicodeFilename); | |||
assertEquals(fileSpec.getUnicodeFilename(), unicodeFilename); | |||
assertEquals(fileSpec.getFilename(), filename); | |||
} | |||
} |
@@ -19,6 +19,7 @@ | |||
package org.apache.fop.pdf; | |||
import org.apache.fop.render.pdf.extensions.PDFEmbeddedFileAttachmentTest; | |||
import org.junit.runner.RunWith; | |||
import org.junit.runners.Suite; | |||
import org.junit.runners.Suite.SuiteClasses; | |||
@@ -42,7 +43,10 @@ import org.junit.runners.Suite.SuiteClasses; | |||
PDFReferenceTestCase.class, | |||
PDFResourcesTestCase.class, | |||
VersionTestCase.class, | |||
VersionControllerTestCase.class | |||
VersionControllerTestCase.class, | |||
PDFRootTestCase.class, | |||
PDFFileSpecTestCase.class, | |||
PDFEmbeddedFileAttachmentTest.class | |||
}) | |||
public class PDFLibraryTestSuite { | |||
} |
@@ -391,6 +391,9 @@ public class PDFLinkTestCase { | |||
{"examples.html?foo#bar", quote("/URI (examples.html?foo#bar)")}, | |||
{"examples.html", quote("<< /URI (examples.html)")}, | |||
{"file:examples.html", quote("<< /Type /Filespec /F (examples.html)")}, | |||
// parenthesis | |||
{"simple_report_(version2.pdf", quote("<< /URI (simple_report_\\(version2.pdf)")} | |||
}); | |||
} | |||
@@ -0,0 +1,42 @@ | |||
/* | |||
* 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. | |||
*/ | |||
/* $Id: PDFFactoryTestCase.java 1823552 2018-02-08 12:26:33Z ssteiner $ */ | |||
package org.apache.fop.pdf; | |||
import org.junit.Test; | |||
import static org.junit.Assert.assertEquals; | |||
public class PDFRootTestCase { | |||
@Test | |||
public void testAddAf() { | |||
String germanAe = "\u00E4"; | |||
String unicodeFilename = "t" + germanAe + "st.pdf"; | |||
PDFFileSpec fileSpec = new PDFFileSpec(unicodeFilename); | |||
String filename = fileSpec.getFilename(); | |||
PDFDocument doc = new PDFDocument(""); | |||
doc.getRoot().addAF(fileSpec); | |||
assertEquals(filename, fileSpec.getFilename()); | |||
assertEquals(unicodeFilename, fileSpec.getUnicodeFilename()); | |||
} | |||
} |
@@ -0,0 +1,42 @@ | |||
/* | |||
* 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. | |||
*/ | |||
/* $Id: PDFRenderingUtil.java 1761019 2016-09-16 10:43:45Z ssteiner $ */ | |||
package org.apache.fop.render.pdf.extensions; | |||
import org.junit.Test; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertFalse; | |||
public class PDFEmbeddedFileAttachmentTest { | |||
@Test | |||
public void testGetFilename() { | |||
String germanAe = "\u00E4"; | |||
String unicodeFilename = "t" + germanAe + "st"; | |||
String src = "src"; | |||
String desc = "desc"; | |||
PDFEmbeddedFileAttachment fileAtt = new PDFEmbeddedFileAttachment(unicodeFilename, src, desc); | |||
assertEquals(fileAtt.getUnicodeFilename(), unicodeFilename); | |||
assertFalse(fileAtt.getFilename().contains(germanAe)); | |||
assertEquals(fileAtt.getSrc(), src); | |||
assertEquals(fileAtt.getDesc(), desc); | |||
} | |||
} |