/// <summary> /// Opens an existing PDF document. /// </summary> public static PDFDocument Open(string path, string password, PDFDocumentOpenMode openmode, PDFPasswordProvider provider) { #if !NETFX_CORE PDFDocument document; Stream stream = null; try { stream = new FileStream(path, FileMode.Open, FileAccess.Read); document = Open(stream, password, openmode, provider); if (document != null) { document._fullPath = Path.GetFullPath(path); } } finally { if (stream != null) #if !UWP { stream.Close(); } #else { stream.Dispose(); } #endif } return(document); #else return(null); #endif }
/// <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); }
/// <summary> /// Opens an existing PDF document. /// </summary> public static PDFDocument Open(Stream stream, string password, PDFDocumentOpenMode openmode) => Open(stream, password, openmode, null);
/// <summary> /// Opens an existing PDF document. /// </summary> public static PDFDocument Open(Stream stream, PDFDocumentOpenMode openmode, PDFPasswordProvider passwordProvider) => Open(stream, null, openmode, passwordProvider);
/// <summary> /// Opens an existing PDF document. /// </summary> public static PDFDocument Open(Stream stream, PDFDocumentOpenMode openmode) => Open(stream, null, openmode);
/// <summary> /// Opens an existing PDF document. /// </summary> public static PDFDocument Open(string path, string password, PDFDocumentOpenMode openmode) => Open(path, password, openmode, null);
/// <summary> /// Opens an existing PDF document. /// </summary> public static PDFDocument Open(string path, PDFDocumentOpenMode openmode, PDFPasswordProvider provider) => Open(path, null, openmode, provider);
/// <summary> /// Opens an existing PDF document. /// </summary> public static PDFDocument Open(string path, PDFDocumentOpenMode openmode) => Open(path, null, openmode, null);