Example #1
0
            public PDFObject GetIndirectObject(int index)
            {
                if (index < 0 || index >= Count)
                {
                    throw new ArgumentOutOfRangeException("index", index, PSSR.IndexOutOfRange);
                }

                PDFReference reference = this[index] as PDFReference;

                return(reference?.Value);
            }
Example #2
0
 static PDFReference RemapReference(PDFPage[] newPages, PDFPage[] impPages, PDFReference iref)
 {
     // Directs the iref to a one of the imported pages?
     for (int idx = 0; idx < newPages.Length; idx++)
     {
         if (impPages[idx].Reference == iref)
         {
             return(newPages[idx].Reference);
         }
     }
     return(null);
 }
Example #3
0
        /// <summary>
        /// Recursively converts the page tree into a flat array.
        /// </summary>
        PDFDictionary[] GetKids(PDFReference iref, PDFPage.InheritedValues values, PDFDictionary parent)
        {
            // TODO: inherit inheritable keys...
            PDFDictionary kid = (PDFDictionary)iref.Value;

#if true
            string type = kid.Elements.GetName(Keys.Type);
            if (type == "/Page")
            {
                PDFPage.InheritValues(kid, values);
                return(new PDFDictionary[] { kid });
            }

            if (String.IsNullOrEmpty(type))
            {
                // Type is required. If type is missing, assume it is "/Page" and hope it will work.
                // TODO Implement a "Strict" mode in PDFSharp and don't do this in "Strict" mode.
                PDFPage.InheritValues(kid, values);
                return(new PDFDictionary[] { kid });
            }
#else
            if (kid.Elements.GetName(Keys.Type) == "/Page")
            {
                PDFPage.InheritValues(kid, values);
                return(new PDFDictionary[] { kid });
            }
#endif

            Debug.Assert(kid.Elements.GetName(Keys.Type) == "/Pages");
            PDFPage.InheritValues(kid, ref values);
            List <PDFDictionary> list = new List <PDFDictionary>();
            PDFArray             kids = kid.Elements["/Kids"] as PDFArray;

            if (kids == null)
            {
                if (kid.Elements["/Kids"] is PDFReference xref3)
                {
                    kids = xref3.Value as PDFArray;
                }
            }

            foreach (PDFReference xref2 in kids)
            {
                list.AddRange(GetKids(xref2, values, kid));
            }
            int count = list.Count;
            Debug.Assert(count == kid.Elements.GetInteger("/Count"));
            return(list.ToArray());
        }
Example #4
0
        /// <summary>
        /// Moves a page within the page sequence.
        /// </summary>
        /// <param name="oldIndex">The page index before this operation.</param>
        /// <param name="newIndex">The page index after this operation.</param>
        public void MovePage(int oldIndex, int newIndex)
        {
            if (oldIndex < 0 || oldIndex >= Count)
            {
                throw new ArgumentOutOfRangeException("oldIndex");
            }
            if (newIndex < 0 || newIndex >= Count)
            {
                throw new ArgumentOutOfRangeException("newIndex");
            }
            if (oldIndex == newIndex)
            {
                return;
            }

            //PDFPage page = (PDFPage)pagesArray.Elements[oldIndex];
            PDFReference page = (PDFReference)_pagesArray.Elements[oldIndex];

            _pagesArray.Elements.RemoveAt(oldIndex);
            _pagesArray.Elements.Insert(newIndex, page);
        }
Example #5
0
        /// <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];
                    if (iref.Value is PDFCrossReferenceStream xrefStream)
                    {
                        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];
                    if (iref.Value is PDFCrossReferenceStream xrefStream)
                    {
                        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);
        }
Example #6
0
        /// <summary>
        /// Implements saving a PDF file.
        /// </summary>
        void DoSave(PDFWriter writer)
        {
            if (_pages == null || _pages.Count == 0)
            {
                if (OutStream != null)
                {
                    // Give feedback if the wrong constructor was used.
                    throw new InvalidOperationException("Cannot save a PDF document with no pages. Do not use \"public PDFDocument(string filename)\" or \"public PDFDocument(Stream outputStream)\" if you want to open an existing PDF document from a file or stream; use PDFReader.Open() for that purpose.");
                }
                throw new InvalidOperationException("Cannot save a PDF document with no pages.");
            }

            try
            {
                // HACK: Remove XRefTrailer
                if (Trailer is PDFCrossReferenceStream)
                {
                    // HACK^2: Preserve the SecurityHandler.
                    PDFStandardSecurityHandler securityHandler = _securitySettings.SecurityHandler;
                    Trailer = new PDFTrailer((PDFCrossReferenceStream)Trailer)
                    {
                        _securityHandler = securityHandler
                    };
                }

                bool encrypt = _securitySettings.DocumentSecurityLevel != PDFDocumentSecurityLevel.None;
                if (encrypt)
                {
                    PDFStandardSecurityHandler securityHandler = _securitySettings.SecurityHandler;
                    if (securityHandler.Reference == null)
                    {
                        IrefTable.Add(securityHandler);
                    }
                    else
                    {
                        Debug.Assert(IrefTable.Contains(securityHandler.ObjectID));
                    }
                    Trailer.Elements[PDFTrailer.Keys.Encrypt] = _securitySettings.SecurityHandler.Reference;
                }
                else
                {
                    Trailer.Elements.Remove(PDFTrailer.Keys.Encrypt);
                }

                PrepareForSave();

                if (encrypt)
                {
                    _securitySettings.SecurityHandler.PrepareEncryption();
                }

                writer.WriteFileHeader(this);
                PDFReference[] irefs = IrefTable.AllReferences;
                int            count = irefs.Length;
                for (int idx = 0; idx < count; idx++)
                {
                    PDFReference iref = irefs[idx];
                    iref.Position = writer.Position;
                    iref.Value.WriteObject(writer);
                }
                int startxref = writer.Position;
                IrefTable.WriteObject(writer);
                writer.WriteRaw("trailer\n");
                Trailer.Elements.SetInteger("/Size", count + 1);
                Trailer.WriteObject(writer);
                writer.WriteEof(this, startxref);
            }
            finally
            {
                if (writer != null)
                {
                    writer.Stream.Flush();
                }
            }
        }
Example #7
0
 public void Write(PDFReference iref)
 {
     WriteSeparator(CharCat.Character);
     WriteRaw(iref.ToString());
     _lastCat = CharCat.Character;
 }