@Override protected void write(PdfContentStreamProcessor processor, PdfLiteral operator, List<PdfObject> operands) throws IOException { String operatorString = operator.toString(); if ("gs".equals(operatorString)) { updateTransparencyFrom((PdfName) operands.get(0)); } PdfLiteral[] mapping = operatorMapping.get(operatorString); if (mapping != null) { int index = 0; if (strokingAlpha < 1) index |= 1; if (nonStrokingAlpha < 1) index |= 2; operator = mapping[index]; operands.set(operands.size() - 1, operator); } super.write(processor, operator, operands); }
/** * @see #testExtractImageLikeSteveB() */ private static List<BufferedImage> FindImages(PdfReader reader, PdfDictionary pdfPage) throws IOException { List<BufferedImage> result = new ArrayList<>(); Iterable<PdfObject> imgPdfObject = FindImageInPDFDictionary(pdfPage); for (PdfObject image : imgPdfObject) { int xrefIndex = ((PRIndirectReference)image).getNumber(); PdfObject stream = reader.getPdfObject(xrefIndex); // Exception occurs here : PdfImageObject pdfImage = new PdfImageObject((PRStream)stream); BufferedImage img = pdfImage.getBufferedImage(); // Do something with the image result.add(img); } return result; }
/** * * @param parameters * @return a map of preferences with corresponding value to be set on the documents */ private Map<PdfName, PdfObject> getConfiguredViewerPreferencesMap(ViewerPreferencesParameters parameters) { Map<PdfName, PdfObject> confPreferences = new HashMap<PdfName, PdfObject>(); if (parameters.getDirection() != null) { confPreferences.put(PdfName.DIRECTION, ViewerPreferencesUtils.getDirection(parameters.getDirection())); } if (parameters.getDuplex() != null) { confPreferences.put(PdfName.DUPLEX, ViewerPreferencesUtils.getDuplex(parameters.getDuplex())); } if (parameters.getPrintScaling() != null) { confPreferences.put(PdfName.PRINTSCALING, ViewerPreferencesUtils.getPrintScaling(parameters.getPrintScaling())); } confPreferences.put(PdfName.NONFULLSCREENPAGEMODE, ViewerPreferencesUtils.getNFSMode(parameters.getNfsMode())); Set<PdfBooleanPreference> activePref = parameters.getEnabledPreferences(); for (PdfBooleanPreference boolPref : PdfBooleanPreference.values()) { if (activePref.contains(boolPref)) { confPreferences.put(ViewerPreferencesUtils.getBooleanPreference(boolPref), PdfBoolean.PDFTRUE); } else { confPreferences.put(ViewerPreferencesUtils.getBooleanPreference(boolPref), PdfBoolean.PDFFALSE); } } return confPreferences; }
@Override protected PdfObject readPRObject() throws IOException { try { return super.readPRObject(); } catch (InvalidPdfException e) { LOGGER.error(String.format("While reading a PdfObject ignored an InvalidPdfException (%s); returning PdfNull.", e.getMessage()), e); return PdfNull.PDFNULL; } }
@Override public void invoke(PdfContentStreamProcessor processor, PdfLiteral operator, ArrayList<PdfObject> operands) throws Exception { if (originalOperator != null && !"Do".equals(operator.toString())) { originalOperator.invoke(processor, operator, operands); } write(processor, operator, operands); }
/** * <p> * A primitive attempt at copying links from page <code>sourcePage</code> * of <code>PdfReader reader</code> to page <code>targetPage</code> of * <code>PdfStamper stamper</code>. * </p> * <p> * This method is meant only for the use case at hand, i.e. copying a link * to an external URI without expecting any advanced features. * </p> */ void copyLinks(PdfStamper stamper, int targetPage, PdfReader reader, int sourcePage) { PdfDictionary sourcePageDict = reader.getPageNRelease(sourcePage); PdfArray annotations = sourcePageDict.getAsArray(PdfName.ANNOTS); if (annotations != null && annotations.size() > 0) { for (PdfObject annotationObject : annotations) { annotationObject = PdfReader.getPdfObject(annotationObject); if (!annotationObject.isDictionary()) continue; PdfDictionary annotation = (PdfDictionary) annotationObject; if (!PdfName.LINK.equals(annotation.getAsName(PdfName.SUBTYPE))) continue; PdfArray rectArray = annotation.getAsArray(PdfName.RECT); if (rectArray == null || rectArray.size() < 4) continue; Rectangle rectangle = PdfReader.getNormalizedRectangle(rectArray); PdfName hightLight = annotation.getAsName(PdfName.H); if (hightLight == null) hightLight = PdfAnnotation.HIGHLIGHT_INVERT; PdfDictionary actionDict = annotation.getAsDict(PdfName.A); if (actionDict == null || !PdfName.URI.equals(actionDict.getAsName(PdfName.S))) continue; PdfString urlPdfString = actionDict.getAsString(PdfName.URI); if (urlPdfString == null) continue; PdfAction action = new PdfAction(urlPdfString.toString()); PdfAnnotation link = PdfAnnotation.createLink(stamper.getWriter(), rectangle, hightLight, action); stamper.addAnnotation(link, targetPage); } } }
/** * <a href="http://stackoverflow.com/questions/31402602/how-to-rename-only-the-first-found-duplicate-acrofield-in-pdf"> * How to rename only the first found duplicate acrofield in pdf? * </a> * <br> * <a href="http://s000.tinyupload.com/index.php?file_id=34970992934525199618"> * test_duplicate_field2.pdf * </a> * <p> * Demonstration of how to transform generate a new field for a widget. * </p> */ @Test public void testWidgetToField() throws IOException, DocumentException { try ( InputStream resource = getClass().getResourceAsStream("test_duplicate_field2.pdf"); OutputStream result = new FileOutputStream(new File(RESULT_FOLDER, "test_duplicate_field2-widgetToField.pdf")) ) { PdfReader reader = new PdfReader(resource); PdfDictionary form = reader.getCatalog().getAsDict(PdfName.ACROFORM); PdfArray fields = form.getAsArray(PdfName.FIELDS); for (PdfObject object: fields) { PdfDictionary field = (PdfDictionary) PdfReader.getPdfObject(object); if ("Text1".equals(field.getAsString(PdfName.T).toString())) { PdfDictionary newField = new PdfDictionary(); PRIndirectReference newFieldRef = reader.addPdfObject(newField); fields.add(newFieldRef); newField.putAll(field); newField.put(PdfName.T, new PdfString("foobar")); PdfArray newKids = new PdfArray(); newField.put(PdfName.KIDS, newKids); PdfArray kids = field.getAsArray(PdfName.KIDS); PdfObject widget = kids.remove(0); newKids.add(widget); PdfDictionary widgetDict = (PdfDictionary) PdfReader.getPdfObject(widget); widgetDict.put(PdfName.PARENT, newFieldRef); break; } } PdfStamper stamper = new PdfStamper(reader, result); stamper.close(); } }
/** * <a href="http://stackoverflow.com/questions/37275267/how-to-make-pdf-annotation-as-read-only-using-itext"> * how to make pdf annotation as read only using itext? * </a> * <br/> * test-annotated.pdf <i>simple PDF with sticky note</i> * * <p> * This test shows how to set the read-only flags of all annotations of a document. * </p> */ @Test public void testMarkAnnotationsReadOnly() throws IOException, DocumentException { try ( InputStream resourceStream = getClass().getResourceAsStream("test-annotated.pdf"); OutputStream outputStream = new FileOutputStream(new File(RESULT_FOLDER, "test-annotated-ro.pdf")) ) { PdfReader reader = new PdfReader(resourceStream); PdfStamper stamper = new PdfStamper(reader, outputStream); for (int page = 1; page <= reader.getNumberOfPages(); page++) { PdfDictionary pageDictionary = reader.getPageN(page); PdfArray annotationArray = pageDictionary.getAsArray(PdfName.ANNOTS); if (annotationArray == null) continue; for (PdfObject object : annotationArray) { PdfObject directObject = PdfReader.getPdfObject(object); if (directObject instanceof PdfDictionary) { PdfDictionary annotationDictionary = (PdfDictionary) directObject; PdfNumber flagsNumber = annotationDictionary.getAsNumber(PdfName.F); int flags = flagsNumber != null ? flagsNumber.intValue() : 0; flags |= PdfAnnotation.FLAGS_READONLY; annotationDictionary.put(PdfName.F, new PdfNumber(flags)); } } } stamper.close(); } }
/** * <a href="http://stackoverflow.com/questions/38498431/how-to-remove-filtered-content-from-a-pdf-with-itext"> * How to remove filtered content from a PDF with iText * </a> * <br/> * <a href="https://1drv.ms/b/s!AmNST-TRoPSemi2k0UnGFsjQM1Yt"> * document.pdf * </a> * <p> * This test shows how to remove text matching the filter condition given * by the OP, i.e. any text drawn using a font whose name ends with "BoldMT". * </p> * <p> * This works well, too good actually, as some table headers also use a * "BoldMT" font and, therefore, also vanish. As an alternative look at * {@link #testRemoveBigTextDocument()} which simply uses the font size * as filter condition. * </p> */ @Test public void testRemoveBoldMTTextDocument() throws IOException, DocumentException { try ( InputStream resource = getClass().getResourceAsStream("document.pdf"); OutputStream result = new FileOutputStream(new File(RESULT_FOLDER, "document-noBoldMTText.pdf"))) { PdfReader pdfReader = new PdfReader(resource); PdfStamper pdfStamper = new PdfStamper(pdfReader, result); PdfContentStreamEditor editor = new PdfContentStreamEditor() { @Override protected void write(PdfContentStreamProcessor processor, PdfLiteral operator, List<PdfObject> operands) throws IOException { String operatorString = operator.toString(); if (TEXT_SHOWING_OPERATORS.contains(operatorString)) { if (gs().getFont().getPostscriptFontName().endsWith("BoldMT")) return; } super.write(processor, operator, operands); } final List<String> TEXT_SHOWING_OPERATORS = Arrays.asList("Tj", "'", "\"", "TJ"); }; for (int i = 1; i <= pdfReader.getNumberOfPages(); i++) { editor.editPage(pdfStamper, i); } pdfStamper.close(); } }
/** * <a href="http://stackoverflow.com/questions/38498431/how-to-remove-filtered-content-from-a-pdf-with-itext"> * How to remove filtered content from a PDF with iText * </a> * <br/> * <a href="https://1drv.ms/b/s!AmNST-TRoPSemi2k0UnGFsjQM1Yt"> * document.pdf * </a> * <p> * This test shows how to remove text filtered by font size. The filter * condition given by the OP, i.e. any text drawn using a font whose * name ends with "BoldMT", had turned out to match more often than * desired, cf. {@link #testRemoveBoldMTTextDocument()}. * </p> */ @Test public void testRemoveBigTextDocument() throws IOException, DocumentException { try ( InputStream resource = getClass().getResourceAsStream("document.pdf"); OutputStream result = new FileOutputStream(new File(RESULT_FOLDER, "document-noBigText.pdf"))) { PdfReader pdfReader = new PdfReader(resource); PdfStamper pdfStamper = new PdfStamper(pdfReader, result); PdfContentStreamEditor editor = new PdfContentStreamEditor() { @Override protected void write(PdfContentStreamProcessor processor, PdfLiteral operator, List<PdfObject> operands) throws IOException { String operatorString = operator.toString(); if (TEXT_SHOWING_OPERATORS.contains(operatorString)) { if (gs().getFontSize() > 100) return; } super.write(processor, operator, operands); } final List<String> TEXT_SHOWING_OPERATORS = Arrays.asList("Tj", "'", "\"", "TJ"); }; for (int i = 1; i <= pdfReader.getNumberOfPages(); i++) { editor.editPage(pdfStamper, i); } pdfStamper.close(); } }
/** * This method checks the signatures referenced from the AcroForm Fields. */ void verify(PdfReader reader) throws GeneralSecurityException { PdfDictionary top = (PdfDictionary)PdfReader.getPdfObjectRelease(reader.getCatalog().get(PdfName.ACROFORM)); if (top == null) { System.out.println("No AcroForm, so nothing to verify"); return; } PdfArray arrfds = (PdfArray)PdfReader.getPdfObjectRelease(top.get(PdfName.FIELDS)); if (arrfds == null || arrfds.isEmpty()) { System.out.println("No AcroForm Fields, so nothing to verify"); return; } for (PdfObject object : arrfds) { object = PdfReader.getPdfObject(object); if (object == null) { System.out.println("* A null entry."); } else if (!object.isDictionary()) { System.out.println("* A non-dictionary entry."); } else { verify(reader, (PdfDictionary) object, null, null, null, false); } } }
public void before(ViewerPreferencesParameters parameters) { totalSteps = parameters.getSourceList().size(); preferences = ViewerPreferencesUtils.getViewerPreferences(parameters.getPageMode(), parameters.getPageLayout()); configuredPreferences = getConfiguredViewerPreferencesMap(parameters); sourceOpener = new DefaultPdfSourceOpener(); if (LOG.isTraceEnabled()) { LOG.trace("The following preferences will be set on the input pdf sources:"); for (Entry<PdfName, PdfObject> entry : configuredPreferences.entrySet()) { LOG.trace("{} = {}", entry.getKey(), entry.getValue()); } LOG.trace("Page mode = {}", parameters.getPageMode()); LOG.trace("Page layout = {}", parameters.getPageLayout()); } outputWriter = OutputWriters.newMultipleOutputWriter(parameters.isOverwrite()); }
private Set<PdfDictionary> getEmbeddedFilesDictionaries(PdfReader reader) { Set<PdfDictionary> retSet = new NullSafeSet<PdfDictionary>(); PdfDictionary catalog = reader.getCatalog(); PdfDictionary names = catalog.getAsDict(PdfName.NAMES); if (names != null) { PdfDictionary embFiles = names.getAsDict(PdfName.EMBEDDEDFILES); if (embFiles != null) { HashMap<String, PdfObject> embMap = PdfNameTree.readTree(embFiles); for (PdfObject value : embMap.values()) { retSet.add((PdfDictionary) PdfReader.getPdfObject(value)); } } } return retSet; }
private Set<PdfDictionary> getFileAttachmentsDictionaries(PdfReader reader) { Set<PdfDictionary> retSet = new NullSafeSet<PdfDictionary>(); for (int k = 1; k <= reader.getNumberOfPages(); ++k) { PdfArray annots = reader.getPageN(k).getAsArray(PdfName.ANNOTS); if (annots != null) { for (PdfObject current : annots) { PdfDictionary annot = (PdfDictionary) PdfReader.getPdfObject(current); if (PdfName.FILEATTACHMENT.equals(annot.getAsName(PdfName.SUBTYPE))) { retSet.add(annot.getAsDict(PdfName.FS)); } } } } return retSet; }
boolean verify(PdfReader reader, PdfDictionary value) throws GeneralSecurityException { PdfArray byteRange = value.getAsArray(PdfName.BYTERANGE); if (byteRange == null || byteRange.isEmpty()) { System.out.printf(" Signed range: missing\n"); } else { StringBuilder builder = new StringBuilder(); builder.append(" Signed range:"); for (PdfObject arrObj: byteRange) { builder.append(' ').append(arrObj); } int byteRangeSize = byteRange.size(); if (byteRangeSize % 2 == 1) { builder.append(" (Invalid: odd number of entries)"); } else { StringBuilder interoperability = new StringBuilder(); if (byteRangeSize != 4) { interoperability.append(", not exactly one gap"); } int rangeStart = byteRange.getAsNumber(0).intValue(); if (rangeStart != 0) { interoperability.append(", first range does not start at 0"); } for (int i = 2; i < byteRangeSize; i+=2) { int lastRangeEnd = rangeStart + byteRange.getAsNumber(i-1).intValue(); rangeStart = byteRange.getAsNumber(i).intValue(); if (lastRangeEnd > rangeStart) { interoperability.append(", unordered or overlapping ranges"); break; } } if (interoperability.length() > 0) { builder.append(" (Interoperability issues").append(interoperability).append(')'); } int finalRangeEnd = byteRange.getAsNumber(byteRangeSize-2).intValue() + byteRange.getAsNumber(byteRangeSize-1).intValue(); if (finalRangeEnd == reader.getFileLength()) { builder.append(" (covers whole file)"); } else { builder.append(" (covers partial file up to ").append(finalRangeEnd).append(")"); } } System.out.println(builder); } PdfPKCS7 pkcs7 = verifySignature(reader, value, null); System.out.printf(" Validity: %s\n", pkcs7.verify()); return pkcs7 != null; }
/** * If the child of a structured element is a dictionary, we inspect the * child; we may also draw a tag. * * @param k * the child dictionary to inspect */ @Override public void inspectChildDictionary(PdfDictionary k, boolean inspectAttributes) throws IOException { if (k == null) return; PdfName s = k.getAsName(PdfName.S); if (s != null) { String tagN = PdfName.decodeName(s.toString()); String tag; if (roleMap != null && roleMap.get(new PdfName(tagN)) != null) { tag = roleMap.get(new PdfName(tagN)).toString().substring(1); } else { tag = fixTagName(tagN); } out.print("<"); out.print(tag); if (inspectAttributes) { PdfDictionary a = k.getAsDict(PdfName.A); if (a != null) { Set<PdfName> keys = a.getKeys(); for (PdfName key : keys) { out.print(' '); PdfObject value = a.get(key); value = PdfReader.getPdfObject(value); out.print(xmlName(key)); out.print("=\""); out.print(XMLUtil.escapeXML(value.toString(), false)); out.print("\""); } } } out.println(">"); PdfObject alt = k.get(PdfName.ALT); if (alt != null && alt.toString() != null) { out.print("<alt><![CDATA["); out.print(alt.toString().replaceAll("[\\000]*", "")); out.print("]]></alt>"); } PdfDictionary dict = k.getAsDict(PdfName.PG); if (dict != null) parseTag(tagN, k.getDirectObject(PdfName.K), dict); inspectChild(k.getDirectObject(PdfName.K)); out.print("</"); out.print(tag); out.println(">"); } else inspectChild(k.getDirectObject(PdfName.K)); }
/** * <p> * This method writes content stream operations to the target canvas. The default * implementation writes them as they come, so it essentially generates identical * copies of the original instructions the {@link ContentOperatorWrapper} instances * forward to it. * </p> * <p> * Override this method to achieve some fancy editing effect. * </p> */ protected void write(PdfContentStreamProcessor processor, PdfLiteral operator, List<PdfObject> operands) throws IOException { int index = 0; for (PdfObject object : operands) { object.toPdf(canvas.getPdfWriter(), canvas.getInternalBuffer()); canvas.getInternalBuffer().append(operands.size() > ++index ? (byte) ' ' : (byte) '\n'); } }
/** * adds the viewer preferences to the stamper * * @see PdfStamper#addViewerPreference(PdfName, PdfObject) * @param preferences * a map of preferences with corresponding value to be set on the documents */ public void addViewerPreferences(Map<PdfName, PdfObject> preferences) { for (Entry<PdfName, PdfObject> entry : preferences.entrySet()) { stamper.addViewerPreference(entry.getKey(), entry.getValue()); } }