001/*
002 * $Id: PRStream.java 4784 2011-03-15 08:33:00Z blowagie $
003 *
004 * This file is part of the iText (R) project.
005 * Copyright (c) 1998-2011 1T3XT BVBA
006 * Authors: Bruno Lowagie, Paulo Soares, et al.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU Affero General Public License version 3
010 * as published by the Free Software Foundation with the addition of the
011 * following permission added to Section 15 as permitted in Section 7(a):
012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT,
013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
014 *
015 * This program is distributed in the hope that it will be useful, but
016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
017 * or FITNESS FOR A PARTICULAR PURPOSE.
018 * See the GNU Affero General Public License for more details.
019 * You should have received a copy of the GNU Affero General Public License
020 * along with this program; if not, see http://www.gnu.org/licenses or write to
021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
022 * Boston, MA, 02110-1301 USA, or download the license from the following URL:
023 * http://itextpdf.com/terms-of-use/
024 *
025 * The interactive user interfaces in modified source and object code versions
026 * of this program must display Appropriate Legal Notices, as required under
027 * Section 5 of the GNU Affero General Public License.
028 *
029 * In accordance with Section 7(b) of the GNU Affero General Public License,
030 * a covered work must retain the producer line in every PDF that is created
031 * or manipulated using iText.
032 *
033 * You can be released from the requirements of the license by purchasing
034 * a commercial license. Buying such a license is mandatory as soon as you
035 * develop commercial activities involving the iText software without
036 * disclosing the source code of your own applications.
037 * These activities include: offering paid services to customers as an ASP,
038 * serving PDFs on the fly in a web application, shipping iText with a closed
039 * source product.
040 *
041 * For more information, please contact iText Software Corp. at this
042 * address: sales@itextpdf.com
043 */
044package com.itextpdf.text.pdf;
045
046import java.io.ByteArrayOutputStream;
047import java.io.IOException;
048import java.io.OutputStream;
049import java.util.zip.Deflater;
050import java.util.zip.DeflaterOutputStream;
051
052import com.itextpdf.text.Document;
053import com.itextpdf.text.ExceptionConverter;
054
055public class PRStream extends PdfStream {
056    
057    protected PdfReader reader;
058    protected int offset;
059    protected int length;
060    
061    //added by ujihara for decryption
062    protected int objNum = 0;
063    protected int objGen = 0;
064    
065    public PRStream(PRStream stream, PdfDictionary newDic) {
066        reader = stream.reader;
067        offset = stream.offset;
068        length = stream.length;
069        compressed = stream.compressed;
070        compressionLevel = stream.compressionLevel;
071        streamBytes = stream.streamBytes;
072        bytes = stream.bytes;
073        objNum = stream.objNum;
074        objGen = stream.objGen;
075        if (newDic != null)
076            putAll(newDic);
077        else
078            hashMap.putAll(stream.hashMap);
079    }
080
081    public PRStream(PRStream stream, PdfDictionary newDic, PdfReader reader) {
082        this(stream, newDic);
083        this.reader = reader;
084    }
085
086    public PRStream(PdfReader reader, int offset) {
087        this.reader = reader;
088        this.offset = offset;
089    }
090
091    public PRStream(PdfReader reader, byte conts[]) {
092        this(reader, conts, DEFAULT_COMPRESSION);
093    }
094
095    /**
096     * Creates a new PDF stream object that will replace a stream
097     * in a existing PDF file.
098     * @param   reader  the reader that holds the existing PDF
099     * @param   conts   the new content
100     * @param   compressionLevel        the compression level for the content
101     * @since   2.1.3 (replacing the existing constructor without param compressionLevel)
102     */
103    public PRStream(PdfReader reader, byte[] conts, int compressionLevel) {
104        this.reader = reader;
105        this.offset = -1;
106        if (Document.compress) {
107            try {
108                ByteArrayOutputStream stream = new ByteArrayOutputStream();
109                Deflater deflater = new Deflater(compressionLevel);
110                DeflaterOutputStream zip = new DeflaterOutputStream(stream, deflater);
111                zip.write(conts);
112                zip.close();
113                deflater.end();
114                bytes = stream.toByteArray();
115            }
116            catch (IOException ioe) {
117                throw new ExceptionConverter(ioe);
118            }
119            put(PdfName.FILTER, PdfName.FLATEDECODE);
120        }
121        else
122            bytes = conts;
123        setLength(bytes.length);
124    }
125    
126    /**
127     * Sets the data associated with the stream, either compressed or
128     * uncompressed. Note that the data will never be compressed if
129     * Document.compress is set to false.
130     * 
131     * @param data raw data, decrypted and uncompressed.
132     * @param compress true if you want the stream to be compressed.
133     * @since   iText 2.1.1
134     */
135    public void setData(byte[] data, boolean compress) {
136        setData(data, compress, DEFAULT_COMPRESSION);
137    }
138    
139    /**
140     * Sets the data associated with the stream, either compressed or
141     * uncompressed. Note that the data will never be compressed if
142     * Document.compress is set to false.
143     * 
144     * @param data raw data, decrypted and uncompressed.
145     * @param compress true if you want the stream to be compressed.
146     * @param compressionLevel  a value between -1 and 9 (ignored if compress == false)
147     * @since   iText 2.1.3
148     */
149    public void setData(byte[] data, boolean compress, int compressionLevel) {
150        remove(PdfName.FILTER);
151        this.offset = -1;
152        if (Document.compress && compress) {
153            try {
154                ByteArrayOutputStream stream = new ByteArrayOutputStream();
155                Deflater deflater = new Deflater(compressionLevel);
156                DeflaterOutputStream zip = new DeflaterOutputStream(stream, deflater);
157                zip.write(data);
158                zip.close();
159                deflater.end();
160                bytes = stream.toByteArray();
161                this.compressionLevel = compressionLevel;
162            }
163            catch (IOException ioe) {
164                throw new ExceptionConverter(ioe);
165            }
166            put(PdfName.FILTER, PdfName.FLATEDECODE);
167        }
168        else
169            bytes = data;
170        setLength(bytes.length);
171    }
172    
173    /**Sets the data associated with the stream
174     * @param data raw data, decrypted and uncompressed.
175     */
176    public void setData(byte[] data) {
177        setData(data, true);
178    }
179
180    public void setLength(int length) {
181        this.length = length;
182        put(PdfName.LENGTH, new PdfNumber(length));
183    }
184    
185    public int getOffset() {
186        return offset;
187    }
188    
189    public int getLength() {
190        return length;
191    }
192    
193    public PdfReader getReader() {
194        return reader;
195    }
196    
197    public byte[] getBytes() {
198        return bytes;
199    }
200    
201    public void setObjNum(int objNum, int objGen) {
202        this.objNum = objNum;
203        this.objGen = objGen;
204    }
205    
206    int getObjNum() {
207        return objNum;
208    }
209    
210    int getObjGen() {
211        return objGen;
212    }
213    
214    public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
215        byte[] b = PdfReader.getStreamBytesRaw(this);
216        PdfEncryption crypto = null;
217        if (writer != null)
218            crypto = writer.getEncryption();
219        PdfObject objLen = get(PdfName.LENGTH);
220        int nn = b.length;
221        if (crypto != null)
222            nn = crypto.calculateStreamSize(nn);
223        put(PdfName.LENGTH, new PdfNumber(nn));
224        superToPdf(writer, os);
225        put(PdfName.LENGTH, objLen);
226        os.write(STARTSTREAM);
227        if (length > 0) {
228            if (crypto != null && !crypto.isEmbeddedFilesOnly())
229                b = crypto.encryptByteArray(b);
230            os.write(b);
231        }
232        os.write(ENDSTREAM);
233    }
234}