Example #1
0
        /**
         * Closes the document. No more content can be written after the
         * document is closed.
         * <p>
         * If closing a signed document with an external signature the closing must be done
         * in the <CODE>PdfSignatureAppearance</CODE> instance.
         * @throws DocumentException on error
         * @throws IOException on error
         */
        public void Close()
        {
            if (!hasSignature)
            {
                stamper.Close(moreInfo);
                return;
            }
            sigApp.PreClose();
            PdfSigGenericPKCS sig = sigApp.SigStandard;
            PdfLiteral        lit = (PdfLiteral)sig.Get(PdfName.CONTENTS);
            int totalBuf          = (lit.PosLength - 2) / 2;

            byte[] buf = new byte[8192];
            int    n;
            Stream inp = sigApp.RangeStream;

            while ((n = inp.Read(buf, 0, buf.Length)) > 0)
            {
                sig.Signer.Update(buf, 0, n);
            }
            buf = new byte[totalBuf];
            byte[] bsig = sig.SignerContents;
            Array.Copy(bsig, 0, buf, 0, bsig.Length);
            PdfString str = new PdfString(buf);

            str.SetHexWriting(true);
            PdfDictionary dic = new PdfDictionary();

            dic.Put(PdfName.CONTENTS, str);
            sigApp.Close(dic);
            stamper.reader.Close();
        }
Example #2
0
        /**
        * 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>Hashtable</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(Dictionary<PdfName, int> exclusionSizes) {
            if (preClosed)
                throw new DocumentException(MessageLocalization.GetComposedMessage("document.already.pre.closed"));
            stamper.MergeVerification();
            preClosed = true;
            AcroFields af = writer.AcroFields;
            String name = FieldName;
            bool fieldExists = !(IsInvisible() || IsNewField());
            PdfIndirectReference refSig = writer.PdfIndirectReference;
            writer.SigFlags = 3;
            if (fieldExists) {
                PdfDictionary widget = af.GetFieldItem(name).GetWidget(0);
                writer.MarkUsed(widget);
                widget.Put(PdfName.P, writer.GetPageReference(Page));
                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().IndirectReference);
                widget.Put(PdfName.AP, ap);
            }
            else {
                PdfFormField sigField = PdfFormField.CreateSignature(writer);
                sigField.FieldName = name;
                sigField.Put(PdfName.V, refSig);
                sigField.Flags = PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_LOCKED;

                int pagen = Page;
                if (!IsInvisible())
                    sigField.SetWidget(PageRect, null);
                else
                    sigField.SetWidget(new Rectangle(0, 0), null);
                sigField.SetAppearance(PdfAnnotation.APPEARANCE_NORMAL, GetAppearance());
                sigField.Page = pagen;
                writer.AddAnnotation(sigField, pagen);
            }

            exclusionLocations = new Dictionary<PdfName,PdfLiteral>();
            if (cryptoDictionary == null) {
                if (PdfName.ADOBE_PPKLITE.Equals(Filter))
                    sigStandard = new PdfSigGenericPKCS.PPKLite();
                else if (PdfName.ADOBE_PPKMS.Equals(Filter))
                    sigStandard = new PdfSigGenericPKCS.PPKMS();
                else if (PdfName.VERISIGN_PPKVS.Equals(Filter))
                    sigStandard = new PdfSigGenericPKCS.VeriSign();
                else
                    throw new ArgumentException(MessageLocalization.GetComposedMessage("unknown.filter.1", Filter));
                sigStandard.SetExternalDigest(externalDigest, externalRSAdata, digestEncryptionAlgorithm);
                if (Reason != null)
                    sigStandard.Reason = Reason;
                if (Location != null)
                    sigStandard.Location = Location;
                if (Contact != null)
                    sigStandard.Contact = Contact;
                sigStandard.Put(PdfName.M, new PdfDate(SignDate));
                sigStandard.SetSignInfo(PrivKey, CertChain, CrlList);
                PdfString contents = (PdfString)sigStandard.Get(PdfName.CONTENTS);
                PdfLiteral lit = new PdfLiteral((contents.ToString().Length + (PdfName.ADOBE_PPKLITE.Equals(Filter)?0:64)) * 2 + 2);
                exclusionLocations[PdfName.CONTENTS] = lit;
                sigStandard.Put(PdfName.CONTENTS, lit);
                lit = new PdfLiteral(80);
                exclusionLocations[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[PdfName.BYTERANGE] = lit;
                cryptoDictionary.Put(PdfName.BYTERANGE, lit);
                foreach (KeyValuePair<PdfName,int> entry in exclusionSizes) {
                    PdfName key = entry.Key;
                    int v = entry.Value;
                    lit = new PdfLiteral(v);
                    exclusionLocations[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.Catalog.Put(new PdfName("Perms"), docmdp);
            }
            writer.Close(stamper.MoreInfo);
            
            range = new int[exclusionLocations.Count * 2];
            int byteRangePosition = exclusionLocations[PdfName.BYTERANGE].Position;
            exclusionLocations.Remove(PdfName.BYTERANGE);
            int idx = 1;
            foreach (PdfLiteral lit in exclusionLocations.Values) {
                int n = lit.Position;
                range[idx++] = n;
                range[idx++] = lit.PosLength + n;
            }
            Array.Sort(range, 1, range.Length - 2);
            for (int k = 3; k < range.Length - 2; k += 2)
                range[k] -= range[k - 1];
            
            if (tempFile == null) {
                bout = sigout.Buffer;
                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(']');
                Array.Copy(bf.Buffer, 0, bout, byteRangePosition, bf.Size);
            }
            else {
                try {
                    raf = new FileStream(tempFile, FileMode.Open, FileAccess.ReadWrite);
                    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, SeekOrigin.Begin);
                    raf.Write(bf.Buffer, 0, bf.Size);
                }
                catch (IOException e) {
                    try{raf.Close();}catch{}
                    try{File.Delete(tempFile);}catch{}
                    throw e;
                }
            }
        }