Exemple #1
0
        internal PdfFormXObject(PdfDocument thisDocument, PdfImportedObjectTable importedObjectTable, XPdfForm form)
            : base(thisDocument)
        {
            Debug.Assert(importedObjectTable != null);
            Debug.Assert(ReferenceEquals(thisDocument, importedObjectTable.Owner));
            Elements.SetName(Keys.Type, "/XObject");
            Elements.SetName(Keys.Subtype, "/Form");

            if (form.IsTemplate)
            {
                Debug.Assert(importedObjectTable == null);
                // TODO more initialization here???
                return;
            }

            XPdfForm pdfForm = form;
            // Get import page
            PdfPages importPages = importedObjectTable.ExternalDocument.Pages;

            if (pdfForm.PageNumber < 1 || pdfForm.PageNumber > importPages.Count)
            {
                PSSR.ImportPageNumberOutOfRange(pdfForm.PageNumber, importPages.Count, form._path);
            }
            PdfPage importPage = importPages[pdfForm.PageNumber - 1];

            // Import resources
            PdfItem res = importPage.Elements["/Resources"];

            if (res != null) // unlikely but possible
            {
#if true
                // Get root object
                PdfObject root;
                if (res is PdfReference)
                {
                    root = ((PdfReference)res).Value;
                }
                else
                {
                    root = (PdfDictionary)res;
                }

                root = ImportClosure(importedObjectTable, thisDocument, root);
                // If the root was a direct object, make it indirect.
                if (root.Reference == null)
                {
                    thisDocument._irefTable.Add(root);
                }

                Debug.Assert(root.Reference != null);
                Elements["/Resources"] = root.Reference;
#else
                // Get transitive closure
                PdfObject[] resources = importPage.Owner.Internals.GetClosure(resourcesRoot);
                int         count     = resources.Length;
#if DEBUG_
                for (int idx = 0; idx < count; idx++)
                {
                    Debug.Assert(resources[idx].XRef != null);
                    Debug.Assert(resources[idx].XRef.Document != null);
                    Debug.Assert(resources[idx].Document != null);
                    if (resources[idx].ObjectID.ObjectNumber == 12)
                    {
                        GetType();
                    }
                }
#endif
                // 1st step. Already imported objects are reused and new ones are cloned.
                for (int idx = 0; idx < count; idx++)
                {
                    PdfObject obj = resources[idx];
                    if (importedObjectTable.Contains(obj.ObjectID))
                    {
                        // external object was already imported
                        PdfReference iref = importedObjectTable[obj.ObjectID];
                        Debug.Assert(iref != null);
                        Debug.Assert(iref.Value != null);
                        Debug.Assert(iref.Document == Owner);
                        // replace external object by the already clone counterpart
                        resources[idx] = iref.Value;
                    }
                    else
                    {
                        // External object was not imported ealier and must be cloned
                        PdfObject clone = obj.Clone();
                        Debug.Assert(clone.Reference == null);
                        clone.Document = Owner;
                        if (obj.Reference != null)
                        {
                            // add it to this (the importer) document
                            Owner.irefTable.Add(clone);
                            Debug.Assert(clone.Reference != null);
                            // save old object identifier
                            importedObjectTable.Add(obj.ObjectID, clone.Reference);
                            //Debug.WriteLine("Cloned: " + obj.ObjectID.ToString());
                        }
                        else
                        {
                            // The root object (the /Resources value) is not an indirect object
                            Debug.Assert(idx == 0);
                            // add it to this (the importer) document
                            Owner.irefTable.Add(clone);
                            Debug.Assert(clone.Reference != null);
                        }
                        // replace external object by its clone
                        resources[idx] = clone;
                    }
                }
#if DEBUG_
                for (int idx = 0; idx < count; idx++)
                {
                    Debug.Assert(resources[idx].XRef != null);
                    Debug.Assert(resources[idx].XRef.Document != null);
                    Debug.Assert(resources[idx].Document != null);
                    if (resources[idx].ObjectID.ObjectNumber == 12)
                    {
                        GetType();
                    }
                }
#endif

                // 2nd step. Fix up indirect references that still refers to the import document.
                for (int idx = 0; idx < count; idx++)
                {
                    PdfObject obj = resources[idx];
                    Debug.Assert(obj.Owner != null);
                    FixUpObject(importedObjectTable, importedObjectTable.Owner, obj);
                }

                // Set resources key to the root of the clones
                Elements["/Resources"] = resources[0].Reference;
#endif
            }

            // Take /Rotate into account
            PdfRectangle rect   = importPage.Elements.GetRectangle(PdfPage.Keys.MediaBox);
            int          rotate = importPage.Elements.GetInteger(PdfPage.Keys.Rotate);
            //rotate = 0;
            if (rotate == 0)
            {
                // Set bounding box to media box
                Elements["/BBox"] = rect;
            }
            else
            {
                // TODO: Have to adjust bounding box? (I think not, but I'm not sure -> wait for problem)
                Elements["/BBox"] = rect;

                // Rotate the image such that it is upright
                XMatrix matrix = new XMatrix();
                double  width  = rect.Width;
                double  height = rect.Height;
                matrix.RotateAtPrepend(-rotate, new XPoint(width / 2, height / 2));

                if (rotate != 180)
                {
                    // Translate the image such that its center lies on the center of the rotated bounding box
                    double offset = (height - width) / 2;
                    if (height > width)
                    {
                        matrix.TranslatePrepend(offset, offset);
                    }
                    else
                    {
                        matrix.TranslatePrepend(-offset, -offset);
                    }
                }

                //string item = "[" + PdfEncoders.ToString(matrix) + "]";
                //Elements[Keys.Matrix] = new PdfLiteral(item);
                Elements.SetMatrix(Keys.Matrix, matrix);
            }

            // Preserve filter because the content keeps unmodified
            PdfContent content = importPage.Contents.CreateSingleContent();
#if !DEBUG
            content.Compressed = true;
#endif
            PdfItem filter = content.Elements["/Filter"];
            if (filter != null)
            {
                Elements["/Filter"] = filter.Clone();
            }

            // (no cloning needed because the bytes keep untouched)
            Stream = content.Stream; // new PdfStream(bytes, this);
            Elements.SetInteger("/Length", content.Stream.Value.Length);
        }
        /// <summary>
        /// Opens an existing PDF document.
        /// </summary>
        public static PdfDocument Open(Stream stream, string password, PdfDocumentOpenMode openmode, PdfPasswordProvider passwordProvider)
        {
            PdfDocument document = null;

            try
            {
                Lexer lexer = new Lexer(stream);
                document          = new PdfDocument(lexer);
                document.state   |= DocumentState.Imported;
                document.openMode = openmode;
                document.fileSize = stream.Length;

                // Get file version
                byte[] header = new byte[1024];
                stream.Position = 0;
                stream.Read(header, 0, 1024);
                document.version = GetPdfFileVersion(header);
                if (document.version == 0)
                {
                    throw new InvalidOperationException(PSSR.InvalidPdf);
                }

                // Read all trailers
                document.irefTable.IsUnderConstruction = true;
                Parser parser = new Parser(document);
                document.trailer = parser.ReadTrailer();

                document.irefTable.IsUnderConstruction = false;

                // Is document encrypted?
                PdfReference xrefEncrypt = document.trailer.Elements[PdfTrailer.Keys.Encrypt] as PdfReference;
                if (xrefEncrypt != null)
                {
                    //xrefEncrypt.Value = parser.ReadObject(null, xrefEncrypt.ObjectID, false);
                    PdfObject encrypt = parser.ReadObject(null, xrefEncrypt.ObjectID, false);

                    encrypt.Reference = xrefEncrypt;
                    xrefEncrypt.Value = encrypt;
                    PdfStandardSecurityHandler securityHandler = document.SecurityHandler;
TryAgain:
                    PasswordValidity validity = securityHandler.ValidatePassword(password);
                    if (validity == PasswordValidity.Invalid)
                    {
                        if (passwordProvider != null)
                        {
                            PdfPasswordProviderArgs args = new PdfPasswordProviderArgs();
                            passwordProvider(args);
                            if (args.Abort)
                            {
                                return(null);
                            }
                            password = args.Password;
                            goto TryAgain;
                        }
                        else
                        {
                            if (password == null)
                            {
                                throw new PdfReaderException(PSSR.PasswordRequired);
                            }
                            else
                            {
                                throw new PdfReaderException(PSSR.InvalidPassword);
                            }
                        }
                    }
                    else if (validity == PasswordValidity.UserPassword && openmode == PdfDocumentOpenMode.Modify)
                    {
                        if (passwordProvider != null)
                        {
                            PdfPasswordProviderArgs args = new PdfPasswordProviderArgs();
                            passwordProvider(args);
                            if (args.Abort)
                            {
                                return(null);
                            }
                            password = args.Password;
                            goto TryAgain;
                        }
                        else
                        {
                            throw new PdfReaderException(PSSR.OwnerPasswordRequired);
                        }
                    }
                }
                else
                {
                    if (password != null)
                    {
                        // Password specified but document is not encrypted.
                        // ignore
                    }
                }

                PdfReference[] irefs = document.irefTable.AllReferences;
                int            count = irefs.Length;

                // Read all indirect objects
                for (int idx = 0; idx < count; idx++)
                {
                    PdfReference iref = irefs[idx];
                    if (iref.Value == null)
                    {
                        try
                        {
                            Debug.Assert(document.irefTable.Contains(iref.ObjectID));
                            PdfObject pdfObject = parser.ReadObject(null, iref.ObjectID, false);
                            Debug.Assert(pdfObject.Reference == iref);
                            pdfObject.Reference = iref;
                            Debug.Assert(pdfObject.Reference.Value != null, "something got wrong");
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine(ex.Message);
                        }
                    }
                    else
                    {
                        Debug.Assert(document.irefTable.Contains(iref.ObjectID));
                        iref.GetType();
                    }
                    // Set maximum object number
                    document.irefTable.maxObjectNumber = Math.Max(document.irefTable.maxObjectNumber, iref.ObjectNumber);
                }
                // Encrypt all objects
                if (xrefEncrypt != null)
                {
                    document.SecurityHandler.EncryptDocument();
                }

                // Fix references of trailer values and then objects and irefs are consistent.
                document.trailer.Finish();

#if DEBUG_
                // Some tests...
                PdfReference[] reachables = document.xrefTable.TransitiveClosure(document.trailer);
                reachables.GetType();
                reachables = document.xrefTable.AllXRefs;
                document.xrefTable.CheckConsistence();
#endif

                if (openmode == PdfDocumentOpenMode.Modify)
                {
                    // Create new or change existing document IDs
                    if (document.Internals.SecondDocumentID == "")
                    {
                        document.trailer.CreateNewDocumentIDs();
                    }
                    else
                    {
                        byte[] agTemp = Guid.NewGuid().ToByteArray();
                        document.Internals.SecondDocumentID = PdfEncoders.RawEncoding.GetString(agTemp, 0, agTemp.Length);
                    }

                    // Change modification date
                    document.Info.ModificationDate = DateTime.Now;

                    // Remove all unreachable objects
                    int removed = document.irefTable.Compact();
                    if (removed != 0)
                    {
                        Debug.WriteLine("Number of deleted unreachable objects: " + removed.ToString());
                    }

                    // Force flattening of page tree
                    PdfPages pages = document.Pages;

                    //bool b = document.irefTable.Contains(new PdfObjectID(1108));
                    //b.GetType();

                    document.irefTable.CheckConsistence();
                    document.irefTable.Renumber();
                    document.irefTable.CheckConsistence();
                }
            }
            finally
            {
                //if (filestream != null)
                //  filestream.Close();
            }
            return(document);
        }
        /// <summary>
        /// Opens an existing PDF document.
        /// </summary>
        public static PdfDocument Open(Stream stream, string password, PdfDocumentOpenMode openmode, PdfPasswordProvider passwordProvider)
        {
            PdfDocument document;

            try
            {
                Lexer lexer = new Lexer(stream);
                document           = new PdfDocument(lexer);
                document._state   |= DocumentState.Imported;
                document._openMode = openmode;
                document._fileSize = stream.Length;

                // Get file version.
                byte[] header = new byte[1024];
                stream.Position = 0;
                stream.Read(header, 0, 1024);
                document._version = GetPdfFileVersion(header);
                if (document._version == 0)
                {
                    throw new InvalidOperationException(PSSR.InvalidPdf);
                }

                document._irefTable.IsUnderConstruction = true;
                Parser parser = new Parser(document);
                // Read all trailers or cross-reference streams, but no objects.
                document._trailer = parser.ReadTrailer();
                if (document._trailer == null)
                {
                    ParserDiagnostics.ThrowParserException("Invalid PDF file: no trailer found."); // TODO L10N using PSSR.
                }
                Debug.Assert(document._irefTable.IsUnderConstruction);
                document._irefTable.IsUnderConstruction = false;

                // Is document encrypted?
                PdfReference xrefEncrypt = document._trailer.Elements[PdfTrailer.Keys.Encrypt] as PdfReference;
                if (xrefEncrypt != null)
                {
                    //xrefEncrypt.Value = parser.ReadObject(null, xrefEncrypt.ObjectID, false);
                    PdfObject encrypt = parser.ReadObject(null, xrefEncrypt.ObjectID, false, false);

                    encrypt.Reference = xrefEncrypt;
                    xrefEncrypt.Value = encrypt;
                    PdfStandardSecurityHandler securityHandler = document.SecurityHandler;
TryAgain:
                    PasswordValidity validity = securityHandler.ValidatePassword(password);
                    if (validity == PasswordValidity.Invalid)
                    {
                        if (passwordProvider != null)
                        {
                            PdfPasswordProviderArgs args = new PdfPasswordProviderArgs();
                            passwordProvider(args);
                            if (args.Abort)
                            {
                                return(null);
                            }
                            password = args.Password;
                            goto TryAgain;
                        }
                        else
                        {
                            if (password == null)
                            {
                                throw new PdfReaderException(PSSR.PasswordRequired);
                            }
                            else
                            {
                                throw new PdfReaderException(PSSR.InvalidPassword);
                            }
                        }
                    }
                    else if (validity == PasswordValidity.UserPassword && openmode == PdfDocumentOpenMode.Modify)
                    {
                        if (passwordProvider != null)
                        {
                            PdfPasswordProviderArgs args = new PdfPasswordProviderArgs();
                            passwordProvider(args);
                            if (args.Abort)
                            {
                                return(null);
                            }
                            password = args.Password;
                            goto TryAgain;
                        }
                        else
                        {
                            throw new PdfReaderException(PSSR.OwnerPasswordRequired);
                        }
                    }
                }
                else
                {
                    if (password != null)
                    {
                        // Password specified but document is not encrypted.
                        // ignore
                    }
                }

                PdfReference[] irefs2 = document._irefTable.AllReferences;
                int            count2 = irefs2.Length;

                // 3rd: Create iRefs for all compressed objects.
                Dictionary <int, object> objectStreams = new Dictionary <int, object>();
                for (int idx = 0; idx < count2; idx++)
                {
                    PdfReference            iref       = irefs2[idx];
                    PdfCrossReferenceStream xrefStream = iref.Value as PdfCrossReferenceStream;
                    if (xrefStream != null)
                    {
                        for (int idx2 = 0; idx2 < xrefStream.Entries.Count; idx2++)
                        {
                            PdfCrossReferenceStream.CrossReferenceStreamEntry item = xrefStream.Entries[idx2];
                            // Is type xref to compressed object?
                            if (item.Type == 2)
                            {
                                //PdfReference irefNew = parser.ReadCompressedObject(new PdfObjectID((int)item.Field2), (int)item.Field3);
                                //document._irefTable.Add(irefNew);
                                int objectNumber = (int)item.Field2;
                                if (!objectStreams.ContainsKey(objectNumber))
                                {
                                    objectStreams.Add(objectNumber, null);
                                    PdfObjectID objectID = new PdfObjectID((int)item.Field2);
                                    parser.ReadIRefsFromCompressedObject(objectID);
                                }
                            }
                        }
                    }
                }

                // 4th: Read compressed objects.
                for (int idx = 0; idx < count2; idx++)
                {
                    PdfReference            iref       = irefs2[idx];
                    PdfCrossReferenceStream xrefStream = iref.Value as PdfCrossReferenceStream;
                    if (xrefStream != null)
                    {
                        for (int idx2 = 0; idx2 < xrefStream.Entries.Count; idx2++)
                        {
                            PdfCrossReferenceStream.CrossReferenceStreamEntry item = xrefStream.Entries[idx2];
                            // Is type xref to compressed object?
                            if (item.Type == 2)
                            {
                                PdfReference irefNew = parser.ReadCompressedObject(new PdfObjectID((int)item.Field2),
                                                                                   (int)item.Field3);
                                Debug.Assert(document._irefTable.Contains(iref.ObjectID));
                                //document._irefTable.Add(irefNew);
                            }
                        }
                    }
                }


                PdfReference[] irefs = document._irefTable.AllReferences;
                int            count = irefs.Length;

                // Read all indirect objects.
                for (int idx = 0; idx < count; idx++)
                {
                    PdfReference iref = irefs[idx];
                    if (iref.Value == null)
                    {
#if DEBUG_
                        if (iref.ObjectNumber == 1074)
                        {
                            iref.GetType();
                        }
#endif
                        try
                        {
                            Debug.Assert(document._irefTable.Contains(iref.ObjectID));
                            PdfObject pdfObject = parser.ReadObject(null, iref.ObjectID, false, false);
                            Debug.Assert(pdfObject.Reference == iref);
                            pdfObject.Reference = iref;
                            Debug.Assert(pdfObject.Reference.Value != null, "Something went wrong.");
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine(ex.Message);
                            // 4STLA rethrow exception to notify caller.
                            throw;
                        }
                    }
                    else
                    {
                        Debug.Assert(document._irefTable.Contains(iref.ObjectID));
                        //iref.GetType();
                    }
                    // Set maximum object number.
                    document._irefTable._maxObjectNumber = Math.Max(document._irefTable._maxObjectNumber,
                                                                    iref.ObjectNumber);
                }

                // Encrypt all objects.
                if (xrefEncrypt != null)
                {
                    document.SecurityHandler.EncryptDocument();
                }

                // Fix references of trailer values and then objects and irefs are consistent.
                document._trailer.Finish();

#if DEBUG_
                // Some tests...
                PdfReference[] reachables = document.xrefTable.TransitiveClosure(document.trailer);
                reachables.GetType();
                reachables = document.xrefTable.AllXRefs;
                document.xrefTable.CheckConsistence();
#endif

                if (openmode == PdfDocumentOpenMode.Modify)
                {
                    // Create new or change existing document IDs.
                    if (document.Internals.SecondDocumentID == "")
                    {
                        document._trailer.CreateNewDocumentIDs();
                    }
                    else
                    {
                        byte[] agTemp = Guid.NewGuid().ToByteArray();
                        document.Internals.SecondDocumentID = PdfEncoders.RawEncoding.GetString(agTemp, 0, agTemp.Length);
                    }

                    // Change modification date
                    document.Info.ModificationDate = DateTime.Now;

                    // Remove all unreachable objects
                    int removed = document._irefTable.Compact();
                    if (removed != 0)
                    {
                        Debug.WriteLine("Number of deleted unreachable objects: " + removed);
                    }

                    // Force flattening of page tree
                    PdfPages pages = document.Pages;
                    Debug.Assert(pages != null);

                    //bool b = document.irefTable.Contains(new PdfObjectID(1108));
                    //b.GetType();

                    document._irefTable.CheckConsistence();
                    document._irefTable.Renumber();
                    document._irefTable.CheckConsistence();
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                throw;
            }
            return(document);
        }
Exemple #4
0
        // The end goal is to have a user select the path of a PDf in need of watermarks.
        // Submit the file and press GO. Once they press Go, it grabs the pdf and watermarks it, then saves it in the network folder.

        public void markPDF(string filepath, string watermark, string userfile, int fontSize, string destination)
        {
            string userWatermark = watermark;

            // If the watermark field is empty.
            if (string.IsNullOrEmpty(userWatermark))
            {
                MessageBox.Show("Enter text for the watermark.", "WaterPDF");  // Alert the user.
            }
            // If the path field is empty.
            else if (string.IsNullOrEmpty(filepath))
            {
                MessageBox.Show("Select a file.", "WaterPDF");// Alert the user
            }
            // If the new filename is empty.
            else if (string.IsNullOrWhiteSpace(userfile))
            {
                MessageBox.Show("Enter a filename", "WaterPDF"); // Alert the user.
            }
            else if (string.IsNullOrWhiteSpace(destination))
            {
                MessageBox.Show("Select a save destination"); // Alert the user.
            }
            else
            {
                if (File.Exists(filepath))
                {
                    // Creates a new file path to save the watermarked PDF.
                    string newFileName = destination + @"\" + userfile + ".pdf";


                    //PdfPasswordProvider provider;
                    // Opens the file from the path provided.
                    PdfDocument document = PdfReader.Open(filepath, PdfDocumentOpenMode.Modify);

                    // Counts the amount of pages in the PDF.
                    PdfPages pages = document.Pages;

                    // foreach page in pdf
                    // Paint the pdf and then move onto the next one?
                    foreach (PdfPage pager in pages)
                    {
                        // Creating the font variable.
                        XFont font = new XFont("Arial", fontSize, XFontStyle.Regular);

                        // Creating the graphics.
                        XGraphics gfx  = XGraphics.FromPdfPage(pager, XGraphicsPdfPageOptions.Append);
                        var       size = gfx.MeasureString(watermark, font);

                        // Creating the coordinates.
                        gfx.TranslateTransform(pager.Width / 2, pager.Height / 2);
                        gfx.RotateTransform(-Math.Atan(pager.Height / pager.Width) * 180 / Math.PI);
                        gfx.TranslateTransform(-pager.Width / 2, -pager.Height / 2);

                        var format = new XStringFormat();
                        format.Alignment     = XStringAlignment.Near;
                        format.LineAlignment = XLineAlignment.Near;

                        // Creating the brush to paint with.
                        XBrush brush = new XSolidBrush(XColor.FromKnownColor(XKnownColor.DimGray));

                        gfx.DrawString(watermark, font, brush,
                                       new XPoint((pager.Width - size.Width) / 2, (pager.Height - size.Height) / 2),
                                       format);

                        gfx.DrawString(watermark, font, brush,
                                       new XPoint((pager.Width - size.Width) / 2, (pager.Height - size.Height) / 2),
                                       format);
                    }
                    // Sets the first page as the page to work on.
                    //  PdfPage page = document.Pages[0];
                    // Saves it in the provided location.
                    document.Save(newFileName);
                    if (MessageBox.Show("Your PDF has been watered.", "WaterPDF") == DialogResult.OK)
                    {
                        // Alerts the user that the file was saved and creates an explorer window of the destination.
                        System.Diagnostics.Process.Start("explorer.exe", destination);
                    }
                }
                else
                {
                    MessageBox.Show("File Incorrect. Choose new file");
                }
            }
        }