diff --git a/app/pom.xml b/app/pom.xml index a824268e8df24fe2d38ee947a8f7f18732a6c2ff..dd1eaf7cca02886ea488bd7d1959d0cd5ffdba2f 100644 --- a/app/pom.xml +++ b/app/pom.xml @@ -23,7 +23,7 @@ org.apache.pdfbox pdfbox-parent - 3.0.0-SNAPSHOT + 3.0.1-SNAPSHOT ../parent/pom.xml @@ -41,7 +41,7 @@ org.bouncycastle - bcmail-jdk18on + bcpkix-jdk18on provided diff --git a/benchmark/pom.xml b/benchmark/pom.xml index 66e06833dceacd2ac58d396f3c675c8179d155d8..83c867c5b3670beee5f02119aa5f64b5e4725b3d 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -58,7 +58,7 @@ UTF-8 - 1.36 + 1.37 benchmarks @@ -67,7 +67,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.5.1 package diff --git a/debugger-app/pom.xml b/debugger-app/pom.xml index e9f257e0ab65613f2275b0a460fddc3604b15eb6..289b63e01c2161d25646858b4ebf7dad4217216d 100644 --- a/debugger-app/pom.xml +++ b/debugger-app/pom.xml @@ -23,7 +23,7 @@ org.apache.pdfbox pdfbox-parent - 3.0.0-SNAPSHOT + 3.0.1-SNAPSHOT ../parent/pom.xml @@ -41,7 +41,7 @@ org.bouncycastle - bcmail-jdk18on + bcpkix-jdk18on provided diff --git a/debugger/pom.xml b/debugger/pom.xml index dd92396e10684e87248049abc9a43cfc241472ad..3c09791a4aeadce0dbc9239e9df64b7e097fbb86 100644 --- a/debugger/pom.xml +++ b/debugger/pom.xml @@ -23,7 +23,7 @@ org.apache.pdfbox pdfbox-parent - 3.0.0-SNAPSHOT + 3.0.1-SNAPSHOT ../parent/pom.xml @@ -38,11 +38,6 @@ 2002 - - org.bouncycastle - bcmail-jdk18on - true - ${project.groupId} pdfbox diff --git a/debugger/src/main/java/org/apache/pdfbox/debugger/PDFDebugger.java b/debugger/src/main/java/org/apache/pdfbox/debugger/PDFDebugger.java index 680c729e5e04960b5557da9f84036e0b1ffb6124..37569ed9472d72677f768d80bc5b5fd09fa78642 100644 --- a/debugger/src/main/java/org/apache/pdfbox/debugger/PDFDebugger.java +++ b/debugger/src/main/java/org/apache/pdfbox/debugger/PDFDebugger.java @@ -17,11 +17,13 @@ package org.apache.pdfbox.debugger; import java.awt.BorderLayout; +import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.FileDialog; import java.awt.Frame; +import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; @@ -32,6 +34,7 @@ import java.awt.event.KeyEvent; import java.awt.event.WindowEvent; import java.awt.print.PrinterException; import java.awt.print.PrinterJob; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -40,6 +43,8 @@ import java.io.PrintStream; import java.lang.reflect.Method; import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -55,7 +60,10 @@ import javax.print.attribute.PrintRequestAttributeSet; import javax.print.attribute.standard.Sides; import javax.swing.AbstractAction; import javax.swing.Action; +import javax.swing.Box; import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JEditorPane; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; @@ -69,6 +77,8 @@ import javax.swing.KeyStroke; import javax.swing.TransferHandler; import javax.swing.UIManager; import javax.swing.border.BevelBorder; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileNameExtensionFilter; @@ -153,7 +163,7 @@ import picocli.CommandLine.Model.CommandSpec; */ @SuppressWarnings({ "serial", "squid:MaximumInheritanceDepth", "squid:S1948" }) @Command(name = "pdfdebugger", description = "Analyzes and inspects the internal structure of a PDF document") -public class PDFDebugger extends JFrame implements Callable +public class PDFDebugger extends JFrame implements Callable, HyperlinkListener { private static Log LOG; // needs late initialization @@ -199,7 +209,7 @@ public class PDFDebugger extends JFrame implements Callable // cli options // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; @Option(names = { "-h", "--help" }, usageHelp = true, description = "display this help message") boolean usageHelpRequested; @@ -223,6 +233,7 @@ public class PDFDebugger extends JFrame implements Callable */ public PDFDebugger() { + SYSERR = System.err; if (viewstructure) { currentTreeViewMode = TreeViewMenu.VIEW_STRUCTURE; @@ -237,6 +248,7 @@ public class PDFDebugger extends JFrame implements Callable */ public PDFDebugger(String initialViewMode) { + SYSERR = System.err; if (TreeViewMenu.isValidViewMode(initialViewMode)) { currentTreeViewMode = initialViewMode; @@ -438,6 +450,18 @@ public class PDFDebugger extends JFrame implements Callable menuBar.add(viewMenu.getMenu()); setJMenuBar(menuBar); + menuBar.add(Box.createHorizontalGlue()); + JMenu help = new JMenu("Help"); + help.setMnemonic(KeyEvent.VK_H); + + JMenuItem item = new JMenuItem("About PDFBox", KeyEvent.VK_A); + item.setActionCommand("about"); + item.addActionListener(actionEvent -> + textDialog("About Apache PDFBox", PDFDebugger.class.getResource("about.html"))); + help.add(item); + + menuBar.add(help); + setExtendedState(windowPrefs.getExtendedState()); setBounds(windowPrefs.getBounds()); @@ -1593,4 +1617,77 @@ public class PDFDebugger extends JFrame implements Callable } return null; } + + private void textDialog(String title, URL resource) + { + try + { + JDialog dialog = new JDialog(this, title, true); + JEditorPane editor = new JEditorPane(resource); + editor.setContentType("text/html"); + editor.setEditable(false); + editor.setBackground(Color.WHITE); + editor.setPreferredSize(new Dimension(400, 250)); + + // put it in the middle of the parent, but not outside of the screen + // GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice() + // doesn't work give the numbers we need + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + double screenWidth = screenSize.getWidth(); + double screenHeight = screenSize.getHeight(); + Rectangle parentBounds = this.getBounds(); + editor.addHyperlinkListener(this); + dialog.add(editor); + dialog.pack(); + + int x = (int) (parentBounds.getX() + (parentBounds.getWidth() - editor.getWidth()) / 2); + int y = (int) (parentBounds.getY() + (parentBounds.getHeight() - editor.getHeight()) / 2); + x = (int) Math.min(x, screenWidth * 3 / 4); + y = (int) Math.min(y, screenHeight * 3 / 4); + x = Math.max(0, x); + y = Math.max(0, y); + dialog.setLocation(x, y); + + dialog.setVisible(true); + } + catch (IOException ex) + { + new ErrorDialog(ex).setVisible(true); + } + } + + @Override + public void hyperlinkUpdate(HyperlinkEvent he) + { + if (he.getEventType() == HyperlinkEvent.EventType.ACTIVATED) + { + try + { + URL url = he.getURL(); + try (InputStream stream = url.openStream()) + { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + IOUtils.copy(stream,baos); + JEditorPane editor + = new JEditorPane("text/plain", baos.toString(StandardCharsets.UTF_8.name())); + editor.setEditable(false); + editor.setBackground(Color.WHITE); + editor.setCaretPosition(0); + editor.setPreferredSize(new Dimension(600, 400)); + + String name = url.toString(); + name = name.substring(name.lastIndexOf('/') + 1); + + JDialog dialog = new JDialog(this, "Apache PDFBox: " + name, true); + dialog.add(new JScrollPane(editor)); + dialog.pack(); + dialog.setVisible(true); + } + } + catch (IOException ex) + { + new ErrorDialog(ex).setVisible(true); + } + } + } } diff --git a/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/SimpleFont.java b/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/SimpleFont.java index d6bccc73179bfffebd35426255a9811afccec7b8..edb88c3d6599a0fd530a1d2691dc3d1756cfb825 100644 --- a/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/SimpleFont.java +++ b/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/SimpleFont.java @@ -55,6 +55,7 @@ class SimpleFont extends FontPane attributes.put("Encoding", getEncodingName(font)); attributes.put("Glyphs", Integer.toString(totalAvailableGlyph)); attributes.put("Standard 14", Boolean.toString(font.isStandard14())); + attributes.put("Embedded", Boolean.toString(font.isEmbedded())); view = new FontEncodingView(tableData, attributes, new String[] {"Code", "Glyph Name", "Unicode Character", "Glyph"}, yBounds); diff --git a/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/Type0Font.java b/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/Type0Font.java index 9e7ada2cdeae8e851f6a35c4e92c1825e9989589..cd941416cce74e82fb672376104c98d46df8b984 100644 --- a/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/Type0Font.java +++ b/debugger/src/main/java/org/apache/pdfbox/debugger/fontencodingpane/Type0Font.java @@ -57,6 +57,7 @@ class Type0Font extends FontPane Map attributes = new LinkedHashMap<>(); attributes.put("Font", descendantFont.getName()); attributes.put("CIDs", Integer.toString(cidtogid.length)); + attributes.put("Embedded", Boolean.toString(descendantFont.isEmbedded())); view = new FontEncodingView(cidtogid, attributes, new String[]{"CID", "GID", "Unicode Character", "Glyph"}, getYBounds(cidtogid, 3)); @@ -69,6 +70,7 @@ class Type0Font extends FontPane attributes.put("CIDs", Integer.toString(tab.length)); attributes.put("Glyphs", Integer.toString(totalAvailableGlyph)); attributes.put("Standard 14", Boolean.toString(parentFont.isStandard14())); + attributes.put("Embedded", Boolean.toString(descendantFont.isEmbedded())); view = new FontEncodingView(tab, attributes, new String[]{"Code", "CID", "GID", "Unicode Character", "Glyph"}, getYBounds(tab, 4)); diff --git a/debugger/src/main/java/org/apache/pdfbox/debugger/pagepane/PagePane.java b/debugger/src/main/java/org/apache/pdfbox/debugger/pagepane/PagePane.java index 9234a56e99da4a5591b3d923e1297831f63f3ee9..80b1a0cd0a9b6f980fd7c102f8ec1414c9501009 100644 --- a/debugger/src/main/java/org/apache/pdfbox/debugger/pagepane/PagePane.java +++ b/debugger/src/main/java/org/apache/pdfbox/debugger/pagepane/PagePane.java @@ -39,11 +39,11 @@ import javax.swing.event.AncestorListener; import java.awt.Component; import java.awt.Cursor; import java.awt.Desktop; -import java.awt.DisplayMode; +import java.awt.Dimension; import java.awt.Font; -import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.Point; +import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; @@ -277,10 +277,9 @@ public class PagePane implements ActionListener, AncestorListener, MouseMotionLi private void startExtracting() { - GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); - DisplayMode dm = gd.getDisplayMode(); - int screenWidth = dm.getWidth(); - int screenHeight = dm.getHeight(); + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + int screenWidth = (int) screenSize.getWidth(); + int screenHeight = (int) screenSize.getHeight(); TextDialog textDialog = TextDialog.instance(); textDialog.setSize(screenWidth / 3, screenHeight / 3); @@ -290,6 +289,8 @@ public class PagePane implements ActionListener, AncestorListener, MouseMotionLi Point locationOnScreen = getPanel().getLocationOnScreen(); int x = Math.min(locationOnScreen.x + getPanel().getWidth() / 2, screenWidth * 3 / 4); int y = Math.min(locationOnScreen.y + getPanel().getHeight() / 2, screenHeight * 3 / 4); + x = Math.max(0, x); + y = Math.max(0, y); textDialog.setLocation(x, y); try diff --git a/debugger/src/main/java/org/apache/pdfbox/debugger/ui/RecentFiles.java b/debugger/src/main/java/org/apache/pdfbox/debugger/ui/RecentFiles.java index 52c5cc9e24838092e556c51cfa1beee538f66df1..a3a59b4f5a341b98b32008905a5da96d4c84c85e 100644 --- a/debugger/src/main/java/org/apache/pdfbox/debugger/ui/RecentFiles.java +++ b/debugger/src/main/java/org/apache/pdfbox/debugger/ui/RecentFiles.java @@ -97,10 +97,7 @@ public class RecentFiles */ public void removeFile(String path) { - if (filePaths.contains(path)) - { - filePaths.remove(path); - } + filePaths.remove(path); } /** diff --git a/debugger/src/main/resources/org/apache/pdfbox/debugger/about.html b/debugger/src/main/resources/org/apache/pdfbox/debugger/about.html new file mode 100644 index 0000000000000000000000000000000000000000..e63b2b8704840d94fffa5013633f743c9af8b2ca --- /dev/null +++ b/debugger/src/main/resources/org/apache/pdfbox/debugger/about.html @@ -0,0 +1,30 @@ + + + +
+

The PDFBox logo showing a toolbox.

+ +

Apache PDFBox® ${project.version} is an open source Java library to create, render, print, split, merge, modify, inspect and extract text and meta-data of PDF files.

+ +

Copyright notice + - License terms

+
+ + diff --git a/debugger/src/main/resources/org/apache/pdfbox/debugger/pdfbox-logo.png b/debugger/src/main/resources/org/apache/pdfbox/debugger/pdfbox-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..76abf9fcdc201cffde4dd537cba46dfd8f6f4821 Binary files /dev/null and b/debugger/src/main/resources/org/apache/pdfbox/debugger/pdfbox-logo.png differ diff --git a/examples/pom.xml b/examples/pom.xml index b37284c900315f3f02e81202e8467d89252dd4c6..19c46020c40021f465429c2b6372ea5bbdb66ae7 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -23,7 +23,7 @@ org.apache.pdfbox pdfbox-parent - 3.0.0-SNAPSHOT + 3.0.1-SNAPSHOT ../parent/pom.xml @@ -45,8 +45,11 @@ org.bouncycastle - bcmail-jdk18on - true + bcprov-jdk18on + + + org.bouncycastle + bcpkix-jdk18on ${project.groupId} @@ -77,7 +80,7 @@ org.apache.ant ant - 1.10.13 + 1.10.14 org.junit.jupiter @@ -98,7 +101,7 @@ commons-net commons-net - 3.9.0 + 3.10.0 test diff --git a/fontbox/pom.xml b/fontbox/pom.xml index 909b78d5899e5b04f90460f55471cd792cb4fd44..282a2da9d49c022df659142960a2b25e9fae5ec4 100644 --- a/fontbox/pom.xml +++ b/fontbox/pom.xml @@ -21,7 +21,7 @@ org.apache.pdfbox pdfbox-parent - 3.0.0-SNAPSHOT + 3.0.1-SNAPSHOT ../parent/pom.xml diff --git a/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharString.java b/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharString.java index 99e725a26bb1a64b6152e780daea2df9f35585bd..c31e30aa6e4b16958e0b240661449046f2b06b9e 100644 --- a/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharString.java +++ b/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharString.java @@ -269,7 +269,7 @@ public class Type2CharString extends Type1CharString : null; if (command != null && command.getType1KeyWord() != Type1KeyWord.CLOSEPATH) { - addCommand(Collections. emptyList(), CharStringCommand.COMMAND_CLOSEPATH); + addCommand(Collections.emptyList(), CharStringCommand.COMMAND_CLOSEPATH); } } diff --git a/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphSubstitutionTable.java b/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphSubstitutionTable.java index 33c2996c1515993527261739ed7881f22486ea90..1ac3fd00a6d470d3f907fda294fe6a61d1134742 100644 --- a/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphSubstitutionTable.java +++ b/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphSubstitutionTable.java @@ -369,7 +369,8 @@ public class GlyphSubstitutionTable extends TTFTable return new LookupTypeSingleSubstFormat2(substFormat, coverageTable, substituteGlyphIDs); } default: - throw new IOException("Unknown substFormat: " + substFormat); + LOG.warn("Unknown substFormat: " + substFormat); + return null; } } diff --git a/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GlyphSubstitutionDataExtractor.java b/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GlyphSubstitutionDataExtractor.java index 20569b51fc4768f0f28c468790d0a5bd1b328d8e..bb59427db95d96e8cbc625d3348ea80927597e91 100644 --- a/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GlyphSubstitutionDataExtractor.java +++ b/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GlyphSubstitutionDataExtractor.java @@ -303,7 +303,7 @@ public class GlyphSubstitutionDataExtractor { String message = "For the newGlyph: " + newGlyph + ", newValue: " + glyphsToBeSubstituted + " is trying to override the oldValue: " + oldValue; - LOG.warn(message); + LOG.debug(message); } } diff --git a/io/pom.xml b/io/pom.xml index f98b866139e29f69543c13babd34fe4a3c618929..97549912ef21ad1429b37bbd860194a29b576f45 100644 --- a/io/pom.xml +++ b/io/pom.xml @@ -23,7 +23,7 @@ org.apache.pdfbox pdfbox-parent - 3.0.0-SNAPSHOT + 3.0.1-SNAPSHOT ../parent/pom.xml diff --git a/io/src/main/java/org/apache/pdfbox/io/RandomAccessReadBuffer.java b/io/src/main/java/org/apache/pdfbox/io/RandomAccessReadBuffer.java index 64d7d730226766750210eee3e13262c4f4a6dead..e87c027689ad93046eba86264380b7d1f310b72a 100644 --- a/io/src/main/java/org/apache/pdfbox/io/RandomAccessReadBuffer.java +++ b/io/src/main/java/org/apache/pdfbox/io/RandomAccessReadBuffer.java @@ -21,6 +21,8 @@ import java.io.InputStream; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; /** * An implementation of the RandomAccessRead interface to store data in memory. The data will be stored in chunks @@ -47,6 +49,9 @@ public class RandomAccessReadBuffer implements RandomAccessRead // maximum chunk list index private int bufferListMaxIndex = 0; + // map holding all copies of the current buffer + private final ConcurrentMap rarbCopies = new ConcurrentHashMap<>(); + /** * Default constructor. */ @@ -145,6 +150,8 @@ public class RandomAccessReadBuffer implements RandomAccessRead @Override public void close() throws IOException { + rarbCopies.values().forEach(IOUtils::closeQuietly); + rarbCopies.clear(); currentBuffer = null; bufferList.clear(); } @@ -362,8 +369,14 @@ public class RandomAccessReadBuffer implements RandomAccessRead @Override public RandomAccessReadView createView(long startPosition, long streamLength) throws IOException { - return new RandomAccessReadView(new RandomAccessReadBuffer(this), startPosition, - streamLength, true); + Long currentThreadID = Thread.currentThread().getId(); + RandomAccessReadBuffer randomAccessReadBuffer = rarbCopies.get(currentThreadID); + if (randomAccessReadBuffer == null || randomAccessReadBuffer.isClosed()) + { + randomAccessReadBuffer = new RandomAccessReadBuffer(this); + rarbCopies.put(currentThreadID, randomAccessReadBuffer); + } + return new RandomAccessReadView(randomAccessReadBuffer, startPosition, streamLength); } /** diff --git a/parent/pom.xml b/parent/pom.xml index 1b911d4a89d2e04e6241ac4123cebd68d34df458..8058387761793b7817266ab8e635d396dde63f60 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -29,7 +29,7 @@ org.apache.pdfbox pdfbox-parent - 3.0.0-SNAPSHOT + 3.0.1-SNAPSHOT pom PDFBox parent @@ -75,7 +75,7 @@ commons-io commons-io - 2.13.0 + 2.14.0 test @@ -83,11 +83,6 @@ bcprov-jdk18on ${bouncycastle.version} - - org.bouncycastle - bcmail-jdk18on - ${bouncycastle.version} - org.bouncycastle bcpkix-jdk18on @@ -119,7 +114,7 @@ info.picocli picocli - 4.7.4 + 4.7.5 @@ -211,7 +206,7 @@ org.owasp dependency-check-maven - 8.3.1 + 8.4.0 true @@ -352,7 +347,7 @@ maven-enforcer-plugin - 3.3.0 + 3.4.1 @@ -552,10 +547,4 @@ - - - scm:svn:http://svn.apache.org/repos/asf/pdfbox/trunk - scm:svn:https://svn.apache.org/repos/asf/pdfbox/trunk - http://svn.apache.org/viewvc/pdfbox/trunk - diff --git a/pdfbox/pom.xml b/pdfbox/pom.xml index 4529bdcd00eae60560fd22fd7fc92d66ba31bbfa..79c8e687cf750e99c62d6f14762e542093b3e083 100644 --- a/pdfbox/pom.xml +++ b/pdfbox/pom.xml @@ -23,7 +23,7 @@ org.apache.pdfbox pdfbox-parent - 3.0.0-SNAPSHOT + 3.0.1-SNAPSHOT ../parent/pom.xml @@ -57,12 +57,14 @@
org.bouncycastle - bcmail-jdk18on + bcprov-jdk18on + compile true org.bouncycastle - bcprov-jdk18on + bcpkix-jdk18on + compile true diff --git a/pdfbox/src/main/java/org/apache/pdfbox/cos/COSArray.java b/pdfbox/src/main/java/org/apache/pdfbox/cos/COSArray.java index df9dd605a4a43f1364ae2617b89104f3e70659de..4a93d7816108e0497fbd24076904b63f5b1ba210 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/cos/COSArray.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/cos/COSArray.java @@ -617,7 +617,7 @@ public class COSArray extends COSBase implements Iterable, COSUpdateInf */ public List toCOSNameStringList() { - return StreamSupport.stream(objects.spliterator(), false) // + return objects.stream() // .map(o -> ((COSName) o).getName()) // .collect(Collectors.toList()); } @@ -629,7 +629,7 @@ public class COSArray extends COSBase implements Iterable, COSUpdateInf */ public List toCOSStringStringList() { - return StreamSupport.stream(objects.spliterator(), false) // + return objects.stream() // .map(o -> ((COSString) o).getString()) // .collect(Collectors.toList()); } diff --git a/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDocument.java b/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDocument.java index af039eb85230aeddbf0d36d0a6851352a175d7e8..402c979c7fd3e27b402665641949e6fe7a635500 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDocument.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDocument.java @@ -195,6 +195,7 @@ public class COSDocument extends COSBase implements Closeable COSStream stream = new COSStream(streamCache, parser.createRandomAccessReadView(startPosition, streamLength)); dictionary.forEach(stream::setItem); + stream.setKey(dictionary.getKey()); return stream; } @@ -249,13 +250,28 @@ public class COSDocument extends COSBase implements Closeable * @return This will return all objects with the specified type(s). */ public List getObjectsByType(COSName type1, COSName type2) + { + List originKeys = new ArrayList(xrefTable.keySet()); + List retval = getObjectsByType(originKeys, type1, type2); + // there might be some additional objects if the brute force parser was triggered + // due to a broken cross reference table/stream + if (originKeys.size() < xrefTable.size()) + { + List additionalKeys = new ArrayList(xrefTable.keySet()); + additionalKeys.removeAll(originKeys); + retval.addAll(getObjectsByType(additionalKeys, type1, type2)); + } + return retval; + } + + private List getObjectsByType(List keys, COSName type1, COSName type2) { List retval = new ArrayList<>(); - for (COSObjectKey objectKey : xrefTable.keySet()) + for (COSObjectKey objectKey : keys) { COSObject objectFromPool = getObjectFromPool(objectKey); COSBase realObject = objectFromPool.getObject(); - if( realObject instanceof COSDictionary ) + if (realObject instanceof COSDictionary) { COSName dictType = ((COSDictionary) realObject).getCOSName(COSName.TYPE); if (type1.equals(dictType) || (type2 != null && type2.equals(dictType))) diff --git a/pdfbox/src/main/java/org/apache/pdfbox/cos/COSInputStream.java b/pdfbox/src/main/java/org/apache/pdfbox/cos/COSInputStream.java index 06840b28aad81a07e206c498da5c3c9a49813036..0b13034763144635b5e91799cdeefa6a6f628e43 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/cos/COSInputStream.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/cos/COSInputStream.java @@ -67,7 +67,7 @@ public final class COSInputStream extends FilterInputStream { if (filters.isEmpty()) { - return new COSInputStream(in, Collections.emptyList()); + return new COSInputStream(in, Collections.emptyList()); } List results = new ArrayList<>(filters.size()); RandomAccessRead decoded = Filter.decode(in, filters, parameters, options, results); diff --git a/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java b/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java index b66a90b1cce930c7927b3266d8dbecad4bf97d96..79a2a665da39e2de0d2553b1809e563584382bf1 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java @@ -535,6 +535,7 @@ public final class COSName extends COSBase implements Comparable public static final COSName SIZE = new COSName("Size"); public static final COSName SM = new COSName("SM"); public static final COSName SMASK = new COSName("SMask"); + public static final COSName SMASK_IN_DATA = new COSName("SMaskInData"); public static final COSName SOFT_LIGHT = new COSName("SoftLight"); public static final COSName SORT = new COSName("Sort"); public static final COSName SOUND = new COSName("Sound"); diff --git a/pdfbox/src/main/java/org/apache/pdfbox/cos/COSObjectKey.java b/pdfbox/src/main/java/org/apache/pdfbox/cos/COSObjectKey.java index 33a26ea615116b7f0fba4f1038885634dd9e1b76..8c09d914097c9adf340c5dc0ab4999a31547ab04 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/cos/COSObjectKey.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/cos/COSObjectKey.java @@ -86,6 +86,16 @@ public final class COSObjectKey implements Comparable return num << NUMBER_OFFSET | (gen & GENERATION_MASK); } + /** + * Return the internal hash value which is based on the number and the generation. + * + * @return the internal hash value + */ + public long getInternalHash() + { + return numberAndGeneration; + } + /** * {@inheritDoc} */ diff --git a/pdfbox/src/main/java/org/apache/pdfbox/filter/JPXFilter.java b/pdfbox/src/main/java/org/apache/pdfbox/filter/JPXFilter.java index 9837e52718f1081cebd3c3912067ec93a3147b7e..8c9757b9f0753fbe95d674a17c572a0d3fe9bdae 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/filter/JPXFilter.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/filter/JPXFilter.java @@ -15,6 +15,9 @@ * limitations under the License. */ package org.apache.pdfbox.filter; + +import java.awt.Graphics2D; +import java.awt.Transparency; import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; import java.awt.image.DataBuffer; @@ -30,6 +33,10 @@ import javax.imageio.ImageReadParam; import javax.imageio.ImageReader; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.MemoryCacheImageInputStream; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.apache.pdfbox.cos.COSDictionary; import org.apache.pdfbox.cos.COSName; import org.apache.pdfbox.pdmodel.graphics.color.PDJPXColorSpace; @@ -51,6 +58,8 @@ import org.apache.pdfbox.pdmodel.graphics.color.PDJPXColorSpace; */ public final class JPXFilter extends Filter { + private static final Log LOG = LogFactory.getLog(JPXFilter.class); + /** * {@inheritDoc} */ @@ -166,6 +175,18 @@ public final class JPXFilter extends Filter // in raster result.setColorSpace(new PDJPXColorSpace(ColorSpace.getInstance(ColorSpace.CS_GRAY))); } + else if (image.getTransparency() == Transparency.TRANSLUCENT && + parameters.getInt(COSName.SMASK_IN_DATA) > 0) + { + LOG.warn("JPEG2000 SMaskInData is not supported, returning opaque image"); + BufferedImage bim = new BufferedImage( + image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = (Graphics2D) bim.getGraphics(); + g2d.drawImage(image, 0, 0, null); + g2d.dispose(); + image = bim; + result.setColorSpace(new PDJPXColorSpace(image.getColorModel().getColorSpace())); + } else { result.setColorSpace(new PDJPXColorSpace(image.getColorModel().getColorSpace())); diff --git a/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java b/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java index a90773ac749379784fe30121e33f3671d5f2a59b..f382d5b1bf9d5a91c3e90d4adcd51ade6b0e7fff 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java @@ -525,7 +525,7 @@ public class PDFMergerUtility PDDocumentInformation destInfo = destination.getDocumentInformation(); PDDocumentInformation srcInfo = source.getDocumentInformation(); - mergeInto(srcInfo.getCOSObject(), destInfo.getCOSObject(), Collections.emptySet()); + mergeInto(srcInfo.getCOSObject(), destInfo.getCOSObject(), Collections.emptySet()); // use the highest version number for the resulting pdf float destVersion = destination.getVersion(); @@ -910,7 +910,7 @@ public class PDFMergerUtility destCatalog.setViewerPreferences(destViewerPreferences); } mergeInto(srcViewerPreferences.getCOSObject(), destViewerPreferences.getCOSObject(), - Collections.emptySet()); + Collections.emptySet()); // check the booleans - set to true if one is set and true if (srcViewerPreferences.hideToolbar() || destViewerPreferences.hideToolbar()) diff --git a/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/BaseParser.java b/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/BaseParser.java index d81e6cdc2f97966db00309a051b0893fba83ab7f..c1f565a28c8d3e160a6037669344547911bb94da 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/BaseParser.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/BaseParser.java @@ -57,7 +57,7 @@ public abstract class BaseParser private final CharsetDecoder utf8Decoder = StandardCharsets.UTF_8.newDecoder(); - private final Map keyCache = new HashMap<>(); + private final Map keyCache = new HashMap<>(); /** * Log instance. @@ -166,11 +166,11 @@ public abstract class BaseParser { for (COSObjectKey key : xrefTable.keySet()) { - keyCache.putIfAbsent(key.hashCode(), key); + keyCache.putIfAbsent(key.getInternalHash(), key); } } - int hashCode = Long.hashCode(COSObjectKey.computeInternalHash(num, gen)); - COSObjectKey foundKey = keyCache.get(hashCode); + long internalHashCode = COSObjectKey.computeInternalHash(num, gen); + COSObjectKey foundKey = keyCache.get(internalHashCode); return foundKey != null ? foundKey : new COSObjectKey(num, gen); } diff --git a/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFParser.java b/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFParser.java index 1c855e64bb71964a5fc31aef9cf139268ae1f621..ba87efe84402ba5dab8a42308f0356ea2f6c4e99 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFParser.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFParser.java @@ -176,7 +176,14 @@ public class PDFParser extends COSParser // PDFBOX-1922 read the version header and rewind if (!parsePDFHeader() && !parseFDFHeader()) { - throw new IOException( "Error: Header doesn't contain versioninfo" ); + if (lenient) + { + LOG.warn("Error: Header doesn't contain versioninfo"); + } + else + { + throw new IOException("Error: Header doesn't contain versioninfo"); + } } if (!initialParseDone) diff --git a/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFStreamParser.java b/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFStreamParser.java index 340e88725da11f77675edbc90a21887f23b9c6ec..c6660b43deec6e00a8b0ed6d1e64a93d39530330 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFStreamParser.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFStreamParser.java @@ -406,6 +406,7 @@ public class PDFStreamParser extends BaseParser nextChar != '<' && nextChar != '(' && nextChar != '/' && + nextChar != '%' && (nextChar < '0' || nextChar > '9' ) ) { diff --git a/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java b/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java index 601fa3078b6cd2b7d724e2b6c6eb50f0ad953815..9b8aa2e1a7441598c4c83194eb82d60dad4ea870 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java @@ -1566,6 +1566,10 @@ public class COSWriter implements ICOSVisitor trailer.setItem(COSName.ID, idArray); } cosDoc.accept(this); + if (!incrementalUpdate) + { + cosDoc.setHighestXRefObjectNumber(number); + } } /** diff --git a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDPageTree.java b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDPageTree.java index 522cb6cb407def64f29a34c240b72514cb5cadfb..86396a522321d9acd885004869baf314bae43917 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDPageTree.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDPageTree.java @@ -155,8 +155,18 @@ public class PDPageTree implements COSObjectable, Iterable } else { - LOG.warn("COSDictionary expected, but got " + - (base == null ? "null" : base.getClass().getSimpleName())); + if (base == null) + { + LOG.warn("replaced null entry with an empty page"); + COSDictionary emptyPage = new COSDictionary(); + emptyPage.setItem(COSName.TYPE, COSName.PAGE); + kids.set(i, emptyPage); + result.add(emptyPage); + } + else + { + LOG.warn("COSDictionary expected, but got " + base.getClass().getSimpleName()); + } } } diff --git a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java index 9d4a02068cf31bc9ba7399209bb657ee046191b3..6e1acdb9bd9df59e09893a38f64b4c703c007f50 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityHandler.java @@ -564,7 +564,11 @@ public abstract class SecurityHandler { return; } - byte[] rawData = IOUtils.toByteArray(stream.createRawInputStream()); + byte[] rawData; + try (InputStream is = stream.createRawInputStream()) + { + rawData = IOUtils.toByteArray(is); + } ByteArrayInputStream encryptedStream = new ByteArrayInputStream(rawData); try (OutputStream output = stream.createRawOutputStream()) { diff --git a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityProvider.java b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityProvider.java index 8492c08461fb6c1f34a82bcbe5c444864d89faae..6478570b4c911defbb1ac16172ccfaa1ce81f661 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityProvider.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/SecurityProvider.java @@ -17,9 +17,10 @@ package org.apache.pdfbox.pdmodel.encryption; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; import java.security.Provider; +import org.bouncycastle.jce.provider.BouncyCastleProvider; + /** * Singleton which provides a security provider. * @@ -44,18 +45,7 @@ public class SecurityProvider // TODO synchronize access if (provider == null) { - try - { - Class providerClass = (Class) Class - .forName("org.bouncycastle.jce.provider.BouncyCastleProvider"); - provider = providerClass.getDeclaredConstructor().newInstance(); - } - catch (ClassNotFoundException | InstantiationException | IllegalAccessException | - NoSuchMethodException | SecurityException | IllegalArgumentException | - InvocationTargetException ex) - { - throw new IOException(ex); - } + provider = new BouncyCastleProvider(); } return provider; } diff --git a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/StandardSecurityHandler.java b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/StandardSecurityHandler.java index 8e37eb34e26f8b2394619654a88487f428a95628..4b849c840337b09f83935259dd60a9fb5bbe150b 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/StandardSecurityHandler.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/StandardSecurityHandler.java @@ -53,6 +53,12 @@ public final class StandardSecurityHandler extends SecurityHandler= 4) { + if (encryption.getVersion() >= REVISION_4) { setStreamFilterName(encryption.getStreamFilterName()); setStringFilterName(encryption.getStringFilterName()); } @@ -164,7 +170,7 @@ public final class StandardSecurityHandler extends SecurityHandler=0; i-- ) + byte[] iterationKey = new byte[rc4Key.length]; + byte[] otemp = new byte[owner.length]; + System.arraycopy(owner, 0, otemp, 0, owner.length); + + for (int i = 19; i >= 0; i--) { - System.arraycopy( rc4Key, 0, iterationKey, 0, rc4Key.length ); - for( int j=0; j< iterationKey.length; j++ ) + System.arraycopy(rc4Key, 0, iterationKey, 0, rc4Key.length); + for (int j = 0; j < iterationKey.length; j++) { - iterationKey[j] = (byte)(iterationKey[j] ^ (byte)i); + iterationKey[j] = (byte) (iterationKey[j] ^ (byte) i); } result.reset(); encryptDataRC4(iterationKey, otemp, result); @@ -687,7 +725,7 @@ public final class StandardSecurityHandler extends SecurityHandler= PDPanoseClassification.LENGTH ? new PDPanoseClassification(panose) : null; this.parent = parent; + this.hash = hash; + this.lastModified = lastModified; } @Override @@ -183,7 +193,7 @@ final class FileSystemFontProvider extends FontProvider @Override public String toString() { - return super.toString() + " " + file; + return super.toString() + " " + file + " " + hash + " " + lastModified; } private TrueTypeFont getTrueTypeFont(String postScriptName, File file) @@ -302,15 +312,18 @@ final class FileSystemFontProvider extends FontProvider } } - /** - * Represents ignored fonts (i.e. bitmap fonts). - */ - private static final class FSIgnored extends FSFontInfo + private FSFontInfo createFSIgnored(File file, FontFormat format, String postScriptName) { - private FSIgnored(File file, FontFormat format, String postScriptName) + String hash; + try { - super(file, format, postScriptName, null, 0, 0, 0, 0, 0, null, null); + hash = computeHash(Files.readAllBytes(file.toPath())); } + catch (IOException ex) + { + hash = ""; + } + return new FSFontInfo(file, format, postScriptName, null, 0, 0, 0, 0, 0, null, null, hash, file.lastModified()); } /** @@ -451,8 +464,8 @@ final class FileSystemFontProvider extends FontProvider if (fontInfo.cidSystemInfo != null) { writer.write(fontInfo.cidSystemInfo.getRegistry() + '-' + - fontInfo.cidSystemInfo.getOrdering() + '-' + - fontInfo.cidSystemInfo.getSupplement()); + fontInfo.cidSystemInfo.getOrdering() + '-' + + fontInfo.cidSystemInfo.getSupplement()); } writer.write("|"); if (fontInfo.usWeightClass > -1) @@ -489,6 +502,10 @@ final class FileSystemFontProvider extends FontProvider } writer.write("|"); writer.write(fontInfo.file.getAbsolutePath()); + writer.write("|"); + writer.write(fontInfo.hash); + writer.write("|"); + writer.write(Long.toString(fontInfo.file.lastModified())); writer.newLine(); } @@ -506,12 +523,12 @@ final class FileSystemFontProvider extends FontProvider List results = new ArrayList<>(); // Get the disk cache - File file = null; + File diskCacheFile = null; boolean fileExists = false; try { - file = getDiskCacheFile(); - fileExists = file.exists(); + diskCacheFile = getDiskCacheFile(); + fileExists = diskCacheFile.exists(); } catch (SecurityException e) { @@ -520,12 +537,12 @@ final class FileSystemFontProvider extends FontProvider if (fileExists) { - try (BufferedReader reader = new BufferedReader(new FileReader(file))) + try (BufferedReader reader = new BufferedReader(new FileReader(diskCacheFile))) { String line; while ((line = reader.readLine()) != null) { - String[] parts = line.split("\\|", 10); + String[] parts = line.split("\\|", 12); if (parts.length < 10) { LOG.warn("Incorrect line '" + line + "' in font disk cache is skipped"); @@ -542,6 +559,8 @@ final class FileSystemFontProvider extends FontProvider int macStyle = -1; byte[] panose = null; File fontFile; + String hash = ""; + long lastModified = 0; postScriptName = parts[0]; format = FontFormat.valueOf(parts[1]); @@ -575,12 +594,42 @@ final class FileSystemFontProvider extends FontProvider } } fontFile = new File(parts[9]); + if (parts.length >= 12 && !parts[10].isEmpty() && !parts[11].isEmpty()) + { + hash = parts[10]; + lastModified = Long.parseLong(parts[11]); + } if (fontFile.exists()) { - FSFontInfo info = new FSFontInfo(fontFile, format, postScriptName, - cidSystemInfo, usWeightClass, sFamilyClass, ulCodePageRange1, - ulCodePageRange2, macStyle, panose, this); - results.add(info); + boolean keep = false; + // if the file exists, find out whether it's the same file. + // first check whether time is different and if yes, whether hash is different + if (fontFile.lastModified() != lastModified) + { + String newHash = computeHash(Files.readAllBytes(fontFile.toPath())); + if (newHash.equals(hash)) + { + keep = true; + lastModified = fontFile.lastModified(); + hash = newHash; + } + } + else + { + keep = true; + } + if (keep) + { + FSFontInfo info = new FSFontInfo(fontFile, format, postScriptName, + cidSystemInfo, usWeightClass, sFamilyClass, ulCodePageRange1, + ulCodePageRange2, macStyle, panose, this, hash, lastModified); + results.add(info); + } + else + { + LOG.debug("Font file " + fontFile.getAbsolutePath() + " is different"); + continue; // don't remove from "pending" + } } else { @@ -599,7 +648,7 @@ final class FileSystemFontProvider extends FontProvider if (!pending.isEmpty()) { // re-build the entire cache if we encounter un-cached fonts (could be optimised) - LOG.warn("New fonts found, font cache will be re-built"); + LOG.warn(pending.size() + " new fonts found, font cache will be re-built"); return null; } @@ -626,16 +675,19 @@ final class FileSystemFontProvider extends FontProvider */ private void addTrueTypeFont(File ttfFile) throws IOException { + FontFormat fontFormat = null; try { if (ttfFile.getPath().toLowerCase().endsWith(".otf")) { + fontFormat = FontFormat.OTF; OTFParser parser = new OTFParser(false); OpenTypeFont otf = parser.parse(new RandomAccessReadBufferedFile(ttfFile)); addTrueTypeFontImpl(otf, ttfFile); } else { + fontFormat = FontFormat.TTF; TTFParser parser = new TTFParser(false); TrueTypeFont ttf = parser.parse(new RandomAccessReadBufferedFile(ttfFile)); addTrueTypeFontImpl(ttf, ttfFile); @@ -644,6 +696,7 @@ final class FileSystemFontProvider extends FontProvider catch (IOException e) { LOG.warn("Could not load font file: " + ttfFile, e); + fontInfoList.add(createFSIgnored(ttfFile, fontFormat, "*skipexception*")); } } @@ -657,7 +710,7 @@ final class FileSystemFontProvider extends FontProvider // read PostScript name, if any if (ttf.getName() != null && ttf.getName().contains("|")) { - fontInfoList.add(new FSIgnored(file, FontFormat.TTF, "*skippipeinname*")); + fontInfoList.add(createFSIgnored(file, FontFormat.TTF, "*skippipeinname*")); LOG.warn("Skipping font with '|' in name " + ttf.getName() + " in file " + file); } else if (ttf.getName() != null) @@ -665,7 +718,7 @@ final class FileSystemFontProvider extends FontProvider // ignore bitmap fonts if (ttf.getHeader() == null) { - fontInfoList.add(new FSIgnored(file, FontFormat.TTF, ttf.getName())); + fontInfoList.add(createFSIgnored(file, FontFormat.TTF, ttf.getName())); return; } int macStyle = ttf.getHeader().getMacStyle(); @@ -686,23 +739,33 @@ final class FileSystemFontProvider extends FontProvider panose = os2WindowsMetricsTable.getPanose(); } + byte[] ba; + try (InputStream is = ttf.getOriginalData()) + { + ba = IOUtils.toByteArray(is); + } + String hash = computeHash(ba); String format; - if (ttf instanceof OpenTypeFont && ((OpenTypeFont)ttf).isPostScript()) + if (ttf instanceof OpenTypeFont && ((OpenTypeFont) ttf).isPostScript()) { format = "OTF"; - CFFFont cff = ((OpenTypeFont)ttf).getCFF().getFont(); CIDSystemInfo ros = null; - if (cff instanceof CFFCIDFont) + OpenTypeFont otf = (OpenTypeFont) ttf; + if (otf.isSupportedOTF() && otf.getCFF() != null) { - CFFCIDFont cidFont = (CFFCIDFont)cff; - String registry = cidFont.getRegistry(); - String ordering = cidFont.getOrdering(); - int supplement = cidFont.getSupplement(); - ros = new CIDSystemInfo(registry, ordering, supplement); + CFFFont cff = otf.getCFF().getFont(); + if (cff instanceof CFFCIDFont) + { + CFFCIDFont cidFont = (CFFCIDFont) cff; + String registry = cidFont.getRegistry(); + String ordering = cidFont.getOrdering(); + int supplement = cidFont.getSupplement(); + ros = new CIDSystemInfo(registry, ordering, supplement); + } } fontInfoList.add(new FSFontInfo(file, FontFormat.OTF, ttf.getName(), ros, usWeightClass, sFamilyClass, ulCodePageRange1, ulCodePageRange2, - macStyle, panose, this)); + macStyle, panose, this, hash, file.lastModified())); } else { @@ -722,7 +785,7 @@ final class FileSystemFontProvider extends FontProvider format = "TTF"; fontInfoList.add(new FSFontInfo(file, FontFormat.TTF, ttf.getName(), ros, usWeightClass, sFamilyClass, ulCodePageRange1, ulCodePageRange2, - macStyle, panose, this)); + macStyle, panose, this, hash, file.lastModified())); } if (LOG.isTraceEnabled()) @@ -738,13 +801,13 @@ final class FileSystemFontProvider extends FontProvider } else { - fontInfoList.add(new FSIgnored(file, FontFormat.TTF, "*skipnoname*")); + fontInfoList.add(createFSIgnored(file, FontFormat.TTF, "*skipnoname*")); LOG.warn("Missing 'name' entry for PostScript name in font " + file); } } catch (IOException e) { - fontInfoList.add(new FSIgnored(file, FontFormat.TTF, "*skipexception*")); + fontInfoList.add(createFSIgnored(file, FontFormat.TTF, "*skipexception*")); LOG.warn("Could not load font file: " + file, e); } finally @@ -763,18 +826,19 @@ final class FileSystemFontProvider extends FontProvider Type1Font type1 = Type1Font.createWithPFB(input); if (type1.getName() == null) { - fontInfoList.add(new FSIgnored(pfbFile, FontFormat.PFB, "*skipnoname*")); + fontInfoList.add(createFSIgnored(pfbFile, FontFormat.PFB, "*skipnoname*")); LOG.warn("Missing 'name' entry for PostScript name in font " + pfbFile); return; } if (type1.getName().contains("|")) { - fontInfoList.add(new FSIgnored(pfbFile, FontFormat.PFB, "*skippipeinname*")); + fontInfoList.add(createFSIgnored(pfbFile, FontFormat.PFB, "*skippipeinname*")); LOG.warn("Skipping font with '|' in name " + type1.getName() + " in file " + pfbFile); return; } + String hash = computeHash(Files.readAllBytes(pfbFile.toPath())); fontInfoList.add(new FSFontInfo(pfbFile, FontFormat.PFB, type1.getName(), - null, -1, -1, 0, 0, -1, null, this)); + null, -1, -1, 0, 0, -1, null, this, hash, pfbFile.lastModified())); if (LOG.isTraceEnabled()) { @@ -809,4 +873,20 @@ final class FileSystemFontProvider extends FontProvider { return fontInfoList; } + + private static String computeHash(byte[] ba) + { + MessageDigest md; + try + { + md = MessageDigest.getInstance("SHA512"); + byte[] md5 = md.digest(ba); + return Hex.getString(md5); + } + catch (NoSuchAlgorithmException ex) + { + // never happens + return ""; + } + } } diff --git a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDSimpleFont.java b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDSimpleFont.java index 68294e4cd4ea77d507318cd85ef0972c7dae092f..edbb27f8226666d93e77b045e7d3ef61e5a3cab4 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDSimpleFont.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDSimpleFont.java @@ -35,6 +35,7 @@ import org.apache.pdfbox.pdmodel.font.encoding.GlyphList; import org.apache.pdfbox.pdmodel.font.encoding.MacRomanEncoding; import org.apache.pdfbox.pdmodel.font.encoding.StandardEncoding; import org.apache.pdfbox.pdmodel.font.encoding.WinAnsiEncoding; +import org.apache.pdfbox.pdmodel.font.encoding.ZapfDingbatsEncoding; /** * A simple font. Simple fonts use a PostScript encoding vector. @@ -88,11 +89,21 @@ public abstract class PDSimpleFont extends PDFont if (encodingBase instanceof COSName) { COSName encodingName = (COSName) encodingBase; - this.encoding = Encoding.getInstance(encodingName); - if (this.encoding == null) + if (FontName.ZAPF_DINGBATS.getName().equals(getName()) && !isEmbedded()) { - LOG.warn("Unknown encoding: " + encodingName.getName()); - this.encoding = readEncodingFromFont(); // fallback + // PDFBOX- and PDF.js issue 16464: ignore other encodings + // this segment will work only if readEncoding() is called after the data + // for getName() and isEmbedded() is available + this.encoding = ZapfDingbatsEncoding.INSTANCE; + } + else + { + this.encoding = Encoding.getInstance(encodingName); + if (this.encoding == null) + { + LOG.warn("Unknown encoding: " + encodingName.getName()); + this.encoding = readEncodingFromFont(); // fallback + } } } else if (encodingBase instanceof COSDictionary) diff --git a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceN.java b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceN.java index e6c6899b1b1004277380f7cca39ae01b7d30ad08..998d1db1cb986fbc5fc707658bf026808fbcff8f 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceN.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDDeviceN.java @@ -24,6 +24,7 @@ import java.awt.image.DataBuffer; import java.awt.image.Raster; import java.awt.image.WritableRaster; import java.io.IOException; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -100,10 +101,7 @@ public class PDDeviceN extends PDSpecialColorSpace // set initial color space int n = getNumberOfComponents(); float[] initial = new float[n]; - for (int i = 0; i < n; i++) - { - initial[i] = 1; - } + Arrays.fill(initial, 1); initialColor = new PDColor(initial, this); } diff --git a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDICCBased.java b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDICCBased.java index f8228ceac29f8f4e912e55dd03f0a4d9c63318b7..5ec3985b22918a804578b9150e7b548d643baeeb 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDICCBased.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDICCBased.java @@ -67,27 +67,6 @@ public final class PDICCBased extends PDCIEBasedColorSpace // reasons with LittleCMS (LCMS), see PDFBOX-4309 // WARNING: do not activate this in a conforming reader private boolean useOnlyAlternateColorSpace = false; - private static final boolean IS_KCMS; - - static - { - String cmmProperty = System.getProperty("sun.java2d.cmm"); - boolean result = false; - if ("sun.java2d.cmm.kcms.KcmsServiceProvider".equals(cmmProperty)) - { - try - { - Class.forName("sun.java2d.cmm.kcms.KcmsServiceProvider"); - result = true; - } - catch (ClassNotFoundException e) - { - // KCMS not available - } - } - // else maybe KCMS was available, but not wished - IS_KCMS = result; - } /** * Creates a new ICC color space with an empty stream. @@ -229,17 +208,12 @@ public final class PDICCBased extends PDCIEBasedColorSpace // do things that trigger a ProfileDataException // or CMMException due to invalid profiles, see PDFBOX-1295 and PDFBOX-1740 (ü-file) // or ArrayIndexOutOfBoundsException, see PDFBOX-3610 - // also triggers a ProfileDataException for PDFBOX-3549 with KCMS - /// also triggers a ProfileDataException for PDFBOX-3549 with KCMS // also triggers "CMMException: LCMS error 13" for PDFBOX-5563 with LCMS, but // calling "new ComponentColorModel" doesn't awtColorSpace.toRGB(new float[numOfComponents]); - if (!IS_KCMS) - { - // PDFBOX-4015: this one triggers "CMMException: LCMS error 13" with LCMS - new ComponentColorModel(awtColorSpace, false, false, - Transparency.OPAQUE, DataBuffer.TYPE_BYTE); - } + // PDFBOX-4015: this one triggers "CMMException: LCMS error 13" with LCMS + new ComponentColorModel(awtColorSpace, false, false, Transparency.OPAQUE, + DataBuffer.TYPE_BYTE); } } catch (ProfileDataException | CMMException | IllegalArgumentException | diff --git a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/SampledImageReader.java b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/SampledImageReader.java index 32c51331b6fa62a419e45d69362850464f07009c..9563100f78ba3da54edc83cd82d1348bbd1d4b4e 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/SampledImageReader.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/SampledImageReader.java @@ -218,7 +218,7 @@ final class SampledImageReader } return fromAny(pdImage, raster, colorKey, clipped, subsampling, width, height); } - catch (NegativeArraySizeException ex) + catch (NegativeArraySizeException | IllegalArgumentException ex) { throw new IOException(ex); } @@ -261,7 +261,7 @@ final class SampledImageReader readRasterFromAny(pdImage, raster); return raster; } - catch (NegativeArraySizeException ex) + catch (NegativeArraySizeException | IllegalArgumentException ex) { throw new IOException(ex); } diff --git a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSignature.java b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSignature.java index b7756181a103805304a6ace9544186e1bb5a7c8d..2d0e2b217e6c2220882fb884159c936746868632 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSignature.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSignature.java @@ -20,6 +20,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.Calendar; import org.apache.pdfbox.cos.COSArray; @@ -383,7 +384,7 @@ public class PDSignature implements COSObjectable } is.close(); - return COSString.parseHex(baos.toString("ISO-8859-1")).getBytes(); + return COSString.parseHex(baos.toString(StandardCharsets.ISO_8859_1.name())).getBytes(); } /** diff --git a/pdfbox/src/main/java/org/apache/pdfbox/rendering/PDFRenderer.java b/pdfbox/src/main/java/org/apache/pdfbox/rendering/PDFRenderer.java index 1c05f89b56105e08138fad736a1d3529e7c28d93..0baf678e886824e4c069fe84f5b47b6a7d617471 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/rendering/PDFRenderer.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/rendering/PDFRenderer.java @@ -24,10 +24,6 @@ import java.awt.GraphicsDevice; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.IOException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.apache.pdfbox.cos.COSName; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; @@ -48,8 +44,6 @@ import org.apache.pdfbox.pdmodel.interactive.annotation.AnnotationFilter; */ public class PDFRenderer { - private static final Log LOG = LogFactory.getLog(PDFRenderer.class); - protected final PDDocument document; // TODO keep rendering state such as caches here @@ -66,8 +60,6 @@ public class PDFRenderer private BufferedImage pageImage; - private static boolean kcmsLogged = false; - private float imageDownscalingOptimizationThreshold = 0.5f; private final PDPageTree pageTree; @@ -80,12 +72,6 @@ public class PDFRenderer { this.document = document; this.pageTree = document.getPages(); - - if (!kcmsLogged) - { - suggestKCMS(); - kcmsLogged = true; - } } /** @@ -579,56 +565,4 @@ public class PDFRenderer return pageImage; } - private static void suggestKCMS() - { - String cmmProperty = System.getProperty("sun.java2d.cmm"); - if (!"sun.java2d.cmm.kcms.KcmsServiceProvider".equals(cmmProperty)) - { - try - { - // Make sure that class exists - Class.forName("sun.java2d.cmm.kcms.KcmsServiceProvider"); - - String version = System.getProperty("java.version"); - if (version == null || - isGoodVersion(version, "1.8.0_(\\d+)", 191) || - isGoodVersion(version, "9.0.(\\d+)", 4)) - { - return; - } - LOG.info("Your current java version is: " + version); - LOG.info("To get higher rendering speed on old java 1.8 or 9 versions,"); - LOG.info(" update to the latest 1.8 or 9 version (>= 1.8.0_191 or >= 9.0.4),"); - LOG.info(" or"); - LOG.info(" use the option -Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider"); - LOG.info(" or call System.setProperty(\"sun.java2d.cmm\", \"sun.java2d.cmm.kcms.KcmsServiceProvider\")"); - } - catch (ClassNotFoundException e) - { - // KCMS not available - } - } - } - - private static boolean isGoodVersion(String version, String regex, int min) - { - Matcher matcher = Pattern.compile(regex).matcher(version); - if (matcher.matches() && matcher.groupCount() >= 1) - { - try - { - int v = Integer.parseInt(matcher.group(1)); - if (v >= min) - { - // LCMS no longer bad - return true; - } - } - catch (NumberFormatException ex) - { - return true; - } - } - return false; - } } diff --git a/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java b/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java index 636312a275870c3abde792c308cbb2e411fc36e8..492e50acef01d21d956927772ce73764753e358c 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java @@ -2033,7 +2033,7 @@ public class PageDrawer extends PDFGraphicsStreamEngine // visible if any of the entries in OCGs are OFF if (COSName.ANY_OFF.equals(visibilityPolicy)) { - return visibles.stream().noneMatch(v -> !v); + return visibles.stream().allMatch(v -> v); } // visible only if all of the entries in OCGs are ON diff --git a/pdfbox/src/main/java/org/apache/pdfbox/rendering/TilingPaint.java b/pdfbox/src/main/java/org/apache/pdfbox/rendering/TilingPaint.java index 1003a793f9986760060b68145c04b55abeb17c6f..fbb7780e7b702a54ca84e1683199c02b9279733c 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/rendering/TilingPaint.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/rendering/TilingPaint.java @@ -227,12 +227,13 @@ class TilingPaint implements Paint if (Math.abs(width * height) > MAXEDGE * MAXEDGE) { // PDFBOX-3653: prevent huge sizes - LOG.info("Pattern surface is too large, will be clipped"); - LOG.info("width: " + width + ", height: " + height); - LOG.info("XStep: " + xStep + ", YStep: " + yStep); - LOG.info("bbox: " + bbox); - LOG.info("pattern matrix: " + pattern.getMatrix()); - LOG.info("concatenated matrix: " + patternMatrix); + LOG.warn("Pattern surface larger than " + MAXEDGE + " x " + MAXEDGE + ", will be clipped"); + LOG.warn("width: " + width + ", height: " + height); + LOG.warn("XStep: " + xStep + ", YStep: " + yStep); + LOG.warn("bbox: " + bbox); + LOG.warn("pattern matrix: " + pattern.getMatrix()); + LOG.warn("concatenated matrix: " + patternMatrix); + LOG.warn("increase the property 'pdfbox.rendering.tilingpaint.maxedge'"); width = Math.min(MAXEDGE, Math.abs(width)) * Math.signum(width); height = Math.min(MAXEDGE, Math.abs(height)) * Math.signum(height); //TODO better solution needed diff --git a/pdfbox/src/test/resources/input/PDFBOX-5350-JX57O5E5YG6XM4FZABPULQGTW4OXPCWA-p1-reduced.pdf b/pdfbox/src/test/resources/input/PDFBOX-5350-JX57O5E5YG6XM4FZABPULQGTW4OXPCWA-p1-reduced.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6622c4de4958aab13030c33861187a3d57fbe99d Binary files /dev/null and b/pdfbox/src/test/resources/input/PDFBOX-5350-JX57O5E5YG6XM4FZABPULQGTW4OXPCWA-p1-reduced.pdf differ diff --git a/pdfbox/src/test/resources/input/PDFBOX-5350-JX57O5E5YG6XM4FZABPULQGTW4OXPCWA-p1-reduced.pdf-sorted.txt b/pdfbox/src/test/resources/input/PDFBOX-5350-JX57O5E5YG6XM4FZABPULQGTW4OXPCWA-p1-reduced.pdf-sorted.txt new file mode 100644 index 0000000000000000000000000000000000000000..093a892ddea1600049b49f7ad0e00f139c73a425 --- /dev/null +++ b/pdfbox/src/test/resources/input/PDFBOX-5350-JX57O5E5YG6XM4FZABPULQGTW4OXPCWA-p1-reduced.pdf-sorted.txt @@ -0,0 +1 @@ +사회복지법인 diff --git a/pdfbox/src/test/resources/input/PDFBOX-5350-JX57O5E5YG6XM4FZABPULQGTW4OXPCWA-p1-reduced.pdf.txt b/pdfbox/src/test/resources/input/PDFBOX-5350-JX57O5E5YG6XM4FZABPULQGTW4OXPCWA-p1-reduced.pdf.txt new file mode 100644 index 0000000000000000000000000000000000000000..093a892ddea1600049b49f7ad0e00f139c73a425 --- /dev/null +++ b/pdfbox/src/test/resources/input/PDFBOX-5350-JX57O5E5YG6XM4FZABPULQGTW4OXPCWA-p1-reduced.pdf.txt @@ -0,0 +1 @@ +사회복지법인 diff --git a/pom.xml b/pom.xml index 6089531e5ff5d1cfc2696603dc73d461060fd259..4839182ca4822f40f6fbc7f83968788044c7fd7b 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ org.apache.pdfbox pdfbox-parent - 3.0.0-SNAPSHOT + 3.0.1-SNAPSHOT parent/pom.xml @@ -33,13 +33,9 @@ Apache PDFBox - - scm:svn:http://svn.apache.org/repos/asf/pdfbox/trunk - - - scm:svn:https://svn.apache.org/repos/asf/pdfbox/trunk - - http://svn.apache.org/viewvc/pdfbox/trunk + cm:svn:http://svn.apache.org/repos/asf/pdfbox/branches/3.0 + scm:svn:https://svn.apache.org/repos/asf/pdfbox/branches/3.0 + http://svn.apache.org/viewvc/pdfbox/branches/3.0 @@ -93,7 +89,7 @@ maven-antrun-plugin - 1.8 + 3.1.0 @@ -107,6 +103,7 @@ + diff --git a/preflight-app/pom.xml b/preflight-app/pom.xml index 98ed06b617ea089b0eb79b53f8fee8389b319b27..c9f4958b588123aa490d16d37a1674a6b75a2eb9 100644 --- a/preflight-app/pom.xml +++ b/preflight-app/pom.xml @@ -23,7 +23,7 @@ org.apache.pdfbox pdfbox-parent - 3.0.0-SNAPSHOT + 3.0.1-SNAPSHOT ../parent/pom.xml @@ -53,7 +53,7 @@ org.bouncycastle - bcmail-jdk18on + bcpkix-jdk18on provided diff --git a/preflight/pom.xml b/preflight/pom.xml index 0a4ab6879b189d8f4330d3640e899cbf87c7ccec..aba4550b18ef8a47aab8aae8f79f6bab580cddce 100644 --- a/preflight/pom.xml +++ b/preflight/pom.xml @@ -26,7 +26,7 @@ org.apache.pdfbox pdfbox-parent - 3.0.0-SNAPSHOT + 3.0.1-SNAPSHOT ../parent/pom.xml @@ -164,21 +164,11 @@ - - org.bouncycastle - bcmail-jdk18on - true - - - org.bouncycastle - bcprov-jdk18on - true - - - org.apache.pdfbox - jbig2-imageio - test - + + org.apache.pdfbox + jbig2-imageio + test +
diff --git a/tools/pom.xml b/tools/pom.xml index 054c023d48bf684bc2d3664738031abe437e8608..d05b1db0ae42ec66981555fd53d8958d9e156828 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -23,7 +23,7 @@ org.apache.pdfbox pdfbox-parent - 3.0.0-SNAPSHOT + 3.0.1-SNAPSHOT ../parent/pom.xml @@ -38,11 +38,6 @@ 2002 - - org.bouncycastle - bcmail-jdk18on - true - ${project.groupId} pdfbox-debugger diff --git a/tools/src/main/java/org/apache/pdfbox/tools/DecompressObjectstreams.java b/tools/src/main/java/org/apache/pdfbox/tools/DecompressObjectstreams.java index 3fb316bfd3b009d2727189c0ebae4e082ef47075..f1c9fdd8ca9f933d506a8d7476bae756ef99d787 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/DecompressObjectstreams.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/DecompressObjectstreams.java @@ -41,7 +41,7 @@ public final class DecompressObjectstreams implements Callable { // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; @Option(names = {"-h", "--help"}, usageHelp = true, description = "display this help message") boolean usageHelpRequested; @@ -53,10 +53,11 @@ public final class DecompressObjectstreams implements Callable private File outfile; /** - * private constructor. + * Constructor. */ - private DecompressObjectstreams() + public DecompressObjectstreams() { + SYSERR = System.err; } /** diff --git a/tools/src/main/java/org/apache/pdfbox/tools/Decrypt.java b/tools/src/main/java/org/apache/pdfbox/tools/Decrypt.java index ae74b39380b379ef59642af621dac64b114130aa..2be636496fd07e1506fb376080af19fef4fe0144 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/Decrypt.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/Decrypt.java @@ -48,7 +48,7 @@ public final class Decrypt implements Callable { // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; @Option(names = "-alias", description = "the alias to the certificate in the keystore.") private String alias; @@ -66,6 +66,14 @@ public final class Decrypt implements Callable @Option(names = {"-o", "--output"}, description = "the decrypted PDF file. If omitted the original file is overwritten.") private File outfile; + /** + * Constructor. + */ + public Decrypt() + { + SYSERR = System.err; + } + /** * This is the entry point for the application. * diff --git a/tools/src/main/java/org/apache/pdfbox/tools/Encrypt.java b/tools/src/main/java/org/apache/pdfbox/tools/Encrypt.java index 2330d5e1502f26ccd7aa0cd963b9af831eca186a..9aff7663156f0b04453e1b6f55bca74c93f120e6 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/Encrypt.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/Encrypt.java @@ -59,7 +59,7 @@ public final class Encrypt implements Callable { // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; @Option(names = "-O", description = "set the owner password (ignored if certFile is set)", arity = "0..1", interactive = true) private String ownerPassword; @@ -103,6 +103,14 @@ public final class Encrypt implements Callable @Option(names = {"-o", "--output"}, description = "the encrypted PDF file. If omitted the original file is overwritten.") private File outfile; + /** + * Constructor. + */ + public Encrypt() + { + SYSERR = System.err; + } + /** * This is the entry point for the application. * diff --git a/tools/src/main/java/org/apache/pdfbox/tools/ExportFDF.java b/tools/src/main/java/org/apache/pdfbox/tools/ExportFDF.java index d1e406e1bbe89c79b92a8f632657dec199ee04fe..2e953d52caf2e8f244943b7070f3d97b0d4d44b9 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/ExportFDF.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/ExportFDF.java @@ -41,7 +41,7 @@ public final class ExportFDF implements Callable { // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; @Option(names = {"-i", "--input"}, description = "the PDF file to export", required = true) private File infile; @@ -49,6 +49,14 @@ public final class ExportFDF implements Callable @Option(names = {"-o", "--output"}, description = "the FDF data file", required = true) private File outfile; + /** + * Constructor. + */ + public ExportFDF() + { + SYSERR = System.err; + } + /** * This is the entry point for the application. * diff --git a/tools/src/main/java/org/apache/pdfbox/tools/ExportXFDF.java b/tools/src/main/java/org/apache/pdfbox/tools/ExportXFDF.java index 6468deb6effd92955adadb64d870cd9013663bb1..fff7328f477fdeb334dd9d1f7cb359e89d22bfd6 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/ExportXFDF.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/ExportXFDF.java @@ -42,7 +42,7 @@ public final class ExportXFDF implements Callable { // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; @Option(names = {"-i", "--input"}, description = "the PDF file to export", required = true) private File infile; @@ -50,6 +50,14 @@ public final class ExportXFDF implements Callable @Option(names = {"-o", "--output"}, description = "the XFDF data file", required = true) private File outfile; + /** + * Constructor. + */ + public ExportXFDF() + { + SYSERR = System.err; + } + /** * This is the entry point for the application. * diff --git a/tools/src/main/java/org/apache/pdfbox/tools/ExtractImages.java b/tools/src/main/java/org/apache/pdfbox/tools/ExtractImages.java index 02e16287c2f3ef263bcf2536dc9a5434c7126f18..376511a53a072fa93bf4c747f6b0d1b8bebd685e 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/ExtractImages.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/ExtractImages.java @@ -72,9 +72,9 @@ public final class ExtractImages implements Callable { // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSOUT = System.out; + private final PrintStream SYSOUT; @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; private static final List JPEG = Arrays.asList( COSName.DCT_DECODE.getName(), @@ -100,6 +100,15 @@ public final class ExtractImages implements Callable private final Set seen = new HashSet<>(); private int imageCounter = 1; + /** + * Constructor. + */ + public ExtractImages() + { + SYSOUT = System.out; + SYSERR = System.err; + } + /** * Entry point for the application. * diff --git a/tools/src/main/java/org/apache/pdfbox/tools/ExtractText.java b/tools/src/main/java/org/apache/pdfbox/tools/ExtractText.java index cfddbee3489053fd2d1697832e1267d3ddd05863..37b927a4766d69f4ddd8633823a6ee50e23c6913 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/ExtractText.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/ExtractText.java @@ -67,9 +67,9 @@ public final class ExtractText implements Callable // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSOUT = System.out; + private final PrintStream SYSOUT; @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; @Option(names = "-alwaysNext", description = "Process next page (if applicable) despite IOException " + "(ignored when -html)") @@ -112,6 +112,15 @@ public final class ExtractText implements Callable @Option(names = {"-o", "--output"}, description = "the exported text file") private File outfile; + /** + * Constructor. + */ + public ExtractText() + { + SYSOUT = System.out; + SYSERR = System.err; + } + /** * Infamous main method. * diff --git a/tools/src/main/java/org/apache/pdfbox/tools/ExtractXMP.java b/tools/src/main/java/org/apache/pdfbox/tools/ExtractXMP.java index 168e23a0c3aeaf0887697b2a9cbc40d5b130c43b..acdb4d2133bc829d20073398af1ac5f758bd626e 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/ExtractXMP.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/ExtractXMP.java @@ -41,9 +41,9 @@ public class ExtractXMP implements Callable { // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSOUT = System.out; + private final PrintStream SYSOUT; @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; @CommandLine.Option(names = "-page", description = "extract the XMP information from a specific page (1 based)") private int page = 0; @@ -60,6 +60,15 @@ public class ExtractXMP implements Callable @CommandLine.Option(names = {"-o", "--output"}, description = "the exported text file") private File outfile; + /** + * Constructor. + */ + private ExtractXMP() + { + SYSOUT = System.out; + SYSERR = System.err; + } + /** * Infamous main method. * @@ -70,7 +79,7 @@ public class ExtractXMP implements Callable // suppress the Dock icon on OS X System.setProperty("apple.awt.UIElement", "true"); - int exitCode = new CommandLine(new ExtractText()).execute(args); + int exitCode = new CommandLine(new ExtractXMP()).execute(args); System.exit(exitCode); } diff --git a/tools/src/main/java/org/apache/pdfbox/tools/ImageToPDF.java b/tools/src/main/java/org/apache/pdfbox/tools/ImageToPDF.java index 1e9a8802826b84c284429670862447c459ed56c7..c65a012a984a9613780ccb7df92e018d28504ff3 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/ImageToPDF.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/ImageToPDF.java @@ -41,7 +41,7 @@ public final class ImageToPDF implements Callable // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; @Option(names = "-autoOrientation", description = "set orientation depending of image proportion") private boolean autoOrientation = false; @@ -61,6 +61,14 @@ public final class ImageToPDF implements Callable @Option(names = {"-o", "--output"}, description = "the generated PDF file", required = true) private File outfile; + /** + * Constructor. + */ + public ImageToPDF() + { + SYSERR = System.err; + } + public static void main(String[] args) { // suppress the Dock icon on OS X diff --git a/tools/src/main/java/org/apache/pdfbox/tools/ImportFDF.java b/tools/src/main/java/org/apache/pdfbox/tools/ImportFDF.java index fc250b685707d506976f679b00bc064287864ac6..d807ae69eb74744e6e233cf92a5ce70541f6a022 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/ImportFDF.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/ImportFDF.java @@ -42,7 +42,7 @@ public class ImportFDF implements Callable { // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; @Option(names = {"-i", "--input"}, description = "the PDF file to import to", required = true) private File infile; @@ -77,8 +77,15 @@ public class ImportFDF implements Callable } /** - * This will import an fdf document and write out another pdf. - *
+ * Constructor. + */ + public ImportFDF() + { + SYSERR = System.err; + } + + /** + * This will import an fdf document and write out another pdf.
* see usage() for commandline * * @param args command line arguments diff --git a/tools/src/main/java/org/apache/pdfbox/tools/ImportXFDF.java b/tools/src/main/java/org/apache/pdfbox/tools/ImportXFDF.java index a537a354d60dd8515a9f613d41815446fc420a3a..0d1f3fd9674fd5419485c8d6f32851161d8d6c1e 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/ImportXFDF.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/ImportXFDF.java @@ -43,7 +43,7 @@ public class ImportXFDF implements Callable { // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; @Option(names = {"-i", "--input"}, description = "the PDF file to import to", required = true) private File infile; @@ -72,8 +72,15 @@ public class ImportXFDF implements Callable } /** - * This will import an fdf document and write out another pdf. - *
+ * Constructor. + */ + public ImportXFDF() + { + SYSERR = System.err; + } + + /** + * This will import an fdf document and write out another pdf.
* see usage() for commandline * * @param args command line arguments @@ -89,7 +96,7 @@ public class ImportXFDF implements Callable public Integer call() { - ImportFDF importer = new ImportFDF(); + ImportXFDF importer = new ImportXFDF(); try (PDDocument pdf = Loader.loadPDF(infile); FDFDocument fdf = Loader.loadXFDF(xfdffile)) { diff --git a/tools/src/main/java/org/apache/pdfbox/tools/OverlayPDF.java b/tools/src/main/java/org/apache/pdfbox/tools/OverlayPDF.java index 69b3b3581aad6e0292f271001ccd0c44bc2faa43..50eddfaf2616fef7355ba4c1c7646ac13256d749 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/OverlayPDF.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/OverlayPDF.java @@ -43,7 +43,7 @@ public final class OverlayPDF implements Callable { // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; @Option(names = "-odd", description = "overlay file used for odd pages") private File oddPageOverlay; @@ -75,6 +75,14 @@ public final class OverlayPDF implements Callable @Option(names = {"-o", "--output"}, description = "the PDF output file", required = true) private File outfile; + /** + * Constructor. + */ + public OverlayPDF() + { + SYSERR = System.err; + } + /** * This will overlay a document and write out the results. * diff --git a/tools/src/main/java/org/apache/pdfbox/tools/PDFMerger.java b/tools/src/main/java/org/apache/pdfbox/tools/PDFMerger.java index bf84129c355384427f7b33825b20b55e3e52ec09..53ac7beeea054f074420a8cebdf840b3e754de8d 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/PDFMerger.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/PDFMerger.java @@ -39,7 +39,7 @@ public final class PDFMerger implements Callable { // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; @Option(names = {"-i", "--input"}, description = "the PDF files to merge.", paramLabel = "", required = true) private File[] infiles; @@ -47,6 +47,14 @@ public final class PDFMerger implements Callable @Option(names = {"-o", "--output"}, description = "the merged PDF file.", required = true) private File outfile; + /** + * Constructor. + */ + public PDFMerger() + { + SYSERR = System.err; + } + /** * Infamous main method. * diff --git a/tools/src/main/java/org/apache/pdfbox/tools/PDFSplit.java b/tools/src/main/java/org/apache/pdfbox/tools/PDFSplit.java index 0fe27f6011db87c943bdf1c8c3100f5d985c29e3..424805bd0d1142cd25c74fda3c442a5f0596edf9 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/PDFSplit.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/PDFSplit.java @@ -43,7 +43,7 @@ public final class PDFSplit implements Callable { // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; @Option(names = "-password", description = "the password to decrypt the document.", arity = "0..1", interactive = true) private String password; @@ -63,6 +63,14 @@ public final class PDFSplit implements Callable @Option(names = {"-i", "--input"}, description = "the PDF file to split", required = true) private File infile; + /** + * Constructor. + */ + public PDFSplit() + { + SYSERR = System.err; + } + /** * Infamous main method. * diff --git a/tools/src/main/java/org/apache/pdfbox/tools/PDFToImage.java b/tools/src/main/java/org/apache/pdfbox/tools/PDFToImage.java index 58482a7cad65ad147ba94c7c7a28686ff3639030..bf4a626ee624ef71196a6507ea4db0b4ace496e6 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/PDFToImage.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/PDFToImage.java @@ -22,7 +22,10 @@ import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io.PrintStream; +import java.util.Arrays; +import java.util.List; import java.util.concurrent.Callable; +import java.util.stream.Collectors; import javax.imageio.ImageIO; @@ -50,7 +53,7 @@ public final class PDFToImage implements Callable { // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; @Option(names = "-password", description = "the password to decrypt the document", arity = "0..1", interactive = true) private String password; @@ -92,6 +95,14 @@ public final class PDFToImage implements Callable @Option(names = {"-i", "--input"}, description = "the PDF files to convert.", required = true) private File infile; + /** + * Constructor. + */ + public PDFToImage() + { + SYSERR = System.err; + } + /** * Infamous main method. * @@ -113,9 +124,12 @@ public final class PDFToImage implements Callable outputPrefix = FilenameUtils.removeExtension(infile.getAbsolutePath()); } - if (getImageFormats().indexOf(imageFormat) == -1) + List writerFormatNames = Arrays.asList(ImageIO.getWriterFormatNames()); + if (!writerFormatNames.contains(imageFormat)) { - SYSERR.println( "Error: Invalid image format " + imageFormat + " - supported are: " + getImageFormats()); + String wfn = writerFormatNames.stream().collect(Collectors.joining(", ")); + SYSERR.println("Error: Invalid image format " + imageFormat + " - supported formats: " + + wfn); return 2; } @@ -187,24 +201,6 @@ public final class PDFToImage implements Callable return 0; } - private static String getImageFormats() - { - StringBuilder retval = new StringBuilder(); - String[] formats = ImageIO.getWriterFormatNames(); - for( int i = 0; i < formats.length; i++ ) - { - if (formats[i].equalsIgnoreCase(formats[i])) - { - retval.append( formats[i] ); - if( i + 1 < formats.length ) - { - retval.append( ", " ); - } - } - } - return retval.toString(); - } - private static void changeCropBox(PDDocument document, float a, float b, float c, float d) { for (PDPage page : document.getPages()) diff --git a/tools/src/main/java/org/apache/pdfbox/tools/PrintPDF.java b/tools/src/main/java/org/apache/pdfbox/tools/PrintPDF.java index 05f391255eb54cbb9499b9842979a06995fbb57d..b323fcaba5a5d5961ae622d9aea366af4d90f2c0 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/PrintPDF.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/PrintPDF.java @@ -85,7 +85,7 @@ public final class PrintPDF implements Callable // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; @Option(names = "-password", description = "the password to decrypt the document.", arity = "0..1", interactive = true) private String password; @@ -120,6 +120,14 @@ public final class PrintPDF implements Callable @Option(names = {"-i", "--input"}, description = "the PDF files to print.", required = true) private File infile; + /** + * Constructor. + */ + public PrintPDF() + { + SYSERR = System.err; + } + /** * Infamous main method. * @@ -312,7 +320,7 @@ public final class PrintPDF implements Callable } @Command(name = "listPrinters", description = "list available printers", helpCommand = true) - private static void showAvailablePrinters() + private void showAvailablePrinters() { SYSERR.println("Available printer names:"); PrintService[] printServices = PrinterJob.lookupPrintServices(); diff --git a/tools/src/main/java/org/apache/pdfbox/tools/TextToPDF.java b/tools/src/main/java/org/apache/pdfbox/tools/TextToPDF.java index 6d5f2a189d111f0662c7a4d4295ea3dc84748122..d166d6d84858a2cfcaa211f233ed298a54078789 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/TextToPDF.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/TextToPDF.java @@ -70,7 +70,7 @@ public class TextToPDF implements Callable // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; @Option(names = "-fontSize", description = "the size of the font to use (default: ${DEFAULT-VALUE}") private int fontSize = DEFAULT_FONT_SIZE; @@ -124,8 +124,15 @@ public class TextToPDF implements Callable } /** - * This will create a PDF document with some text in it. - *
+ * Constructor. + */ + public TextToPDF() + { + SYSERR = System.err; + } + + /** + * This will create a PDF document with some text in it.
* see usage() for commandline * * @param args Command line arguments. diff --git a/tools/src/main/java/org/apache/pdfbox/tools/Version.java b/tools/src/main/java/org/apache/pdfbox/tools/Version.java index 9b5fa849b9492122dde8efc9ffe4675ed46e37e1..2deb0fea8d4d7394d3b15a3c9b79ecd81029eba4 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/Version.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/Version.java @@ -35,7 +35,7 @@ final class Version implements Callable, IVersionProvider { // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSOUT = System.out; + private final PrintStream SYSOUT; @Spec CommandSpec spec; @@ -57,6 +57,14 @@ final class Version implements Callable, IVersionProvider } } + /** + * Constructor. + */ + public Version() + { + SYSOUT = System.out; + } + /** * This will print out the version of PDF to System.out. * diff --git a/tools/src/main/java/org/apache/pdfbox/tools/WriteDecodedDoc.java b/tools/src/main/java/org/apache/pdfbox/tools/WriteDecodedDoc.java index 2598a114d1c540cb3fb0919f1ff18b4faeee4221..3264fc6be711a0af5c630d22e5bb0e0d61170af6 100644 --- a/tools/src/main/java/org/apache/pdfbox/tools/WriteDecodedDoc.java +++ b/tools/src/main/java/org/apache/pdfbox/tools/WriteDecodedDoc.java @@ -47,7 +47,7 @@ public class WriteDecodedDoc implements Callable { // Expected for CLI app to write to System.out/System.err @SuppressWarnings("squid:S106") - private static final PrintStream SYSERR = System.err; + private final PrintStream SYSERR; @Option(names = "-password", description = "the password to decrypt the document", arity = "0..1", interactive = true) private String password; @@ -66,7 +66,7 @@ public class WriteDecodedDoc implements Callable */ public WriteDecodedDoc() { - super(); + SYSERR = System.err; } /** diff --git a/xmpbox/pom.xml b/xmpbox/pom.xml index 487c96f8d958adbd32147b521c943b1e35a9a86c..7d9b1e70a082555b536b6d4a21e0924c2e75491f 100644 --- a/xmpbox/pom.xml +++ b/xmpbox/pom.xml @@ -27,7 +27,7 @@ org.apache.pdfbox pdfbox-parent - 3.0.0-SNAPSHOT + 3.0.1-SNAPSHOT ../parent/pom.xml diff --git a/xmpbox/src/main/java/org/apache/xmpbox/schema/XMPSchemaFactory.java b/xmpbox/src/main/java/org/apache/xmpbox/schema/XMPSchemaFactory.java index 8843e393fab1a6a56fb2167c11a67598f03a80f4..9773cf6c0f4f7bd52435513cc94dca25deca1e2c 100644 --- a/xmpbox/src/main/java/org/apache/xmpbox/schema/XMPSchemaFactory.java +++ b/xmpbox/src/main/java/org/apache/xmpbox/schema/XMPSchemaFactory.java @@ -41,8 +41,6 @@ public class XMPSchemaFactory private final PropertiesDescription propDef; - private String nsName; - /** * Factory Constructor for basic known schemas * @@ -102,7 +100,7 @@ public class XMPSchemaFactory if (schemaClass == XMPSchema.class) { argsClass = new Class[] { XMPMetadata.class, String.class, String.class }; - schemaArgs = new Object[] { metadata, namespace, nsName }; + schemaArgs = new Object[] { metadata, namespace, prefix }; } else if (prefix != null && !"".equals(prefix)) { diff --git a/xmpbox/src/main/java/org/apache/xmpbox/xml/DomXmpParser.java b/xmpbox/src/main/java/org/apache/xmpbox/xml/DomXmpParser.java index 324d05b129818a741c4bdf005a85ff7ddf8c5326..707ea75cb6159e8710230add2d128151f871e477 100644 --- a/xmpbox/src/main/java/org/apache/xmpbox/xml/DomXmpParser.java +++ b/xmpbox/src/main/java/org/apache/xmpbox/xml/DomXmpParser.java @@ -227,12 +227,14 @@ public class DomXmpParser } else if (XMLConstants.XMLNS_ATTRIBUTE.equals(attr.getPrefix())) { - if (!strictParsing) + String namespace = attr.getValue(); + if (!strictParsing && !tm.isStructuredTypeNamespace(namespace)) { - // Add the schema on the fly if it can't be found + // PDFBOX-5128: Add the schema on the fly if it can't be found + // PDFBOX-5649: But only if the namespace isn't already known + // because this adds a namespace without property descriptions String prefix = attr.getLocalName(); - String namespace = attr.getValue(); - + XMPSchema schema = xmp.getSchema(namespace); if (schema == null && tm.getSchemaFactory(namespace) == null) { diff --git a/xmpbox/src/test/java/org/apache/xmpbox/xml/DomXmpParserTest.java b/xmpbox/src/test/java/org/apache/xmpbox/xml/DomXmpParserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b34b4960e2a77647f1484412996b5753acc50da8 --- /dev/null +++ b/xmpbox/src/test/java/org/apache/xmpbox/xml/DomXmpParserTest.java @@ -0,0 +1,53 @@ +/***************************************************************************** + * + * 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. + * + ****************************************************************************/ + +package org.apache.xmpbox.xml; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.xmpbox.XMPMetadata; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * + * @author Tilman Hausherr + */ +class DomXmpParserTest +{ + public DomXmpParserTest() + { + } + + @Test + void testPDFBox5649() throws IOException, XmpParsingException + { + try (InputStream fis = DomXmpParser.class.getResourceAsStream("/org/apache/xmpbox/xml/PDFBOX-5649.xml")) + { + DomXmpParser dxp = new DomXmpParser(); + dxp.setStrictParsing(false); + XMPMetadata xmp = dxp.parse(fis); + Assertions.assertNotNull(xmp); + } + } +} diff --git a/xmpbox/src/test/resources/org/apache/xmpbox/xml/PDFBOX-5649.xml b/xmpbox/src/test/resources/org/apache/xmpbox/xml/PDFBOX-5649.xml new file mode 100644 index 0000000000000000000000000000000000000000..39089521563cfce37a26dbf72524945df25fb8d4 --- /dev/null +++ b/xmpbox/src/test/resources/org/apache/xmpbox/xml/PDFBOX-5649.xml @@ -0,0 +1,55 @@ + + + + + + + application/x-indesign + + + Test Document + + + 2020-09-20T21:07:44+01:00 + 2019-11-20T21:37:24Z + 2020-09-20T21:07:44+01:00 + Adobe InDesign CC 14.0 (Windows) + xmp.iid:a3bd370c-e037-426e-bc9e-47b6f3605337 + xmp.did:a3bd370c-e037-426e-bc9e-47b6f3605337 + + + + created + xmp.iid:a3bd370c-e037-426e-bc9e-47b6f3605337 + 2019-11-20T21:37:24Z + Adobe InDesign 15.0 (Macintosh) + + + + xmp.did:226be94e-f935-4543-9173-94bb89ded271 + default + + + + \ No newline at end of file