示例#1
0
 /**
  * This will return a list of signature fields.
  *
  * @param onlyEmptyFields only empty signature fields will be returned
  * @return list of signature dictionaries as COSDictionary
  * @throws IOException if no document catalog can be found
  */
 public List<COSDictionary> getSignatureFields(boolean onlyEmptyFields) throws IOException {
   COSObject documentCatalog = getCatalog();
   if (documentCatalog != null) {
     COSDictionary acroForm =
         (COSDictionary) documentCatalog.getDictionaryObject(COSName.ACRO_FORM);
     if (acroForm != null) {
       COSArray fields = (COSArray) acroForm.getDictionaryObject(COSName.FIELDS);
       if (fields != null) {
         // Some fields may contain twice references to a single field.
         // This will prevent such double entries.
         HashMap<COSObjectKey, COSDictionary> signatures =
             new HashMap<COSObjectKey, COSDictionary>();
         for (Object object : fields) {
           COSObject dict = (COSObject) object;
           if (COSName.SIG.equals(dict.getItem(COSName.FT))) {
             COSBase dictionaryObject = dict.getDictionaryObject(COSName.V);
             if (dictionaryObject == null || (dictionaryObject != null && !onlyEmptyFields)) {
               signatures.put(new COSObjectKey(dict), (COSDictionary) dict.getObject());
             }
           }
         }
         return new LinkedList<COSDictionary>(signatures.values());
       }
     }
   }
   return Collections.emptyList();
 }
 /**
  * This method checks the AP entry of the Annotation Dictionary. If the AP key is missing, this
  * method returns true. If the AP key exists, only the N entry is authorized and must be a Stream
  * which define the appearance of the annotation. (Currently, only the type of the N entry is
  * checked because of the Appearance stream is a Form XObject, so it will be checked by the
  * Graphics Helper)
  *
  * <p>If the AP content isn't valid, this method return false and updates the errors list.
  *
  * @param errors list of errors which is updated if validation fails
  * @return
  */
 protected boolean checkAP(List<ValidationError> errors) {
   PDAppearanceDictionary ap = this.pdAnnot.getAppearance();
   if (ap != null) {
     COSDictionary apDict = ap.getDictionary();
     // ---- Only N entry is authorized
     if (apDict.getItem(COSName.getPDFName(ANNOT_DICTIONARY_KEY_D)) != null
         || apDict.getItem(COSName.getPDFName(ANNOT_DICTIONARY_KEY_R)) != null) {
       errors.add(
           new ValidationResult.ValidationError(
               ValidationConstants.ERROR_ANNOT_INVALID_AP_CONTENT,
               "Only the N Appearance is authorized"));
       return false;
     } else if (apDict.getItem(COSName.getPDFName(ANNOT_DICTIONARY_KEY_N)) == null) {
       // ---- N entry is required
       errors.add(
           new ValidationResult.ValidationError(
               ValidationConstants.ERROR_ANNOT_MISSING_AP_N_CONTENT,
               "The N Appearance must be present"));
       return false;
     } else {
       // ---- the N entry must be a Stream (Dictionaries are forbidden)
       COSBase apn = apDict.getItem(COSName.getPDFName(ANNOT_DICTIONARY_KEY_N));
       if (!COSUtils.isStream(apn, this.cosDoc)) {
         errors.add(
             new ValidationResult.ValidationError(
                 ValidationConstants.ERROR_ANNOT_INVALID_AP_CONTENT,
                 "The N Appearance must be a Stream"));
         return false;
       }
     }
   } // else  ok, nothing to check,this field is optional
   return true;
 }
示例#3
0
  public Map<String, Image> getImages() {
    Map<String, Image> images = new HashMap<String, Image>();
    COSDictionary xobjectsDictionary =
        (COSDictionary) getDictionary().getDictionaryObject(COSName.XOBJECT);
    if (xobjectsDictionary == null) {
      return images;
    }

    for (COSName objName : xobjectsDictionary.keySet()) {
      try {
        COSBase xobject = xobjectsDictionary.getDictionaryObject(objName);
        if (xobject instanceof COSStream) {
          COSStream xstream = (COSStream) xobject;
          String subtype = xstream.getNameAsString(COSName.SUBTYPE);
          if (!subtype.equals("Image")) {
            continue;
          }

          PDFunction tintTransformer = getTintTransformer(xstream);

          PDStream pdstream = new PDStream(xstream);
          byte[] data = getStreamData(pdstream);
          Image image = processStream(data, tintTransformer);
          if (image != null) {
            images.put(objName.getName(), image);
          }
        }
      } catch (Exception e) {
        LOG.error("error while creating a image", e);
      }
    }

    return images;
  }
示例#4
0
 /**
  * This will close all storage and delete the tmp files.
  *
  * @throws IOException If there is an error close resources.
  */
 public void close() throws IOException {
   if (!closed) {
     scratchFile.close();
     if (tmpFile != null) {
       tmpFile.delete();
     }
     if (trailer != null) {
       trailer.clear();
       trailer = null;
     }
     // Clear object pool
     for (COSObject object : objectPool.values()) {
       COSBase cosObject = object.getObject();
       // clear the resources of the pooled objects
       if (cosObject instanceof COSStream) {
         ((COSStream) cosObject).close();
       } else if (cosObject instanceof COSDictionary) {
         ((COSDictionary) cosObject).clear();
       } else if (cosObject instanceof COSArray) {
         ((COSArray) cosObject).clear();
       }
       // TODO are there other kind of COSObjects to be cleared?
     }
     objectPool.clear();
     closed = true;
   }
 }
 private InfoDictionaryImpl getInfo() {
   COSDictionary trailer = this.document.getDocument().getTrailer();
   COSBase infoDict = trailer.getDictionaryObject(COSName.INFO);
   return !(infoDict instanceof COSDictionary)
       ? null
       : new InfoDictionaryImpl(new PDDocumentInformation((COSDictionary) infoDict));
 }
示例#6
0
  private void writeColorSpace(PDColorSpace colorSpace) throws IOException {
    COSName key = null;
    if (colorSpace instanceof PDDeviceGray
        || colorSpace instanceof PDDeviceRGB
        || colorSpace instanceof PDDeviceCMYK) {
      key = COSName.getPDFName(colorSpace.getName());
    } else {
      COSDictionary colorSpaces =
          (COSDictionary) resources.getCOSDictionary().getDictionaryObject(COSName.COLORSPACE);
      if (colorSpaces == null) {
        colorSpaces = new COSDictionary();
        resources.getCOSDictionary().setItem(COSName.COLORSPACE, colorSpaces);
      }
      key = colorSpaces.getKeyForValue(colorSpace.getCOSObject());

      if (key == null) {
        int counter = 0;
        String csName = "CS";
        while (colorSpaces.containsValue(csName + counter)) {
          counter++;
        }
        key = COSName.getPDFName(csName + counter);
        colorSpaces.setItem(key, colorSpace);
      }
    }
    key.writePDF(output);
    appendRawCommands(SPACE);
  }
示例#7
0
 /**
  * This is a convenience method that will convert the value to a COSInteger object.
  *
  * @param embeddedDictionary The embedded dictionary.
  * @param key The key to the object,
  * @param value The int value for the name.
  */
 public void setEmbeddedInt(String embeddedDictionary, COSName key, int value) {
   COSDictionary embedded = (COSDictionary) getDictionaryObject(embeddedDictionary);
   if (embedded == null) {
     embedded = new COSDictionary();
     setItem(embeddedDictionary, embedded);
   }
   embedded.setInt(key, value);
 }
示例#8
0
 /**
  * This is a convenience method that will get the dictionary object that is expected to be a name
  * and convert it to a string. Null is returned if the entry does not exist in the dictionary.
  *
  * @param embedded The embedded dictionary.
  * @param key The key to the item in the dictionary.
  * @param defaultValue The default value to return.
  * @return The name converted to a string.
  */
 public String getEmbeddedString(String embedded, COSName key, String defaultValue) {
   String retval = defaultValue;
   COSDictionary dic = (COSDictionary) getDictionaryObject(embedded);
   if (dic != null) {
     retval = dic.getString(key, defaultValue);
   }
   return retval;
 }
示例#9
0
 /**
  * Get an integer from an embedded dictionary. Useful for 1-1 mappings.
  *
  * @param embeddedDictionary The name of the embedded dictionary.
  * @param key The key in the embedded dictionary.
  * @param defaultValue The value if there is no embedded dictionary or it does not contain the
  *     key.
  * @return The value of the embedded integer.
  */
 public int getEmbeddedInt(String embeddedDictionary, COSName key, int defaultValue) {
   int retval = defaultValue;
   COSDictionary embedded = (COSDictionary) getDictionaryObject(embeddedDictionary);
   if (embedded != null) {
     retval = embedded.getInt(key, defaultValue);
   }
   return retval;
 }
示例#10
0
 /**
  * This is a convenience method that will get the dictionary object that is expected to be a date.
  * Null is returned if the entry does not exist in the dictionary.
  *
  * @param embedded The embedded dictionary to get.
  * @param key The key to the item in the dictionary.
  * @param defaultValue The default value to return.
  * @return The name converted to a string.
  * @throws IOException If there is an error converting to a date.
  */
 public Calendar getEmbeddedDate(String embedded, COSName key, Calendar defaultValue)
     throws IOException {
   Calendar retval = defaultValue;
   COSDictionary eDic = (COSDictionary) getDictionaryObject(embedded);
   if (eDic != null) {
     retval = eDic.getDate(key, defaultValue);
   }
   return retval;
 }
示例#11
0
 /**
  * Returns the given attribute, inheriting from parent nodes if necessary.
  *
  * @param key the key to look up
  * @return COS value for the given key
  */
 protected COSBase getInheritableAttribute(COSName key) {
   if (dictionary.containsKey(key)) {
     return dictionary.getDictionaryObject(key);
   } else if (parent != null) {
     return parent.getInheritableAttribute(key);
   } else {
     return acroForm.getCOSObject().getDictionaryObject(key);
   }
 }
 /** true if catalog contain OCProperties key */
 @Override
 public Boolean getisOptionalContentPresent() {
   try {
     COSDictionary root = (COSDictionary) ((COSDocument) baseObject).getCatalog().getObject();
     return Boolean.valueOf(root.getItem(COSName.OCPROPERTIES) != null);
   } catch (IOException e) {
     return Boolean.FALSE;
   }
 }
示例#13
0
 /**
  * Set the date object.
  *
  * @param embedded The embedded dictionary.
  * @param key The key to the date.
  * @param date The date to set.
  */
 public void setEmbeddedDate(String embedded, COSName key, Calendar date) {
   COSDictionary dic = (COSDictionary) getDictionaryObject(embedded);
   if (dic == null && date != null) {
     dic = new COSDictionary();
     setItem(embedded, dic);
   }
   if (dic != null) {
     dic.setDate(key, date);
   }
 }
 public COSBase getCOSObject() {
   COSDictionary dict = new COSDictionary();
   COSArray arr = new COSArray();
   for (Entry<Integer, PDPageLabelRange> i : labels.entrySet()) {
     arr.add(COSInteger.get(i.getKey()));
     arr.add(i.getValue());
   }
   dict.setItem(COSName.NUMS, arr);
   return dict;
 }
示例#15
0
 /**
  * This is a convenience method that will convert the value to a COSString object. If it is null
  * then the object will be removed.
  *
  * @param embedded The embedded dictionary to set the item in.
  * @param key The key to the object,
  * @param value The string value for the name.
  */
 public void setEmbeddedString(String embedded, COSName key, String value) {
   COSDictionary dic = (COSDictionary) getDictionaryObject(embedded);
   if (dic == null && value != null) {
     dic = new COSDictionary();
     setItem(embedded, dic);
   }
   if (dic != null) {
     dic.setString(key, value);
   }
 }
示例#16
0
 /**
  * This will return a list of signature dictionaries as COSDictionary.
  *
  * @return list of signature dictionaries as COSDictionary
  * @throws IOException if no document catalog can be found
  */
 public List<COSDictionary> getSignatureDictionaries() throws IOException {
   List<COSDictionary> signatureFields = getSignatureFields(false);
   List<COSDictionary> signatures = new LinkedList<COSDictionary>();
   for (COSDictionary dict : signatureFields) {
     COSBase dictionaryObject = dict.getDictionaryObject(COSName.V);
     if (dictionaryObject != null) {
       signatures.add((COSDictionary) dictionaryObject);
     }
   }
   return signatures;
 }
 /**
  * Decode JBIG2 data using Java ImageIO library.
  *
  * <p>{@inheritDoc}
  */
 public void decode(
     InputStream compressedData, OutputStream result, COSDictionary options, int filterIndex)
     throws IOException {
   /**
    * A working JBIG2 ImageIO plugin is needed to decode JBIG2 encoded streams. The following is
    * known to be working. It can't be bundled with PDFBox because of an incompatible license.
    * http://code.google.com/p/jbig2-imageio/
    */
   Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("JBIG2");
   if (!readers.hasNext()) {
     LOG.error("Can't find an ImageIO plugin to decode the JBIG2 encoded datastream.");
     return;
   }
   ImageReader reader = readers.next();
   COSDictionary decodeP = (COSDictionary) options.getDictionaryObject(COSName.DECODE_PARMS);
   COSInteger bits = (COSInteger) options.getDictionaryObject(COSName.BITS_PER_COMPONENT);
   COSStream st = null;
   if (decodeP != null) {
     st = (COSStream) decodeP.getDictionaryObject(COSName.JBIG2_GLOBALS);
   }
   if (st != null) {
     reader.setInput(
         ImageIO.createImageInputStream(
             new SequenceInputStream(st.getFilteredStream(), compressedData)));
   } else {
     reader.setInput(ImageIO.createImageInputStream(compressedData));
   }
   BufferedImage bi = reader.read(0);
   reader.dispose();
   if (bi != null) {
     // I am assuming since JBIG2 is always black and white
     // depending on your renderer this might or might be needed
     if (bi.getColorModel().getPixelSize() != bits.intValue()) {
       if (bits.intValue() != 1) {
         LOG.error("Do not know how to deal with JBIG2 with more than 1 bit");
         return;
       }
       BufferedImage packedImage =
           new BufferedImage(bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
       Graphics graphics = packedImage.getGraphics();
       graphics.drawImage(bi, 0, 0, null);
       graphics.dispose();
       bi = packedImage;
     }
     DataBuffer dBuf = bi.getData().getDataBuffer();
     if (dBuf.getDataType() == DataBuffer.TYPE_BYTE) {
       result.write(((DataBufferByte) dBuf).getData());
     } else {
       LOG.error("Image data buffer not of type byte but type " + dBuf.getDataType());
     }
   } else {
     LOG.error("Something went wrong when decoding the JBIG2 encoded datastream.");
   }
 }
 /** @return list of embedded files */
 private List<Object> getEmbeddedFiles() {
   List<Object> files = new ArrayList<>();
   try {
     COSDictionary buffer = (COSDictionary) pdDocument.getDocument().getCatalog().getObject();
     buffer = getCosDictionary(buffer.getItem(COSName.NAMES));
     if (buffer != null) {
       buffer = getCosDictionary(buffer.getItem(COSName.EMBEDDED_FILES));
     }
     getNamesEmbeddedFiles(files, buffer);
   } catch (IOException e) {
     logger.error(
         "Something wrong with getting embedded files - return empty list. " + e.getMessage());
   }
   return files;
 }
 /**
  * This will set the font name.
  *
  * @param fontName The new name for the font.
  */
 public void setFontName(String fontName) {
   COSName name = null;
   if (fontName != null) {
     name = COSName.getPDFName(fontName);
   }
   dic.setItem(COSName.FONT_NAME, name);
 }
 /**
  * This will set the character set for the font.
  *
  * @param charSet The new character set for the font.
  */
 public void setCharacterSet(String charSet) {
   COSString name = null;
   if (charSet != null) {
     name = new COSString(charSet);
   }
   dic.setItem(COSName.CHAR_SET, name);
 }
 /**
  * Set the fonts bounding box.
  *
  * @param rect The new bouding box.
  */
 public void setFontBoundingBox(PDRectangle rect) {
   COSArray array = null;
   if (rect != null) {
     array = rect.getCOSArray();
   }
   dic.setItem(COSName.FONT_BBOX, array);
 }
 /**
  * This will set the font stretch.
  *
  * @param fontStretch The new stretch for the font.
  */
 public void setFontStretch(String fontStretch) {
   COSName name = null;
   if (fontStretch != null) {
     name = COSName.getPDFName(fontStretch);
   }
   dic.setItem(COSName.FONT_STRETCH, name);
 }
 /**
  * This will set the font family.
  *
  * @param fontFamily The font family.
  */
 public void setFontFamily(String fontFamily) {
   COSString name = null;
   if (fontFamily != null) {
     name = new COSString(fontFamily);
   }
   dic.setItem(COSName.FONT_FAMILY, name);
 }
 /**
  * Creates a new instance based on a given {@link COSDictionary}.
  *
  * @param dict the dictionary
  */
 public PDOptionalContentGroup(COSDictionary dict) {
   super(dict);
   if (!dict.getItem(COSName.TYPE).equals(COSName.OCG)) {
     throw new IllegalArgumentException(
         "Provided dictionary is not of type '" + COSName.OCG + "'");
   }
 }
示例#25
0
 /**
  * Get the additional actions for this field. This will return null if there are no additional
  * actions for this field.
  *
  * @return The actions of the field.
  */
 public PDFormFieldAdditionalActions getActions() {
   COSDictionary aa = (COSDictionary) dictionary.getDictionaryObject(COSName.AA);
   if (aa != null) {
     return new PDFormFieldAdditionalActions(aa);
   }
   return null;
 }
示例#26
0
 /**
  * This will find one of the child elements. The name array are the components of the name to
  * search down the tree of names. The nameIndex is where to start in that array. This method is
  * called recursively until it finds the end point based on the name array.
  *
  * @param name An array that picks the path to the field.
  * @param nameIndex The index into the array.
  * @return The field at the endpoint or null if none is found.
  */
 PDField findKid(String[] name, int nameIndex) {
   PDField retval = null;
   COSArray kids = (COSArray) dictionary.getDictionaryObject(COSName.KIDS);
   if (kids != null) {
     for (int i = 0; retval == null && i < kids.size(); i++) {
       COSDictionary kidDictionary = (COSDictionary) kids.getObject(i);
       if (name[nameIndex].equals(kidDictionary.getString(COSName.T))) {
         retval = PDField.fromDictionary(acroForm, kidDictionary, (PDNonTerminalField) this);
         if (retval != null && name.length > nameIndex + 1) {
           retval = retval.findKid(name, nameIndex + 1);
         }
       }
     }
   }
   return retval;
 }
示例#27
0
 /**
  * This will tell if this is an encrypted document.
  *
  * @return true If this document is encrypted.
  */
 public boolean isEncrypted() {
   boolean encrypted = false;
   if (trailer != null) {
     encrypted = trailer.getDictionaryObject(COSName.ENCRYPT) != null;
   }
   return encrypted;
 }
  /**
   * This method creates a COSField subclass from the given field. The field is a PDF Dictionary
   * object that must represent a field element. - othewise null is returned
   *
   * @param acroForm The form that the field will be part of.
   * @param field The dictionary representing a field element
   * @return a subclass to COSField according to the kind of field passed to createField
   * @throws IOException If there is an error determining the field type.
   */
  public static PDField createField(PDAcroForm acroForm, COSDictionary field) throws IOException {
    PDField pdField = new PDUnknownField(acroForm, field);
    if (isButton(pdField)) {
      int flags = pdField.getFieldFlags();
      // BJL, I have found that the radio flag bit is not always set
      // and that sometimes there is just a kids dictionary.
      // so, if there is a kids dictionary then it must be a radio button
      // group.
      COSArray kids = (COSArray) field.getDictionaryObject(COSName.getPDFName("Kids"));
      if (kids != null || isRadio(flags)) {
        pdField = new PDRadioCollection(acroForm, field);
      } else if (isPushButton(flags)) {
        pdField = new PDPushButton(acroForm, field);
      } else {
        pdField = new PDCheckbox(acroForm, field);
      }

    } else if (isChoiceField(pdField)) {
      pdField = new PDChoiceField(acroForm, field);
    } else if (isTextbox(pdField)) {
      pdField = new PDTextbox(acroForm, field);
    } else if (isSignature(pdField)) {
      pdField = new PDSignatureField(acroForm, field);
    } else {
      // do nothing and return an unknown field type.
    }
    return pdField;
  }
示例#29
0
 /**
  * This will add all of the dictionarys keys/values to this dictionary, but only if they don't
  * already exist. If a key already exists in this dictionary then nothing is changed.
  *
  * @param dic The dic to get the keys from.
  */
 public void mergeInto(COSDictionary dic) {
   for (Map.Entry<COSName, COSBase> entry : dic.entrySet()) {
     if (getItem(entry.getKey()) == null) {
       setItem(entry.getKey(), entry.getValue());
     }
   }
 }
 /**
  * Get the font name.
  *
  * @return The name of the font.
  */
 public String getFontName() {
   String retval = null;
   COSName name = (COSName) dic.getDictionaryObject(COSName.FONT_NAME);
   if (name != null) {
     retval = name.getName();
   }
   return retval;
 }