PdfStamper.java

1
/*
2
 * Copyright 2003, 2004 by Paulo Soares.
3
 *
4
 * The contents of this file are subject to the Mozilla Public License Version 1.1
5
 * (the "License"); you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at http://www.mozilla.org/MPL/
7
 *
8
 * Software distributed under the License is distributed on an "AS IS" basis,
9
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10
 * for the specific language governing rights and limitations under the License.
11
 *
12
 * The Original Code is 'iText, a free JAVA-PDF library'.
13
 *
14
 * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
15
 * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
16
 * All Rights Reserved.
17
 * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
18
 * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
19
 *
20
 * Contributor(s): all the names of the contributors are added in the source code
21
 * where applicable.
22
 *
23
 * Alternatively, the contents of this file may be used under the terms of the
24
 * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
25
 * provisions of LGPL are applicable instead of those above.  If you wish to
26
 * allow use of your version of this file only under the terms of the LGPL
27
 * License and not to allow others to use your version of this file under
28
 * the MPL, indicate your decision by deleting the provisions above and
29
 * replace them with the notice and other provisions required by the LGPL.
30
 * If you do not delete the provisions above, a recipient may use your version
31
 * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
32
 *
33
 * This library is free software; you can redistribute it and/or modify it
34
 * under the terms of the MPL as stated above or under the terms of the GNU
35
 * Library General Public License as published by the Free Software Foundation;
36
 * either version 2 of the License, or any later version.
37
 *
38
 * This library is distributed in the hope that it will be useful, but WITHOUT
39
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
40
 * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
41
 * details.
42
 *
43
 * If you didn't download this code from the following link, you should check if
44
 * you aren't using an obsolete version:
45
 * http://www.lowagie.com/iText/
46
 */
47
package com.lowagie.text.pdf;
48
49
import java.io.File;
50
import java.io.FileOutputStream;
51
import java.io.IOException;
52
import java.io.InputStream;
53
import java.io.OutputStream;
54
import java.security.SignatureException;
55
import java.util.Calendar;
56
import java.util.List;
57
import java.util.Map;
58
import com.lowagie.text.error_messages.MessageLocalization;
59
60
import com.lowagie.text.DocWriter;
61
import com.lowagie.text.DocumentException;
62
63
import com.lowagie.text.Image;
64
import com.lowagie.text.Rectangle;
65
import com.lowagie.text.ExceptionConverter;
66
import com.lowagie.text.pdf.collection.PdfCollection;
67
import com.lowagie.text.pdf.interfaces.PdfEncryptionSettings;
68
import com.lowagie.text.pdf.interfaces.PdfViewerPreferences;
69
import java.security.cert.Certificate;
70
71
/** Applies extra content to the pages of a PDF document.
72
 * This extra content can be all the objects allowed in PdfContentByte
73
 * including pages from other Pdfs. The original PDF will keep
74
 * all the interactive elements including bookmarks, links and form fields.
75
 * <p>
76
 * It is also possible to change the field values and to
77
 * flatten them. New fields can be added but not flattened.
78
 * @author Paulo Soares (psoares@consiste.pt)
79
 */
80
public class PdfStamper
81
    implements PdfViewerPreferences, PdfEncryptionSettings {
82
    /**
83
     * The writer
84
     */    
85
    protected PdfStamperImp stamper;
86
    private Map<String, String> moreInfo;
87
    private boolean hasSignature;
88
    private PdfSignatureAppearance sigApp;
89
90
    /** Starts the process of adding extra content to an existing PDF
91
     * document.
92
     * @param reader the original document. It cannot be reused
93
     * @param os the output stream
94
     * @throws DocumentException on error
95
     * @throws IOException on error
96
     */
97
    public PdfStamper(PdfReader reader, OutputStream os) throws DocumentException, IOException {
98
        stamper = new PdfStamperImp(reader, os, '\0', false);
99
    }
100
101
    /**
102
     * Starts the process of adding extra content to an existing PDF
103
     * document.
104
     * @param reader the original document. It cannot be reused
105
     * @param os the output stream
106
     * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
107
     * document
108
     * @throws DocumentException on error
109
     * @throws IOException on error
110
     */
111
    public PdfStamper(PdfReader reader, OutputStream os, char pdfVersion) throws DocumentException, IOException {
112
        stamper = new PdfStamperImp(reader, os, pdfVersion, false);
113
    }
114
115
    /**
116
     * Starts the process of adding extra content to an existing PDF
117
     * document, possibly as a new revision.
118
     * @param reader the original document. It cannot be reused
119
     * @param os the output stream
120
     * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
121
     * document
122
     * @param append if <CODE>true</CODE> appends the document changes as a new revision. This is
123
     * only useful for multiple signatures as nothing is gained in speed or memory
124
     * @throws DocumentException on error
125
     * @throws IOException on error
126
     */
127
    public PdfStamper(PdfReader reader, OutputStream os, char pdfVersion, boolean append) throws DocumentException, IOException {
128
        stamper = new PdfStamperImp(reader, os, pdfVersion, append);
129
    }
130
131
    /** Gets the optional <CODE>String</CODE> map to add or change values in
132
     * the info dictionary.
133
     * @return the map or <CODE>null</CODE>
134
     *
135
     */
136
    public Map<String, String> getMoreInfo() {
137
        return this.moreInfo;
138
    }
139
140
    /** An optional <CODE>String</CODE> map to add or change values in
141
     * the info dictionary. Entries with <CODE>null</CODE>
142
     * values delete the key in the original info dictionary
143
     * @param moreInfo additional entries to the info dictionary
144
     *
145
     */
146
    public void setMoreInfo(Map<String, String> moreInfo) {
147
        this.moreInfo = moreInfo;
148
    }
149
150
    /**
151
     * Replaces a page from this document with a page from other document. Only the content
152
     * is replaced not the fields and annotations. This method must be called before 
153
     * getOverContent() or getUndercontent() are called for the same page.
154
     * @param r the <CODE>PdfReader</CODE> from where the new page will be imported
155
     * @param pageImported the page number of the imported page
156
     * @param pageReplaced the page to replace in this document
157
     * @since iText 2.1.1
158
     */
159
    public void replacePage(PdfReader r, int pageImported, int pageReplaced) {
160
        stamper.replacePage(r, pageImported, pageReplaced);
161
    }
162
    
163
    /**
164
     * Inserts a blank page. All the pages above and including <CODE>pageNumber</CODE> will
165
     * be shifted up. If <CODE>pageNumber</CODE> is bigger than the total number of pages
166
     * the new page will be the last one.
167
     * @param pageNumber the page number position where the new page will be inserted
168
     * @param mediabox the size of the new page
169
     */    
170
    public void insertPage(int pageNumber, Rectangle mediabox) {
171
        stamper.insertPage(pageNumber, mediabox);
172
    }
173
    
174
    /**
175
     * Gets the signing instance. The appearances and other parameters can the be set.
176
     * @return the signing instance
177
     */    
178
    public PdfSignatureAppearance getSignatureAppearance() {
179
        return sigApp;
180
    }
181
182
    /**
183
     * Closes the document. No more content can be written after the
184
     * document is closed.
185
     * <p>
186
     * If closing a signed document with an external signature the closing must be done
187
     * in the <CODE>PdfSignatureAppearance</CODE> instance.
188
     * @throws DocumentException on error
189
     * @throws IOException on error
190
     */
191
    public void close() throws DocumentException, IOException {
192 1 1. close : negated conditional → NO_COVERAGE
        if (!hasSignature) {
193 1 1. close : removed call to com/lowagie/text/pdf/PdfStamperImp::close → NO_COVERAGE
            stamper.close(moreInfo);
194
            return;
195
        }
196 1 1. close : removed call to com/lowagie/text/pdf/PdfSignatureAppearance::preClose → NO_COVERAGE
        sigApp.preClose();
197
        PdfSigGenericPKCS sig = sigApp.getSigStandard();
198
        PdfLiteral lit = (PdfLiteral)sig.get(PdfName.CONTENTS);
199 2 1. close : Replaced integer subtraction with addition → NO_COVERAGE
2. close : Replaced integer division with multiplication → NO_COVERAGE
        int totalBuf = (lit.getPosLength() - 2) / 2;
200
        byte[] buf = new byte[8192];
201
        int n;
202
        InputStream inp = sigApp.getRangeStream();
203
        try {
204 2 1. close : changed conditional boundary → NO_COVERAGE
2. close : negated conditional → NO_COVERAGE
            while ((n = inp.read(buf)) > 0) {
205 1 1. close : removed call to com/lowagie/text/pdf/PdfPKCS7::update → NO_COVERAGE
                sig.getSigner().update(buf, 0, n);
206
            }
207
        }
208
        catch (SignatureException se) {
209
            throw new ExceptionConverter(se);
210
        }
211
        buf = new byte[totalBuf];
212
        byte[] bsig = sig.getSignerContents();
213 1 1. close : removed call to java/lang/System::arraycopy → NO_COVERAGE
        System.arraycopy(bsig, 0, buf, 0, bsig.length);
214
        PdfString str = new PdfString(buf);
215
        str.setHexWriting(true);
216
        PdfDictionary dic = new PdfDictionary();
217 1 1. close : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE
        dic.put(PdfName.CONTENTS, str);
218 1 1. close : removed call to com/lowagie/text/pdf/PdfSignatureAppearance::close → NO_COVERAGE
        sigApp.close(dic);
219 1 1. close : removed call to com/lowagie/text/pdf/PdfReader::close → NO_COVERAGE
        stamper.reader.close();
220
    }
221
222
    /** Gets a <CODE>PdfContentByte</CODE> to write under the page of
223
     * the original document.
224
     * @param pageNum the page number where the extra content is written
225
     * @return a <CODE>PdfContentByte</CODE> to write under the page of
226
     * the original document
227
     */
228
    public PdfContentByte getUnderContent(int pageNum) {
229
        return stamper.getUnderContent(pageNum);
230
    }
231
232
    /** Gets a <CODE>PdfContentByte</CODE> to write over the page of
233
     * the original document.
234
     * @param pageNum the page number where the extra content is written
235
     * @return a <CODE>PdfContentByte</CODE> to write over the page of
236
     * the original document
237
     */
238
    public PdfContentByte getOverContent(int pageNum) {
239
        return stamper.getOverContent(pageNum);
240
    }
241
242
    /** Checks if the content is automatically adjusted to compensate
243
     * the original page rotation.
244
     * @return the auto-rotation status
245
     */
246
    public boolean isRotateContents() {
247
        return stamper.isRotateContents();
248
    }
249
250
    /** Flags the content to be automatically adjusted to compensate
251
     * the original page rotation. The default is <CODE>true</CODE>.
252
     * @param rotateContents <CODE>true</CODE> to set auto-rotation, <CODE>false</CODE>
253
     * otherwise
254
     */
255
    public void setRotateContents(boolean rotateContents) {
256
        stamper.setRotateContents(rotateContents);
257
    }
258
259
    /** Sets the encryption options for this document. The userPassword and the
260
     *  ownerPassword can be null or have zero length. In this case the ownerPassword
261
     *  is replaced by a random string. The open permissions for the document can be
262
     *  AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
263
     *  AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
264
     *  The permissions can be combined by ORing them.
265
     * @param userPassword the user password. Can be null or empty
266
     * @param ownerPassword the owner password. Can be null or empty
267
     * @param permissions the user permissions
268
     * @param strength128Bits <code>true</code> for 128 bit key length, <code>false</code> for 40 bit key length
269
     * @throws DocumentException if anything was already written to the output
270
     */
271
    public void setEncryption(byte[] userPassword, byte[] ownerPassword, int permissions, boolean strength128Bits) throws DocumentException {
272 1 1. setEncryption : negated conditional → NO_COVERAGE
        if (stamper.isAppend())
273
            throw new DocumentException(MessageLocalization.getComposedMessage("append.mode.does.not.support.changing.the.encryption.status"));
274 1 1. setEncryption : negated conditional → NO_COVERAGE
        if (stamper.isContentWritten())
275
            throw new DocumentException(MessageLocalization.getComposedMessage("content.was.already.written.to.the.output"));
276 2 1. setEncryption : negated conditional → NO_COVERAGE
2. setEncryption : removed call to com/lowagie/text/pdf/PdfStamperImp::setEncryption → NO_COVERAGE
        stamper.setEncryption(userPassword, ownerPassword, permissions, strength128Bits ? PdfWriter.STANDARD_ENCRYPTION_128 : PdfWriter.STANDARD_ENCRYPTION_40);
277
    }
278
279
    /** Sets the encryption options for this document. The userPassword and the
280
     *  ownerPassword can be null or have zero length. In this case the ownerPassword
281
     *  is replaced by a random string. The open permissions for the document can be
282
     *  AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
283
     *  AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
284
     *  The permissions can be combined by ORing them.
285
     * @param userPassword the user password. Can be null or empty
286
     * @param ownerPassword the owner password. Can be null or empty
287
     * @param permissions the user permissions
288
     * @param encryptionType the type of encryption. It can be one of STANDARD_ENCRYPTION_40, STANDARD_ENCRYPTION_128 or ENCRYPTION_AES128.
289
     * Optionally DO_NOT_ENCRYPT_METADATA can be ored to output the metadata in cleartext
290
     * @throws DocumentException if the document is already open
291
     */
292
    public void setEncryption(byte[] userPassword, byte[] ownerPassword, int permissions, int encryptionType) throws DocumentException {
293 1 1. setEncryption : negated conditional → NO_COVERAGE
        if (stamper.isAppend())
294
            throw new DocumentException(MessageLocalization.getComposedMessage("append.mode.does.not.support.changing.the.encryption.status"));
295 1 1. setEncryption : negated conditional → NO_COVERAGE
        if (stamper.isContentWritten())
296
            throw new DocumentException(MessageLocalization.getComposedMessage("content.was.already.written.to.the.output"));
297 1 1. setEncryption : removed call to com/lowagie/text/pdf/PdfStamperImp::setEncryption → NO_COVERAGE
        stamper.setEncryption(userPassword, ownerPassword, permissions, encryptionType);
298
    }
299
300
    /**
301
     * Sets the encryption options for this document. The userPassword and the
302
     *  ownerPassword can be null or have zero length. In this case the ownerPassword
303
     *  is replaced by a random string. The open permissions for the document can be
304
     *  AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
305
     *  AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
306
     *  The permissions can be combined by ORing them.
307
     * @param strength <code>true</code> for 128 bit key length, <code>false</code> for 40 bit key length
308
     * @param userPassword the user password. Can be null or empty
309
     * @param ownerPassword the owner password. Can be null or empty
310
     * @param permissions the user permissions
311
     * @throws DocumentException if anything was already written to the output
312
     */
313
    public void setEncryption(boolean strength, String userPassword, String ownerPassword, int permissions) throws DocumentException {
314 1 1. setEncryption : removed call to com/lowagie/text/pdf/PdfStamper::setEncryption → NO_COVERAGE
        setEncryption(DocWriter.getISOBytes(userPassword), DocWriter.getISOBytes(ownerPassword), permissions, strength);
315
    }
316
317
    /**
318
     * Sets the encryption options for this document. The userPassword and the
319
     *  ownerPassword can be null or have zero length. In this case the ownerPassword
320
     *  is replaced by a random string. The open permissions for the document can be
321
     *  AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
322
     *  AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
323
     *  The permissions can be combined by ORing them.
324
     * @param encryptionType the type of encryption. It can be one of STANDARD_ENCRYPTION_40, STANDARD_ENCRYPTION_128 or ENCRYPTION_AES128.
325
     * Optionally DO_NOT_ENCRYPT_METADATA can be ored to output the metadata in cleartext
326
     * @param userPassword the user password. Can be null or empty
327
     * @param ownerPassword the owner password. Can be null or empty
328
     * @param permissions the user permissions
329
     * @throws DocumentException if anything was already written to the output
330
     */
331
    public void setEncryption(int encryptionType, String userPassword, String ownerPassword, int permissions) throws DocumentException {
332 1 1. setEncryption : removed call to com/lowagie/text/pdf/PdfStamper::setEncryption → NO_COVERAGE
        setEncryption(DocWriter.getISOBytes(userPassword), DocWriter.getISOBytes(ownerPassword), permissions, encryptionType);
333
    }
334
335
    /**
336
     * Sets the certificate encryption options for this document. An array of one or more public certificates
337
     * must be provided together with an array of the same size for the permissions for each certificate.
338
     *  The open permissions for the document can be
339
     *  AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
340
     *  AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
341
     *  The permissions can be combined by ORing them.
342
     * Optionally DO_NOT_ENCRYPT_METADATA can be ored to output the metadata in cleartext
343
     * @param certs the public certificates to be used for the encryption
344
     * @param permissions the user permissions for each of the certificates
345
     * @param encryptionType the type of encryption. It can be one of STANDARD_ENCRYPTION_40, STANDARD_ENCRYPTION_128 or ENCRYPTION_AES128.
346
     * @throws DocumentException if the encryption was set too late
347
     */
348
     public void setEncryption(Certificate[] certs, int[] permissions, int encryptionType) throws DocumentException {
349 1 1. setEncryption : negated conditional → NO_COVERAGE
        if (stamper.isAppend())
350
            throw new DocumentException(MessageLocalization.getComposedMessage("append.mode.does.not.support.changing.the.encryption.status"));
351 1 1. setEncryption : negated conditional → NO_COVERAGE
        if (stamper.isContentWritten())
352
            throw new DocumentException(MessageLocalization.getComposedMessage("content.was.already.written.to.the.output"));
353 1 1. setEncryption : removed call to com/lowagie/text/pdf/PdfStamperImp::setEncryption → NO_COVERAGE
        stamper.setEncryption(certs, permissions, encryptionType);
354
     }
355
     
356
    /** Gets a page from other PDF document. Note that calling this method more than
357
     * once with the same parameters will retrieve the same object.
358
     * @param reader the PDF document where the page is
359
     * @param pageNumber the page number. The first page is 1
360
     * @return the template representing the imported page
361
     */
362
    public PdfImportedPage getImportedPage(PdfReader reader, int pageNumber) {
363
        return stamper.getImportedPage(reader, pageNumber);
364
    }
365
366
    /** Gets the underlying PdfWriter.
367
     * @return the underlying PdfWriter
368
     */
369
    public PdfWriter getWriter() {
370
        return stamper;
371
    }
372
373
    /** Gets the underlying PdfReader.
374
     * @return the underlying PdfReader
375
     */
376
    public PdfReader getReader() {
377 1 1. getReader : mutated return of Object value for com/lowagie/text/pdf/PdfStamper::getReader to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE
        return stamper.reader;
378
    }
379
380
    /** Gets the <CODE>AcroFields</CODE> object that allows to get and set field values
381
     * and to merge FDF forms.
382
     * @return the <CODE>AcroFields</CODE> object
383
     */
384
    public AcroFields getAcroFields() {
385
        return stamper.getAcroFields();
386
    }
387
388
    /** Determines if the fields are flattened on close. The fields added with
389
     * {@link #addAnnotation(PdfAnnotation,int)} will never be flattened.
390
     * @param flat <CODE>true</CODE> to flatten the fields, <CODE>false</CODE>
391
     * to keep the fields
392
     */
393
    public void setFormFlattening(boolean flat) {
394
        stamper.setFormFlattening(flat);
395
    }
396
397
    /** Determines if the FreeText annotations are flattened on close. 
398
     * @param flat <CODE>true</CODE> to flatten the FreeText annotations, <CODE>false</CODE>
399
     * (the default) to keep the FreeText annotations as active content.
400
     */
401
    public void setFreeTextFlattening(boolean flat) {
402
        stamper.setFreeTextFlattening(flat);
403
    }
404
405
    /**
406
     * Adds an annotation of form field in a specific page. This page number
407
     * can be overridden with {@link PdfAnnotation#setPlaceInPage(int)}.
408
     * @param annot the annotation
409
     * @param page the page
410
     */
411
    public void addAnnotation(PdfAnnotation annot, int page) {
412
        stamper.addAnnotation(annot, page);
413
    }
414
415
    /**
416
     * Adds an empty signature.
417
     * @param name    the name of the signature
418
     * @param page    the page number
419
     * @param llx    lower left x coordinate of the signature's position
420
     * @param lly    lower left y coordinate of the signature's position
421
     * @param urx    upper right x coordinate of the signature's position
422
     * @param ury    upper right y coordinate of the signature's position
423
     * @return    a signature form field
424
     * @since    2.1.4
425
     */
426
    public PdfFormField addSignature(String name, int page, float llx, float lly, float urx, float ury) {
427
        PdfAcroForm acroForm = stamper.getAcroForm();
428
        PdfFormField signature = PdfFormField.createSignature(stamper);
429 1 1. addSignature : removed call to com/lowagie/text/pdf/PdfAcroForm::setSignatureParams → NO_COVERAGE
        acroForm.setSignatureParams(signature, name, llx, lly, urx, ury);
430 1 1. addSignature : removed call to com/lowagie/text/pdf/PdfAcroForm::drawSignatureAppearences → NO_COVERAGE
        acroForm.drawSignatureAppearences(signature, llx, lly, urx, ury);
431 1 1. addSignature : removed call to com/lowagie/text/pdf/PdfStamper::addAnnotation → NO_COVERAGE
        addAnnotation(signature, page);
432 1 1. addSignature : mutated return of Object value for com/lowagie/text/pdf/PdfStamper::addSignature to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE
        return signature;
433
    }
434
    
435
    /**
436
     * Adds the comments present in an FDF file.
437
     * @param fdf the FDF file
438
     * @throws IOException on error
439
     */    
440
    public void addComments(FdfReader fdf) throws IOException {
441
        stamper.addComments(fdf);
442
    }
443
    
444
    /**
445
     * Sets the bookmarks. The list structure is defined in
446
     * {@link SimpleBookmark}.
447
     * @param outlines the bookmarks or <CODE>null</CODE> to remove any
448
     */
449
    public void setOutlines(List outlines) {
450
        stamper.setOutlines(outlines);
451
    }
452
453
    /**
454
     * Sets the thumbnail image for a page.
455
     * @param image the image
456
     * @param page the page
457
     * @throws PdfException on error
458
     * @throws DocumentException on error
459
     */    
460
    public void setThumbnail(Image image, int page) throws DocumentException {
461
        stamper.setThumbnail(image, page);
462
    }
463
    
464
    /**
465
     * Adds <CODE>name</CODE> to the list of fields that will be flattened on close,
466
     * all the other fields will remain. If this method is never called or is called
467
     * with invalid field names, all the fields will be flattened.
468
     * <p>
469
     * Calling <CODE>setFormFlattening(true)</CODE> is needed to have any kind of
470
     * flattening.
471
     * @param name the field name
472
     * @return <CODE>true</CODE> if the field exists, <CODE>false</CODE> otherwise
473
     */
474
    public boolean partialFormFlattening(String name) {
475
        return stamper.partialFormFlattening(name);
476
    }
477
478
    /** Adds a JavaScript action at the document level. When the document
479
     * opens all this JavaScript runs. The existing JavaScript will be replaced.
480
     * @param js the JavaScript code
481
     */
482
    public void addJavaScript(String js) {
483 2 1. addJavaScript : negated conditional → NO_COVERAGE
2. addJavaScript : removed call to com/lowagie/text/pdf/PdfStamperImp::addJavaScript → NO_COVERAGE
        stamper.addJavaScript(js, !PdfEncodings.isPdfDocEncoding(js));
484
    }
485
486
    /** Adds a file attachment at the document level. Existing attachments will be kept.
487
     * @param description the file description
488
     * @param fileStore an array with the file. If it's <CODE>null</CODE>
489
     * the file will be read from the disk
490
     * @param file the path to the file. It will only be used if
491
     * <CODE>fileStore</CODE> is not <CODE>null</CODE>
492
     * @param fileDisplay the actual file name stored in the pdf
493
     * @throws IOException on error
494
     */    
495
    public void addFileAttachment(String description, byte[] fileStore, String file, String fileDisplay) throws IOException {
496 1 1. addFileAttachment : removed call to com/lowagie/text/pdf/PdfStamper::addFileAttachment → NO_COVERAGE
        addFileAttachment(description, PdfFileSpecification.fileEmbedded(stamper, file, fileDisplay, fileStore));
497
    }
498
499
    /** Adds a file attachment at the document level. Existing attachments will be kept.
500
     * @param description the file description
501
     * @param fs the file specification
502
     */    
503
    public void addFileAttachment(String description, PdfFileSpecification fs) throws IOException {
504
        stamper.addFileAttachment(description, fs);
505
    }
506
507
    /**
508
     * This is the most simple way to change a PDF into a
509
     * portable collection. Choose one of the following names:
510
     * <ul>
511
     * <li>PdfName.D (detailed view)
512
     * <li>PdfName.T (tiled view)
513
     * <li>PdfName.H (hidden)
514
     * </ul>
515
     * Pass this name as a parameter and your PDF will be
516
     * a portable collection with all the embedded and
517
     * attached files as entries.
518
     * @param initialView can be PdfName.D, PdfName.T or PdfName.H
519
     */
520
    public void makePackage( PdfName initialView ) {
521
        PdfCollection collection = new PdfCollection(0);
522 1 1. makePackage : removed call to com/lowagie/text/pdf/collection/PdfCollection::put → NO_COVERAGE
        collection.put(PdfName.VIEW, initialView);
523 1 1. makePackage : removed call to com/lowagie/text/pdf/PdfStamperImp::makePackage → NO_COVERAGE
        stamper.makePackage( collection );
524
    }
525
526
    /**
527
     * Adds or replaces the Collection Dictionary in the Catalog.
528
     * @param    collection    the new collection dictionary.
529
     */
530
    public void makePackage(PdfCollection collection) {
531
        stamper.makePackage(collection);        
532
    }
533
    
534
    /**
535
     * Sets the viewer preferences.
536
     * @param preferences the viewer preferences
537
     * @see PdfViewerPreferences#setViewerPreferences(int)
538
     */
539
    public void setViewerPreferences(int preferences) {
540
        stamper.setViewerPreferences(preferences);
541
    }
542
    
543
    /** Adds a viewer preference
544
     * @param key a key for a viewer preference
545
     * @param value the value for the viewer preference
546
     * @see PdfViewerPreferences#addViewerPreference
547
     */
548
    
549
    public void addViewerPreference(PdfName key, PdfObject value) {
550
        stamper.addViewerPreference(key, value);
551
    }
552
553
    /**
554
     * Sets the XMP metadata.
555
     * @param xmp
556
     * @see PdfWriter#setXmpMetadata(byte[])
557
     */
558
    public void setXmpMetadata(byte[] xmp) {
559
        stamper.setXmpMetadata(xmp);
560
    }
561
562
    /**
563
     * Gets the 1.5 compression status.
564
     * @return <code>true</code> if the 1.5 compression is on
565
     */
566
    public boolean isFullCompression() {
567
        return stamper.isFullCompression();
568
    }
569
570
    /**
571
     * Sets the document's compression to the new 1.5 mode with object streams and xref
572
     * streams. It can be set at any time but once set it can't be unset.
573
     */
574
    public void setFullCompression() {
575 1 1. setFullCompression : negated conditional → NO_COVERAGE
        if (stamper.isAppend())
576
            return;
577 1 1. setFullCompression : removed call to com/lowagie/text/pdf/PdfStamperImp::setFullCompression → NO_COVERAGE
        stamper.setFullCompression();
578
    }
579
580
    /**
581
     * Sets the open and close page additional action.
582
     * @param actionType the action type. It can be <CODE>PdfWriter.PAGE_OPEN</CODE>
583
     * or <CODE>PdfWriter.PAGE_CLOSE</CODE>
584
     * @param action the action to perform
585
     * @param page the page where the action will be applied. The first page is 1
586
     * @throws PdfException if the action type is invalid
587
     */    
588
    public void setPageAction(PdfName actionType, PdfAction action, int page) throws PdfException {
589
        stamper.setPageAction(actionType, action, page);
590
    }
591
592
    /**
593
     * Sets the display duration for the page (for presentations)
594
     * @param seconds   the number of seconds to display the page. A negative value removes the entry
595
     * @param page the page where the duration will be applied. The first page is 1
596
     */
597
    public void setDuration(int seconds, int page) {
598
        stamper.setDuration(seconds, page);
599
    }
600
    
601
    /**
602
     * Sets the transition for the page
603
     * @param transition   the transition object. A <code>null</code> removes the transition
604
     * @param page the page where the transition will be applied. The first page is 1
605
     */
606
    public void setTransition(PdfTransition transition, int page) {
607
        stamper.setTransition(transition, page);
608
    }
609
610
    /**
611
     * Applies a digital signature to a document, possibly as a new revision, making
612
     * possible multiple signatures. The returned PdfStamper
613
     * can be used normally as the signature is only applied when closing.
614
     * <p>
615
     * A possible use for adding a signature without invalidating an existing one is:
616
     * <p>
617
     * <pre>
618
     * KeyStore ks = KeyStore.getInstance("pkcs12");
619
     * ks.load(new FileInputStream("my_private_key.pfx"), "my_password".toCharArray());
620
     * String alias = (String)ks.aliases().nextElement();
621
     * PrivateKey key = (PrivateKey)ks.getKey(alias, "my_password".toCharArray());
622
     * Certificate[] chain = ks.getCertificateChain(alias);
623
     * PdfReader reader = new PdfReader("original.pdf");
624
     * FileOutputStream fout = new FileOutputStream("signed.pdf");
625
     * PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0', new
626
     * File("/temp"), true);
627
     * PdfSignatureAppearance sap = stp.getSignatureAppearance();
628
     * sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
629
     * sap.setReason("I'm the author");
630
     * sap.setLocation("Lisbon");
631
     * // comment next line to have an invisible signature
632
     * sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
633
     * stp.close();
634
     * </pre>
635
     * @param reader the original document
636
     * @param os the output stream or <CODE>null</CODE> to keep the document in the temporary file
637
     * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
638
     * document
639
     * @param tempFile location of the temporary file. If it's a directory a temporary file will be created there.
640
     *     If it's a file it will be used directly. The file will be deleted on exit unless <CODE>os</CODE> is null.
641
     *     In that case the document can be retrieved directly from the temporary file. If it's <CODE>null</CODE>
642
     *     no temporary file will be created and memory will be used
643
     * @param append if <CODE>true</CODE> the signature and all the other content will be added as a
644
     * new revision thus not invalidating existing signatures
645
     * @return a <CODE>PdfStamper</CODE>
646
     * @throws DocumentException on error
647
     * @throws IOException on error
648
     */
649
    public static PdfStamper createSignature(PdfReader reader, OutputStream os, char pdfVersion, File tempFile, boolean append) throws DocumentException, IOException {
650
        PdfStamper stp;
651 1 1. createSignature : negated conditional → NO_COVERAGE
        if (tempFile == null) {
652
            ByteBuffer bout = new ByteBuffer();
653
            stp = new PdfStamper(reader, bout, pdfVersion, append);
654
            stp.sigApp = new PdfSignatureAppearance(stp.stamper);
655 1 1. createSignature : removed call to com/lowagie/text/pdf/PdfSignatureAppearance::setSigout → NO_COVERAGE
            stp.sigApp.setSigout(bout);
656
        }
657
        else {
658 1 1. createSignature : negated conditional → NO_COVERAGE
            if (tempFile.isDirectory())
659
                tempFile = File.createTempFile("pdf", null, tempFile);
660
            FileOutputStream fout = new FileOutputStream(tempFile);
661
            stp = new PdfStamper(reader, fout, pdfVersion, append);
662
            stp.sigApp = new PdfSignatureAppearance(stp.stamper);
663 1 1. createSignature : removed call to com/lowagie/text/pdf/PdfSignatureAppearance::setTempFile → NO_COVERAGE
            stp.sigApp.setTempFile(tempFile);
664
        }
665 1 1. createSignature : removed call to com/lowagie/text/pdf/PdfSignatureAppearance::setOriginalout → NO_COVERAGE
        stp.sigApp.setOriginalout(os);
666 1 1. createSignature : removed call to com/lowagie/text/pdf/PdfSignatureAppearance::setStamper → NO_COVERAGE
        stp.sigApp.setStamper(stp);
667
        stp.hasSignature = true;
668
        PdfDictionary catalog = reader.getCatalog();
669
        PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.ACROFORM), catalog);
670 1 1. createSignature : negated conditional → NO_COVERAGE
        if (acroForm != null) {
671 1 1. createSignature : removed call to com/lowagie/text/pdf/PdfDictionary::remove → NO_COVERAGE
            acroForm.remove(PdfName.NEEDAPPEARANCES);
672 1 1. createSignature : removed call to com/lowagie/text/pdf/PdfStamperImp::markUsed → NO_COVERAGE
            stp.stamper.markUsed(acroForm);
673
        }
674 1 1. createSignature : mutated return of Object value for com/lowagie/text/pdf/PdfStamper::createSignature to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE
        return stp;
675
    }
676
677
    /**
678
     * Applies a digital signature to a document. The returned PdfStamper
679
     * can be used normally as the signature is only applied when closing.
680
     * <p>
681
     * Note that the pdf is created in memory.
682
     * <p>
683
     * A possible use is:
684
     * <p>
685
     * <pre>
686
     * KeyStore ks = KeyStore.getInstance("pkcs12");
687
     * ks.load(new FileInputStream("my_private_key.pfx"), "my_password".toCharArray());
688
     * String alias = (String)ks.aliases().nextElement();
689
     * PrivateKey key = (PrivateKey)ks.getKey(alias, "my_password".toCharArray());
690
     * Certificate[] chain = ks.getCertificateChain(alias);
691
     * PdfReader reader = new PdfReader("original.pdf");
692
     * FileOutputStream fout = new FileOutputStream("signed.pdf");
693
     * PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0');
694
     * PdfSignatureAppearance sap = stp.getSignatureAppearance();
695
     * sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
696
     * sap.setReason("I'm the author");
697
     * sap.setLocation("Lisbon");
698
     * // comment next line to have an invisible signature
699
     * sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
700
     * stp.close();
701
     * </pre>
702
     * @param reader the original document
703
     * @param os the output stream
704
     * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
705
     * document
706
     * @throws DocumentException on error
707
     * @throws IOException on error
708
     * @return a <CODE>PdfStamper</CODE>
709
     */
710
    public static PdfStamper createSignature(PdfReader reader, OutputStream os, char pdfVersion) throws DocumentException, IOException {
711 1 1. createSignature : mutated return of Object value for com/lowagie/text/pdf/PdfStamper::createSignature to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE
        return createSignature(reader, os, pdfVersion, null, false);
712
    }
713
    
714
    /**
715
     * Applies a digital signature to a document. The returned PdfStamper
716
     * can be used normally as the signature is only applied when closing.
717
     * <p>
718
     * A possible use is:
719
     * <p>
720
     * <pre>
721
     * KeyStore ks = KeyStore.getInstance("pkcs12");
722
     * ks.load(new FileInputStream("my_private_key.pfx"), "my_password".toCharArray());
723
     * String alias = (String)ks.aliases().nextElement();
724
     * PrivateKey key = (PrivateKey)ks.getKey(alias, "my_password".toCharArray());
725
     * Certificate[] chain = ks.getCertificateChain(alias);
726
     * PdfReader reader = new PdfReader("original.pdf");
727
     * FileOutputStream fout = new FileOutputStream("signed.pdf");
728
     * PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0', new File("/temp"));
729
     * PdfSignatureAppearance sap = stp.getSignatureAppearance();
730
     * sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
731
     * sap.setReason("I'm the author");
732
     * sap.setLocation("Lisbon");
733
     * // comment next line to have an invisible signature
734
     * sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
735
     * stp.close();
736
     * </pre>
737
     * @param reader the original document
738
     * @param os the output stream or <CODE>null</CODE> to keep the document in the temporary file
739
     * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
740
     * document
741
     * @param tempFile location of the temporary file. If it's a directory a temporary file will be created there.
742
     *     If it's a file it will be used directly. The file will be deleted on exit unless <CODE>os</CODE> is null.
743
     *     In that case the document can be retrieved directly from the temporary file. If it's <CODE>null</CODE>
744
     *     no temporary file will be created and memory will be used
745
     * @return a <CODE>PdfStamper</CODE>
746
     * @throws DocumentException on error
747
     * @throws IOException on error
748
     */
749
    public static PdfStamper createSignature(PdfReader reader, OutputStream os, char pdfVersion, File tempFile) throws DocumentException, IOException 
750
    {
751 1 1. createSignature : mutated return of Object value for com/lowagie/text/pdf/PdfStamper::createSignature to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE
        return createSignature(reader, os, pdfVersion, tempFile, false);
752
    }
753
    
754
    /**
755
     * Gets the PdfLayer objects in an existing document as a Map
756
     * with the names/titles of the layers as keys.
757
     * @return    a Map with all the PdfLayers in the document (and the name/title of the layer as key)
758
     * @since    2.1.2
759
     */
760
    public Map getPdfLayers() {
761
        return stamper.getPdfLayers();
762
    }
763
764
    /**
765
     * Specifies if the file ID property should be included in the PDF file header when creating and stamping the PDF file.
766
     *
767
     * @since OpenPDF 1.2.1
768
     * @date 25. aug 2018
769
     * @see PdfName#ID
770
     *
771
     * @param includeFileID
772
     */
773
    public void setIncludeFileID(boolean includeFileID) {
774
        this.stamper.setIncludeFileID(includeFileID);
775
    }
776
777
    /**
778
     * Returns if the file ID property should be included in the PDF file header when creating and signing the PDF file.
779
     *
780
     * @since OpenPDF 1.2.1
781
     * @date 25. aug 2018
782
     * @see PdfName#ID
783
     *
784
     * @return boolean
785
     */
786
    public boolean isIncludeFileID() {
787
        return stamper.isIncludeFileID();
788
    }
789
790
    /**
791
     * Specifies the enforced PDF file ID, used to specifically override the PDF file ID when creating and signing the PDF file.
792
     *
793
     * @param overrideFileId
794
     * @since OpenPDF 1.2.1
795
     * @date 25. aug 2018
796
     * @see PdfName#ID
797
     */
798
    public void setOverrideFileId(PdfObject overrideFileId) {
799
        this.stamper.setOverrideFileId(overrideFileId);
800
    }
801
802
    /**
803
     * Returns the enforced PDF file ID, used to specifically override the created PDF file ID when creating and signing the PDF file.
804
     *
805
     * @date 25. aug 2018
806
     * @since OpenPDF 1.2.1
807
     * @see PdfName#ID
808
     * @return PdfObject
809
     */
810
    public PdfObject getOverrideFileId() {
811
        return stamper.getOverrideFileId();
812
    }
813
814
    /**
815
     * Returns the enforced modification date, used to specifically override the PDF modification date (ModDate) property when creating and signing the PDF file.
816
     *
817
     * @since OpenPDF 1.2.1
818
     * @date 25. aug 2018
819
     * @see PdfName#MODDATE
820
     * @return Calendar
821
     */
822
    public Calendar getEnforcedModificationDate() {
823
        return stamper.getModificationDate();
824
    }
825
826
    /**
827
     * Specifies the enforced modification date, used to specifically override the PDF modification date (ModDate) property when creating and signing the PDF file.
828
     *
829
     * @date 25. aug 2018
830
     * @since OpenPDF 1.2.1
831
     * @see PdfName#MODDATE
832
     * @param modificationDate enforced modification date.
833
     */
834
    public void setEnforcedModificationDate(Calendar modificationDate) {
835
        this.stamper.setModificationDate(modificationDate);
836
    }
837
838
}

Mutations

192

1.1
Location : close
Killed by : none
negated conditional → NO_COVERAGE

193

1.1
Location : close
Killed by : none
removed call to com/lowagie/text/pdf/PdfStamperImp::close → NO_COVERAGE

196

1.1
Location : close
Killed by : none
removed call to com/lowagie/text/pdf/PdfSignatureAppearance::preClose → NO_COVERAGE

199

1.1
Location : close
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

2.2
Location : close
Killed by : none
Replaced integer division with multiplication → NO_COVERAGE

204

1.1
Location : close
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : close
Killed by : none
negated conditional → NO_COVERAGE

205

1.1
Location : close
Killed by : none
removed call to com/lowagie/text/pdf/PdfPKCS7::update → NO_COVERAGE

213

1.1
Location : close
Killed by : none
removed call to java/lang/System::arraycopy → NO_COVERAGE

217

1.1
Location : close
Killed by : none
removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE

218

1.1
Location : close
Killed by : none
removed call to com/lowagie/text/pdf/PdfSignatureAppearance::close → NO_COVERAGE

219

1.1
Location : close
Killed by : none
removed call to com/lowagie/text/pdf/PdfReader::close → NO_COVERAGE

272

1.1
Location : setEncryption
Killed by : none
negated conditional → NO_COVERAGE

274

1.1
Location : setEncryption
Killed by : none
negated conditional → NO_COVERAGE

276

1.1
Location : setEncryption
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : setEncryption
Killed by : none
removed call to com/lowagie/text/pdf/PdfStamperImp::setEncryption → NO_COVERAGE

293

1.1
Location : setEncryption
Killed by : none
negated conditional → NO_COVERAGE

295

1.1
Location : setEncryption
Killed by : none
negated conditional → NO_COVERAGE

297

1.1
Location : setEncryption
Killed by : none
removed call to com/lowagie/text/pdf/PdfStamperImp::setEncryption → NO_COVERAGE

314

1.1
Location : setEncryption
Killed by : none
removed call to com/lowagie/text/pdf/PdfStamper::setEncryption → NO_COVERAGE

332

1.1
Location : setEncryption
Killed by : none
removed call to com/lowagie/text/pdf/PdfStamper::setEncryption → NO_COVERAGE

349

1.1
Location : setEncryption
Killed by : none
negated conditional → NO_COVERAGE

351

1.1
Location : setEncryption
Killed by : none
negated conditional → NO_COVERAGE

353

1.1
Location : setEncryption
Killed by : none
removed call to com/lowagie/text/pdf/PdfStamperImp::setEncryption → NO_COVERAGE

377

1.1
Location : getReader
Killed by : none
mutated return of Object value for com/lowagie/text/pdf/PdfStamper::getReader to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE

429

1.1
Location : addSignature
Killed by : none
removed call to com/lowagie/text/pdf/PdfAcroForm::setSignatureParams → NO_COVERAGE

430

1.1
Location : addSignature
Killed by : none
removed call to com/lowagie/text/pdf/PdfAcroForm::drawSignatureAppearences → NO_COVERAGE

431

1.1
Location : addSignature
Killed by : none
removed call to com/lowagie/text/pdf/PdfStamper::addAnnotation → NO_COVERAGE

432

1.1
Location : addSignature
Killed by : none
mutated return of Object value for com/lowagie/text/pdf/PdfStamper::addSignature to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE

483

1.1
Location : addJavaScript
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : addJavaScript
Killed by : none
removed call to com/lowagie/text/pdf/PdfStamperImp::addJavaScript → NO_COVERAGE

496

1.1
Location : addFileAttachment
Killed by : none
removed call to com/lowagie/text/pdf/PdfStamper::addFileAttachment → NO_COVERAGE

522

1.1
Location : makePackage
Killed by : none
removed call to com/lowagie/text/pdf/collection/PdfCollection::put → NO_COVERAGE

523

1.1
Location : makePackage
Killed by : none
removed call to com/lowagie/text/pdf/PdfStamperImp::makePackage → NO_COVERAGE

575

1.1
Location : setFullCompression
Killed by : none
negated conditional → NO_COVERAGE

577

1.1
Location : setFullCompression
Killed by : none
removed call to com/lowagie/text/pdf/PdfStamperImp::setFullCompression → NO_COVERAGE

651

1.1
Location : createSignature
Killed by : none
negated conditional → NO_COVERAGE

655

1.1
Location : createSignature
Killed by : none
removed call to com/lowagie/text/pdf/PdfSignatureAppearance::setSigout → NO_COVERAGE

658

1.1
Location : createSignature
Killed by : none
negated conditional → NO_COVERAGE

663

1.1
Location : createSignature
Killed by : none
removed call to com/lowagie/text/pdf/PdfSignatureAppearance::setTempFile → NO_COVERAGE

665

1.1
Location : createSignature
Killed by : none
removed call to com/lowagie/text/pdf/PdfSignatureAppearance::setOriginalout → NO_COVERAGE

666

1.1
Location : createSignature
Killed by : none
removed call to com/lowagie/text/pdf/PdfSignatureAppearance::setStamper → NO_COVERAGE

670

1.1
Location : createSignature
Killed by : none
negated conditional → NO_COVERAGE

671

1.1
Location : createSignature
Killed by : none
removed call to com/lowagie/text/pdf/PdfDictionary::remove → NO_COVERAGE

672

1.1
Location : createSignature
Killed by : none
removed call to com/lowagie/text/pdf/PdfStamperImp::markUsed → NO_COVERAGE

674

1.1
Location : createSignature
Killed by : none
mutated return of Object value for com/lowagie/text/pdf/PdfStamper::createSignature to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE

711

1.1
Location : createSignature
Killed by : none
mutated return of Object value for com/lowagie/text/pdf/PdfStamper::createSignature to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE

751

1.1
Location : createSignature
Killed by : none
mutated return of Object value for com/lowagie/text/pdf/PdfStamper::createSignature to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.4.2