📄 pdfsignatureappearance.java
字号:
return this.crlList; } /** * Gets the filter used to sign the document. * @return the filter used to sign the document */ public com.lowagie.text.pdf.PdfName getFilter() { return filter; } /** * Checks if a new field was created. * @return <CODE>true</CODE> if a new field was created, <CODE>false</CODE> if signing * an existing field or if the signature is invisible */ public boolean isNewField() { return this.newField; } /** * Gets the page number of the field. * @return the page number of the field */ public int getPage() { return page; } /** * Gets the field name. * @return the field name */ public java.lang.String getFieldName() { return fieldName; } /** * Gets the rectangle that represent the position and dimension of the signature in the page. * @return the rectangle that represent the position and dimension of the signature in the page */ public com.lowagie.text.Rectangle getPageRect() { return pageRect; } /** * Gets the signature date. * @return the signature date */ public java.util.Calendar getSignDate() { return signDate; } /** * Sets the signature date. * @param signDate the signature date */ public void setSignDate(java.util.Calendar signDate) { this.signDate = signDate; } com.lowagie.text.pdf.ByteBuffer getSigout() { return sigout; } void setSigout(com.lowagie.text.pdf.ByteBuffer sigout) { this.sigout = sigout; } java.io.OutputStream getOriginalout() { return originalout; } void setOriginalout(java.io.OutputStream originalout) { this.originalout = originalout; } /** * Gets the temporary file. * @return the temporary file or <CODE>null</CODE> is the document is created in memory */ public java.io.File getTempFile() { return tempFile; } void setTempFile(java.io.File tempFile) { this.tempFile = tempFile; } /** * Gets a new signature fied name that doesn't clash with any existing name. * @return a new signature fied name */ public String getNewSigName() { AcroFields af = writer.getAcroFields(); String name = "Signature"; int step = 0; boolean found = false; while (!found) { ++step; String n1 = name + step; if (af.getFieldItem(n1) != null) continue; n1 += "."; found = true; for (Iterator it = af.getFields().keySet().iterator(); it.hasNext();) { String fn = (String)it.next(); if (fn.startsWith(n1)) { found = false; break; } } } name += step; return name; } /** * This is the first method to be called when using external signatures. The general sequence is: * preClose(), getDocumentBytes() and close(). * <p> * If calling preClose() <B>dont't</B> call PdfStamper.close(). * <p> * No external signatures are allowed if this method is called. * @throws IOException on error * @throws DocumentException on error */ public void preClose() throws IOException, DocumentException { preClose(null); } /** * This is the first method to be called when using external signatures. The general sequence is: * preClose(), getDocumentBytes() and close(). * <p> * If calling preClose() <B>dont't</B> call PdfStamper.close(). * <p> * If using an external signature <CODE>exclusionSizes</CODE> must contain at least * the <CODE>PdfName.CONTENTS</CODE> key with the size that it will take in the * document. Note that due to the hex string coding this size should be * byte_size*2+2. * @param exclusionSizes a <CODE>HashMap</CODE> with names and sizes to be excluded in the signature * calculation. The key is a <CODE>PdfName</CODE> and the value an * <CODE>Integer</CODE>. At least the <CODE>PdfName.CONTENTS</CODE> must be present * @throws IOException on error * @throws DocumentException on error */ public void preClose(HashMap exclusionSizes) throws IOException, DocumentException { if (preClosed) throw new DocumentException("Document already pre closed."); preClosed = true; AcroFields af = writer.getAcroFields(); String name = getFieldName(); boolean fieldExists = !(isInvisible() || isNewField()); PdfIndirectReference refSig = writer.getPdfIndirectReference(); writer.setSigFlags(3); if (fieldExists) { ArrayList widgets = af.getFieldItem(name).widgets; PdfDictionary widget = (PdfDictionary)widgets.get(0); writer.markUsed(widget); widget.put(PdfName.P, writer.getPageReference(getPage())); widget.put(PdfName.V, refSig); PdfObject obj = PdfReader.getPdfObjectRelease(widget.get(PdfName.F)); int flags = 0; if (obj != null && obj.isNumber()) flags = ((PdfNumber)obj).intValue(); flags |= PdfAnnotation.FLAGS_LOCKED; widget.put(PdfName.F, new PdfNumber(flags)); PdfDictionary ap = new PdfDictionary(); ap.put(PdfName.N, getAppearance().getIndirectReference()); widget.put(PdfName.AP, ap); } else { PdfFormField sigField = PdfFormField.createSignature(writer); sigField.setFieldName(name); sigField.put(PdfName.V, refSig); sigField.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_LOCKED); int pagen = getPage(); if (!isInvisible()) sigField.setWidget(getPageRect(), null); else sigField.setWidget(new Rectangle(0, 0), null); sigField.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, getAppearance()); sigField.setPage(pagen); writer.addAnnotation(sigField, pagen); } exclusionLocations = new HashMap(); if (cryptoDictionary == null) { if (PdfName.ADOBE_PPKLITE.equals(getFilter())) sigStandard = new PdfSigGenericPKCS.PPKLite(getProvider()); else if (PdfName.ADOBE_PPKMS.equals(getFilter())) sigStandard = new PdfSigGenericPKCS.PPKMS(getProvider()); else if (PdfName.VERISIGN_PPKVS.equals(getFilter())) sigStandard = new PdfSigGenericPKCS.VeriSign(getProvider()); else throw new IllegalArgumentException("Unknown filter: " + getFilter()); sigStandard.setExternalDigest(externalDigest, externalRSAdata, digestEncryptionAlgorithm); if (getReason() != null) sigStandard.setReason(getReason()); if (getLocation() != null) sigStandard.setLocation(getLocation()); if (getContact() != null) sigStandard.setContact(getContact()); sigStandard.put(PdfName.M, new PdfDate(getSignDate())); sigStandard.setSignInfo(getPrivKey(), getCertChain(), getCrlList()); PdfString contents = (PdfString)sigStandard.get(PdfName.CONTENTS); PdfLiteral lit = new PdfLiteral((contents.toString().length() + (PdfName.ADOBE_PPKLITE.equals(getFilter())?0:64)) * 2 + 2); exclusionLocations.put(PdfName.CONTENTS, lit); sigStandard.put(PdfName.CONTENTS, lit); lit = new PdfLiteral(80); exclusionLocations.put(PdfName.BYTERANGE, lit); sigStandard.put(PdfName.BYTERANGE, lit); if (certificationLevel > 0) { addDocMDP(sigStandard); } if (signatureEvent != null) signatureEvent.getSignatureDictionary(sigStandard); writer.addToBody(sigStandard, refSig, false); } else { PdfLiteral lit = new PdfLiteral(80); exclusionLocations.put(PdfName.BYTERANGE, lit); cryptoDictionary.put(PdfName.BYTERANGE, lit); for (Iterator it = exclusionSizes.entrySet().iterator(); it.hasNext();) { Map.Entry entry = (Map.Entry)it.next(); PdfName key = (PdfName)entry.getKey(); Integer v = (Integer)entry.getValue(); lit = new PdfLiteral(v.intValue()); exclusionLocations.put(key, lit); cryptoDictionary.put(key, lit); } if (certificationLevel > 0) addDocMDP(cryptoDictionary); if (signatureEvent != null) signatureEvent.getSignatureDictionary(cryptoDictionary); writer.addToBody(cryptoDictionary, refSig, false); } if (certificationLevel > 0) { // add DocMDP entry to root PdfDictionary docmdp = new PdfDictionary(); docmdp.put(new PdfName("DocMDP"), refSig); writer.reader.getCatalog().put(new PdfName("Perms"), docmdp); } writer.close(stamper.getMoreInfo()); range = new int[exclusionLocations.size() * 2]; int byteRangePosition = ((PdfLiteral)exclusionLocations.get(PdfName.BYTERANGE)).getPosition(); exclusionLocations.remove(PdfName.BYTERANGE); int idx = 1; for (Iterator it = exclusionLocations.values().iterator(); it.hasNext();) { PdfLiteral lit = (PdfLiteral)it.next(); int n = lit.getPosition(); range[idx++] = n; range[idx++] = lit.getPosLength() + n; } Arrays.sort(range, 1, range.length - 1); for (int k = 3; k < range.length - 2; k += 2) range[k] -= range[k - 1]; if (tempFile == null) { bout = sigout.getBuffer(); boutLen = sigout.size(); range[range.length - 1] = boutLen - range[range.length - 2]; ByteBuffer bf = new ByteBuffer(); bf.append('['); for (int k = 0; k < range.length; ++k) bf.append(range[k]).append(' '); bf.append(']'); System.arraycopy(bf.getBuffer(), 0, bout, byteRangePosition, bf.size()); } else { try { raf = new RandomAccessFile(tempFile, "rw"); int boutLen = (int)raf.length(); range[range.length - 1] = boutLen - range[range.length - 2]; ByteBuffer bf = new ByteBuffer(); bf.append('['); for (int k = 0; k < range.length; ++k) bf.append(range[k]).append(' '); bf.append(']'); raf.seek(byteRangePosition); raf.write(bf.getBuffer(), 0, bf.size()); } catch (IOException e) { try{raf.close();}catch(Exception ee){} try{tempFile.delete();}catch(Exception ee){} throw e; } } } /** * This is the last method to be called when using external signatures. The general sequence is: * preClose(), getDocumentBytes() and close(). * <p> * <CODE>update</CODE> is a <CODE>PdfDictionary</CODE> that must have exactly the * same keys as the ones provided in {@link #preClose(HashMap)}. * @param update a <CODE>PdfDictionary</CODE> with the key/value that will fill the holes defined * in {@link #preClose(HashMap)} * @throws DocumentException on error * @throws IOException on error */ public void close(PdfDictionary update) throws IOException, DocumentException { try { if (!preClosed) throw new DocumentException("preClose() must be called first."); ByteBuffer bf = new ByteBuffer(); for (Iterator it = update.getKeys().iterator(); it.hasNext();) { PdfName key = (PdfName)it.next(); PdfObject obj = update.get(key); PdfLiteral lit = (PdfLiteral)exclusionLocations.get(key); if (lit == null) throw new IllegalArgumentException("The key " + key.toString() + " didn't reserve space in preClose()."); bf.reset(); obj.toPdf(null, bf); if (bf.size() > lit.getPosLength()) throw new IllegalArgumentException("The key " + key.toString() + " is too big. Is " + bf.size() + ", reserved " + lit.getPosLength()); if (tempFile == null) System.arraycopy(bf.getBuffer(), 0, bout, lit.getPosition(), bf.size()); else { raf.seek(lit.getPosition()); raf.write(bf.getBuffer(), 0, bf.size()); } } if (update.size() != exclusionLocations.size()) throw new IllegalArgumentException("The update dictionary has less keys than required."); if (tempFile == null) { originalout.write(bout, 0, boutLen); } else { if (originalout != null) { raf.seek(0); int length = (int)raf.length(); byte buf[] = new byte[8192]; while (length > 0) { int r = raf.read(buf, 0, Math.min(buf.length, length)); if (r < 0) throw new EOFException("Unexpected EOF"); originalout.write(buf, 0, r); length -= r; } } } } finally { if (tempFile != null) { try{raf.close();}catch(Exception ee){} if (originalout != null) try{tempFile.delete();}catch(Exception ee){} } if (originalout != null) try{originalout.close();}catch(Exception e){} } } private void addDocMDP(PdfDictionary crypto) { PdfDictionary reference = new PdfDictionary(); PdfDictionary transformParams = new PdfDictionary(); transformParams.put(PdfName.P, new PdfNumber(certificationLevel)); transformParams.put(PdfName.V, new PdfName("1.2")); transformParams.put(PdfName.TYPE, PdfName.TRANSFORMPARAMS); reference.put(PdfName.TRANSFORMMETHOD, PdfName.DOCMDP); reference.put(PdfName.TYPE, PdfName.SIGREF); reference.put(PdfName.TRANSFORMPARAMS, transformParams); reference.put(new PdfName("DigestValue"), new PdfString("aa"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -