📄 pdfreader.java
字号:
/*
* $Id: PdfReader.java 2764 2007-05-18 21:17:56Z xlv $
* $Name$
*
* Copyright 2001, 2002 Paulo Soares
*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the License.
*
* The Original Code is 'iText, a free JAVA-PDF library'.
*
* The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
* the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
* All Rights Reserved.
* Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
* are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
*
* Contributor(s): all the names of the contributors are added in the source code
* where applicable.
*
* Alternatively, the contents of this file may be used under the terms of the
* LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
* provisions of LGPL are applicable instead of those above. If you wish to
* allow use of your version of this file only under the terms of the LGPL
* License and not to allow others to use your version of this file under
* the MPL, indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by the LGPL.
* If you do not delete the provisions above, a recipient may use your version
* of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MPL as stated above or under the terms of the GNU
* Library General Public License as published by the Free Software Foundation;
* either version 2 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
* details.
*
* If you didn't download this code from the following link, you should check if
* you aren't using an obsolete version:
* http://www.lowagie.com/iText/
*/
package com.lowagie.text.pdf;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.InflaterInputStream;
import java.util.Stack;
import java.security.Key;
import java.security.MessageDigest;
import java.security.cert.Certificate;
import com.lowagie.text.ExceptionConverter;
import com.lowagie.text.PageSize;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.interfaces.PdfViewerPreferences;
import com.lowagie.text.pdf.internal.PdfViewerPreferencesImp;
import org.bouncycastle.cms.CMSEnvelopedData;
import org.bouncycastle.cms.RecipientInformation;
/** Reads a PDF document.
* @author Paulo Soares (psoares@consiste.pt)
* @author Kazuya Ujihara
*/
public class PdfReader implements PdfViewerPreferences {
static final PdfName pageInhCandidates[] = {
PdfName.MEDIABOX, PdfName.ROTATE, PdfName.RESOURCES, PdfName.CROPBOX
};
static final byte endstream[] = PdfEncodings.convertToBytes("endstream", null);
static final byte endobj[] = PdfEncodings.convertToBytes("endobj", null);
protected PRTokeniser tokens;
// Each xref pair is a position
// type 0 -> -1, 0
// type 1 -> offset, 0
// type 2 -> index, obj num
protected int xref[];
protected HashMap objStmMark;
protected IntHashtable objStmToOffset;
protected boolean newXrefType;
private ArrayList xrefObj;
PdfDictionary rootPages;
protected PdfDictionary trailer;
protected PdfDictionary catalog;
protected PageRefs pageRefs;
protected PRAcroForm acroForm = null;
protected boolean acroFormParsed = false;
protected boolean encrypted = false;
protected boolean rebuilt = false;
protected int freeXref;
protected boolean tampered = false;
protected int lastXref;
protected int eofPos;
protected char pdfVersion;
protected PdfEncryption decrypt;
protected byte password[] = null; //added by ujihara for decryption
protected Key certificateKey = null; //added by Aiken Sam for certificate decryption
protected Certificate certificate = null; //added by Aiken Sam for certificate decryption
protected String certificateKeyProvider = null; //added by Aiken Sam for certificate decryption
private boolean ownerPasswordUsed;
protected ArrayList strings = new ArrayList();
protected boolean sharedStreams = true;
protected boolean consolidateNamedDestinations = false;
protected int rValue;
protected int pValue;
private int objNum;
private int objGen;
private int fileLength;
private boolean hybridXref;
private int lastXrefPartial = -1;
private boolean partial;
private PRIndirectReference cryptoRef;
private PdfViewerPreferencesImp viewerPreferences = new PdfViewerPreferencesImp();
/**
* Holds value of property appendable.
*/
private boolean appendable;
protected PdfReader() {
}
/** Reads and parses a PDF document.
* @param filename the file name of the document
* @throws IOException on error
*/
public PdfReader(String filename) throws IOException {
this(filename, null);
}
/** Reads and parses a PDF document.
* @param filename the file name of the document
* @param ownerPassword the password to read the document
* @throws IOException on error
*/
public PdfReader(String filename, byte ownerPassword[]) throws IOException {
password = ownerPassword;
tokens = new PRTokeniser(filename);
readPdf();
}
/** Reads and parses a PDF document.
* @param pdfIn the byte array with the document
* @throws IOException on error
*/
public PdfReader(byte pdfIn[]) throws IOException {
this(pdfIn, null);
}
/** Reads and parses a PDF document.
* @param pdfIn the byte array with the document
* @param ownerPassword the password to read the document
* @throws IOException on error
*/
public PdfReader(byte pdfIn[], byte ownerPassword[]) throws IOException {
password = ownerPassword;
tokens = new PRTokeniser(pdfIn);
readPdf();
}
/** Reads and parses a PDF document.
* @param filename the file name of the document
* @param certificate the certificate to read the document
* @param certificateKey the private key of the certificate
* @param certificateKeyProvider the security provider for certificateKey
* @throws IOException on error
*/
public PdfReader(String filename, Certificate certificate, Key certificateKey, String certificateKeyProvider) throws IOException {
this.certificate = certificate;
this.certificateKey = certificateKey;
this.certificateKeyProvider = certificateKeyProvider;
tokens = new PRTokeniser(filename);
readPdf();
}
/** Reads and parses a PDF document.
* @param url the URL of the document
* @throws IOException on error
*/
public PdfReader(URL url) throws IOException {
this(url, null);
}
/** Reads and parses a PDF document.
* @param url the URL of the document
* @param ownerPassword the password to read the document
* @throws IOException on error
*/
public PdfReader(URL url, byte ownerPassword[]) throws IOException {
password = ownerPassword;
tokens = new PRTokeniser(new RandomAccessFileOrArray(url));
readPdf();
}
/**
* Reads and parses a PDF document.
* @param is the <CODE>InputStream</CODE> containing the document. The stream is read to the
* end but is not closed
* @param ownerPassword the password to read the document
* @throws IOException on error
*/
public PdfReader(InputStream is, byte ownerPassword[]) throws IOException {
password = ownerPassword;
tokens = new PRTokeniser(new RandomAccessFileOrArray(is));
readPdf();
}
/**
* Reads and parses a PDF document.
* @param is the <CODE>InputStream</CODE> containing the document. The stream is read to the
* end but is not closed
* @throws IOException on error
*/
public PdfReader(InputStream is) throws IOException {
this(is, null);
}
/**
* Reads and parses a pdf document. Contrary to the other constructors only the xref is read
* into memory. The reader is said to be working in "partial" mode as only parts of the pdf
* are read as needed. The pdf is left open but may be closed at any time with
* <CODE>PdfReader.close()</CODE>, reopen is automatic.
* @param raf the document location
* @param ownerPassword the password or <CODE>null</CODE> for no password
* @throws IOException on error
*/
public PdfReader(RandomAccessFileOrArray raf, byte ownerPassword[]) throws IOException {
password = ownerPassword;
partial = true;
tokens = new PRTokeniser(raf);
readPdfPartial();
}
/** Creates an independent duplicate.
* @param reader the <CODE>PdfReader</CODE> to duplicate
*/
public PdfReader(PdfReader reader) {
this.appendable = reader.appendable;
this.consolidateNamedDestinations = reader.consolidateNamedDestinations;
this.encrypted = reader.encrypted;
this.rebuilt = reader.rebuilt;
this.sharedStreams = reader.sharedStreams;
this.tampered = reader.tampered;
this.password = reader.password;
this.pdfVersion = reader.pdfVersion;
this.eofPos = reader.eofPos;
this.freeXref = reader.freeXref;
this.lastXref = reader.lastXref;
this.tokens = new PRTokeniser(reader.tokens.getSafeFile());
if (reader.decrypt != null)
this.decrypt = new PdfEncryption(reader.decrypt);
this.pValue = reader.pValue;
this.rValue = reader.rValue;
this.xrefObj = new ArrayList(reader.xrefObj);
for (int k = 0; k < reader.xrefObj.size(); ++k) {
this.xrefObj.set(k, duplicatePdfObject((PdfObject)reader.xrefObj.get(k), this));
}
this.pageRefs = new PageRefs(reader.pageRefs, this);
this.trailer = (PdfDictionary)duplicatePdfObject(reader.trailer, this);
this.catalog = (PdfDictionary)getPdfObject(trailer.get(PdfName.ROOT));
this.rootPages = (PdfDictionary)getPdfObject(catalog.get(PdfName.PAGES));
this.fileLength = reader.fileLength;
this.partial = reader.partial;
this.hybridXref = reader.hybridXref;
this.objStmToOffset = reader.objStmToOffset;
this.xref = reader.xref;
this.cryptoRef = (PRIndirectReference)duplicatePdfObject(reader.cryptoRef, this);
this.ownerPasswordUsed = reader.ownerPasswordUsed;
}
/** Gets a new file instance of the original PDF
* document.
* @return a new file instance of the original PDF document
*/
public RandomAccessFileOrArray getSafeFile() {
return tokens.getSafeFile();
}
protected PdfReaderInstance getPdfReaderInstance(PdfWriter writer) {
return new PdfReaderInstance(this, writer);
}
/** Gets the number of pages in the document.
* @return the number of pages in the document
*/
public int getNumberOfPages() {
return pageRefs.size();
}
/** Returns the document's catalog. This dictionary is not a copy,
* any changes will be reflected in the catalog.
* @return the document's catalog
*/
public PdfDictionary getCatalog() {
return catalog;
}
/** Returns the document's acroform, if it has one.
* @return the document's acroform
*/
public PRAcroForm getAcroForm() {
if (!acroFormParsed) {
acroFormParsed = true;
PdfObject form = catalog.get(PdfName.ACROFORM);
if (form != null) {
try {
acroForm = new PRAcroForm(this);
acroForm.readAcroForm((PdfDictionary)getPdfObject(form));
}
catch (Exception e) {
acroForm = null;
}
}
}
return acroForm;
}
/**
* Gets the page rotation. This value can be 0, 90, 180 or 270.
* @param index the page number. The first page is 1
* @return the page rotation
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -