WriterProperties.java
/*
This file is part of the iText (R) project.
Copyright (c) 1998-2025 Apryse Group NV
Authors: Apryse Software.
This program is offered under a commercial and under the AGPL license.
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
AGPL licensing:
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itextpdf.kernel.pdf;
import com.itextpdf.bouncycastleconnector.BouncyCastleFactoryCreator;
import com.itextpdf.kernel.mac.MacProperties;
import java.security.cert.Certificate;
public class WriterProperties {
protected int compressionLevel;
/**
* Indicates if to use full compression (using object streams).
*/
protected Boolean isFullCompression;
/**
* Indicates if the writer copy objects in a smart mode. If so PdfDictionary and PdfStream will be hashed
* and reused if there's an object with the same content later.
*/
protected boolean smartMode;
protected boolean addXmpMetadata;
protected PdfAConformance addPdfAXmpMetadata = null;
protected PdfUAConformance addPdfUaXmpMetadata = null;
protected PdfVersion pdfVersion;
protected EncryptionProperties encryptionProperties;
/**
* The ID entry that represents the initial identifier.
*/
protected PdfString initialDocumentId;
/**
* The ID entry that represents a change in a document.
*/
protected PdfString modifiedDocumentId;
public WriterProperties() {
smartMode = false;
compressionLevel = CompressionConstants.DEFAULT_COMPRESSION;
isFullCompression = null;
encryptionProperties = new EncryptionProperties();
}
/**
* Defines pdf version for the created document. Default value is PDF_1_7.
*
* @param version version for the document.
* @return this {@link WriterProperties} instance
*/
public WriterProperties setPdfVersion(PdfVersion version) {
this.pdfVersion = version;
return this;
}
/**
* Enables smart mode.
* <br>
* In smart mode when resources (such as fonts, images,...) are
* encountered, a reference to these resources is saved
* in a cache, so that they can be reused.
* This requires more memory, but reduces the file size
* of the resulting PDF document.
*
* @return this {@link WriterProperties} instance
*/
public WriterProperties useSmartMode() {
this.smartMode = true;
return this;
}
/**
* If true, default XMPMetadata based on {@link PdfDocumentInfo} will be added.
* For PDF 2.0 documents, metadata will be added in any case.
*
* @return this {@link WriterProperties} instance
*/
public WriterProperties addXmpMetadata() {
this.addXmpMetadata = true;
return this;
}
/**
* Adds PDF/A XMP metadata to the PDF document.
*
* <p>
* This method calls {@link #addXmpMetadata()} implicitly.
*
* <p>
* NOTE: Calling this method only affects the XMP metadata, but doesn't enable any additional checks that the
* created document meets all PDF/A requirements. When using this method make sure you are familiar with PDF/A
* document requirements. If you are not sure, use dedicated iText PDF/A module to create valid PDF/A documents.
*
* @param aConformance the PDF/A conformance which will be added to XMP metadata
*
* @return this {@link WriterProperties} instance
*/
public WriterProperties addPdfAXmpMetadata(PdfAConformance aConformance) {
this.addPdfAXmpMetadata = aConformance;
addXmpMetadata();
return this;
}
/**
* Adds PDF/UA XMP metadata to the PDF document.
*
* <p>
* This method calls {@link #addXmpMetadata()} implicitly.
*
* <p>
* NOTE: Calling this method only affects the XMP metadata, but doesn't enable any additional checks that the
* created document meets all PDF/UA requirements. When using this method make sure you are familiar with PDF/UA
* document requirements. If you are not sure, use dedicated iText PDF/UA module to create valid PDF/UA documents.
*
* @param uaConformance the PDF/UA conformance which will be added to XMP metadata
*
* @return this {@link WriterProperties} instance
*/
public WriterProperties addPdfUaXmpMetadata(PdfUAConformance uaConformance) {
this.addPdfUaXmpMetadata = uaConformance;
addXmpMetadata();
return this;
}
/**
* Defines the level of compression for the document.
* See {@link CompressionConstants}
*
* @param compressionLevel {@link CompressionConstants} value.
* @return this {@link WriterProperties} instance
*/
public WriterProperties setCompressionLevel(int compressionLevel) {
this.compressionLevel = compressionLevel;
return this;
}
/**
* Defines if full compression mode is enabled. If enabled, not only the content of the pdf document will be
* compressed, but also the pdf document inner structure.
*
* @param fullCompressionMode true - to enable full compression mode, false to disable it
* @return this {@link WriterProperties} instance
*/
public WriterProperties setFullCompressionMode(boolean fullCompressionMode) {
this.isFullCompression = fullCompressionMode;
return this;
}
/**
* Sets the encryption options for the document.
*
* @param userPassword the user password. Can be null or of zero length, which is equal to
* omitting the user password
* @param ownerPassword the owner password. If it's null or empty, iText will generate
* a random string to be used as the owner password
* @param permissions the user permissions
* The open permissions for the document can be
* {@link EncryptionConstants#ALLOW_PRINTING},
* {@link EncryptionConstants#ALLOW_MODIFY_CONTENTS},
* {@link EncryptionConstants#ALLOW_COPY},
* {@link EncryptionConstants#ALLOW_MODIFY_ANNOTATIONS},
* {@link EncryptionConstants#ALLOW_FILL_IN},
* {@link EncryptionConstants#ALLOW_SCREENREADERS},
* {@link EncryptionConstants#ALLOW_ASSEMBLY} and
* {@link EncryptionConstants#ALLOW_DEGRADED_PRINTING}.
* The permissions can be combined by ORing them
* @param encryptionAlgorithm the type of encryption. It can be one of
* {@link EncryptionConstants#STANDARD_ENCRYPTION_40},
* {@link EncryptionConstants#STANDARD_ENCRYPTION_128},
* {@link EncryptionConstants#ENCRYPTION_AES_128},
* {@link EncryptionConstants#ENCRYPTION_AES_256}
* or {@link EncryptionConstants#ENCRYPTION_AES_GCM}.
* Optionally {@link EncryptionConstants#DO_NOT_ENCRYPT_METADATA} can be ORed
* to output the metadata in cleartext.
* {@link EncryptionConstants#EMBEDDED_FILES_ONLY} can be ORed as well.
* Please be aware that the passed encryption types may override permissions:
* {@link EncryptionConstants#STANDARD_ENCRYPTION_40} implicitly sets
* {@link EncryptionConstants#DO_NOT_ENCRYPT_METADATA} and
* {@link EncryptionConstants#EMBEDDED_FILES_ONLY} as false;
* {@link EncryptionConstants#STANDARD_ENCRYPTION_128} implicitly sets
* {@link EncryptionConstants#EMBEDDED_FILES_ONLY} as false;
*
* @return this {@link WriterProperties} instance
*/
public WriterProperties setStandardEncryption(byte[] userPassword, byte[] ownerPassword, int permissions,
int encryptionAlgorithm) {
return setStandardEncryption(userPassword, ownerPassword, permissions, encryptionAlgorithm,
EncryptionProperties.DEFAULT_MAC_PROPERTIES);
}
/**
* Sets the encryption options for the document.
*
* @param userPassword the user password. Can be null or of zero length, which is equal to
* omitting the user password
* @param ownerPassword the owner password. If it's null or empty, iText will generate
* a random string to be used as the owner password
* @param permissions the user permissions
* The open permissions for the document can be
* {@link EncryptionConstants#ALLOW_PRINTING},
* {@link EncryptionConstants#ALLOW_MODIFY_CONTENTS},
* {@link EncryptionConstants#ALLOW_COPY},
* {@link EncryptionConstants#ALLOW_MODIFY_ANNOTATIONS},
* {@link EncryptionConstants#ALLOW_FILL_IN},
* {@link EncryptionConstants#ALLOW_SCREENREADERS},
* {@link EncryptionConstants#ALLOW_ASSEMBLY} and
* {@link EncryptionConstants#ALLOW_DEGRADED_PRINTING}.
* The permissions can be combined by ORing them
* @param encryptionAlgorithm the type of encryption. It can be one of
* {@link EncryptionConstants#STANDARD_ENCRYPTION_40},
* {@link EncryptionConstants#STANDARD_ENCRYPTION_128},
* {@link EncryptionConstants#ENCRYPTION_AES_128},
* {@link EncryptionConstants#ENCRYPTION_AES_256}
* or {@link EncryptionConstants#ENCRYPTION_AES_GCM}.
* Optionally {@link EncryptionConstants#DO_NOT_ENCRYPT_METADATA} can be ORed
* to output the metadata in cleartext.
* {@link EncryptionConstants#EMBEDDED_FILES_ONLY} can be ORed as well.
* Please be aware that the passed encryption types may override permissions:
* {@link EncryptionConstants#STANDARD_ENCRYPTION_40} implicitly sets
* {@link EncryptionConstants#DO_NOT_ENCRYPT_METADATA} and
* {@link EncryptionConstants#EMBEDDED_FILES_ONLY} as false;
* {@link EncryptionConstants#STANDARD_ENCRYPTION_128} implicitly sets
* {@link EncryptionConstants#EMBEDDED_FILES_ONLY} as false;
* @param macProperties {@link MacProperties} class to configure MAC integrity protection properties.
* Pass {@code null} if you want to disable MAC protection for any reason
*
* @return this {@link WriterProperties} instance
*/
public WriterProperties setStandardEncryption(byte[] userPassword, byte[] ownerPassword, int permissions,
int encryptionAlgorithm, MacProperties macProperties) {
encryptionProperties.setStandardEncryption(
userPassword, ownerPassword, permissions, encryptionAlgorithm, macProperties);
return this;
}
/**
* Sets the certificate encryption options for the document. An array of one or more public certificates
* must be provided together with an array of the same size for the permissions for each certificate.
*
* @param certs the public certificates to be used for the encryption
* @param permissions the user permissions for each of the certificates
* The open permissions for the document can be
* {@link EncryptionConstants#ALLOW_PRINTING},
* {@link EncryptionConstants#ALLOW_MODIFY_CONTENTS},
* {@link EncryptionConstants#ALLOW_COPY},
* {@link EncryptionConstants#ALLOW_MODIFY_ANNOTATIONS},
* {@link EncryptionConstants#ALLOW_FILL_IN},
* {@link EncryptionConstants#ALLOW_SCREENREADERS},
* {@link EncryptionConstants#ALLOW_ASSEMBLY} and
* {@link EncryptionConstants#ALLOW_DEGRADED_PRINTING}.
* The permissions can be combined by ORing them
* @param encryptionAlgorithm the type of encryption. It can be one of
* {@link EncryptionConstants#STANDARD_ENCRYPTION_40},
* {@link EncryptionConstants#STANDARD_ENCRYPTION_128},
* {@link EncryptionConstants#ENCRYPTION_AES_128},
* {@link EncryptionConstants#ENCRYPTION_AES_256}
* or {@link EncryptionConstants#ENCRYPTION_AES_GCM}.
* Optionally {@link EncryptionConstants#DO_NOT_ENCRYPT_METADATA} can be ORed
* to output the metadata in cleartext.
* {@link EncryptionConstants#EMBEDDED_FILES_ONLY} can be ORed as well.
* Please be aware that the passed encryption types may override permissions:
* {@link EncryptionConstants#STANDARD_ENCRYPTION_40} implicitly sets
* {@link EncryptionConstants#DO_NOT_ENCRYPT_METADATA} and
* {@link EncryptionConstants#EMBEDDED_FILES_ONLY} as false;
* {@link EncryptionConstants#STANDARD_ENCRYPTION_128} implicitly sets
* {@link EncryptionConstants#EMBEDDED_FILES_ONLY} as false;
*
* @return this {@link WriterProperties} instance
*/
public WriterProperties setPublicKeyEncryption(Certificate[] certs, int[] permissions, int encryptionAlgorithm) {
return setPublicKeyEncryption(certs, permissions, encryptionAlgorithm,
EncryptionProperties.DEFAULT_MAC_PROPERTIES);
}
/**
* Sets the certificate encryption options for the document. An array of one or more public certificates
* must be provided together with an array of the same size for the permissions for each certificate.
*
* @param certs the public certificates to be used for the encryption
* @param permissions the user permissions for each of the certificates
* The open permissions for the document can be
* {@link EncryptionConstants#ALLOW_PRINTING},
* {@link EncryptionConstants#ALLOW_MODIFY_CONTENTS},
* {@link EncryptionConstants#ALLOW_COPY},
* {@link EncryptionConstants#ALLOW_MODIFY_ANNOTATIONS},
* {@link EncryptionConstants#ALLOW_FILL_IN},
* {@link EncryptionConstants#ALLOW_SCREENREADERS},
* {@link EncryptionConstants#ALLOW_ASSEMBLY} and
* {@link EncryptionConstants#ALLOW_DEGRADED_PRINTING}.
* The permissions can be combined by ORing them
* @param encryptionAlgorithm the type of encryption. It can be one of
* {@link EncryptionConstants#STANDARD_ENCRYPTION_40},
* {@link EncryptionConstants#STANDARD_ENCRYPTION_128},
* {@link EncryptionConstants#ENCRYPTION_AES_128},
* {@link EncryptionConstants#ENCRYPTION_AES_256}
* or {@link EncryptionConstants#ENCRYPTION_AES_GCM}.
* Optionally {@link EncryptionConstants#DO_NOT_ENCRYPT_METADATA} can be ORed
* to output the metadata in cleartext.
* {@link EncryptionConstants#EMBEDDED_FILES_ONLY} can be ORed as well.
* Please be aware that the passed encryption types may override permissions:
* {@link EncryptionConstants#STANDARD_ENCRYPTION_40} implicitly sets
* {@link EncryptionConstants#DO_NOT_ENCRYPT_METADATA} and
* {@link EncryptionConstants#EMBEDDED_FILES_ONLY} as false;
* {@link EncryptionConstants#STANDARD_ENCRYPTION_128} implicitly sets
* {@link EncryptionConstants#EMBEDDED_FILES_ONLY} as false;
* @param macProperties {@link MacProperties} class to configure MAC integrity protection properties.
* Pass {@code null} if you want to disable MAC protection for any reason
*
* @return this {@link WriterProperties} instance
*/
public WriterProperties setPublicKeyEncryption(Certificate[] certs, int[] permissions, int encryptionAlgorithm,
MacProperties macProperties) {
BouncyCastleFactoryCreator.getFactory().isEncryptionFeatureSupported(encryptionAlgorithm, true);
encryptionProperties.setPublicKeyEncryption(certs, permissions, encryptionAlgorithm, macProperties);
return this;
}
/**
* The /ID entry of a document contains an array with two entries.
* The first one (initial id) represents the initial document id.
* It's a permanent identifier based on the contents of the file at the time it was originally created
* and does not change when the file is incrementally updated.
* To help ensure the uniqueness of file identifiers,
* it is recommended to be computed by means of a message digest algorithm such as MD5.
*
* iText will by default keep the existing initial id.
* But if you'd like you can set this id yourself using this setter.
*
* @param initialDocumentId the new initial document id
* @return this {@link WriterProperties} instance
*/
public WriterProperties setInitialDocumentId(PdfString initialDocumentId) {
this.initialDocumentId = initialDocumentId;
return this;
}
/**
* The /ID entry of a document contains an array with two entries.
* The second one (modified id) should be the same entry, unless the document has been modified. iText will by default generate
* a modified id. But if you'd like you can set this id yourself using this setter.
*
* @param modifiedDocumentId the new modified document id
* @return this {@link WriterProperties} instance
*/
public WriterProperties setModifiedDocumentId(PdfString modifiedDocumentId) {
this.modifiedDocumentId = modifiedDocumentId;
return this;
}
boolean isStandardEncryptionUsed() {
return encryptionProperties.isStandardEncryptionUsed();
}
boolean isPublicKeyEncryptionUsed() {
return encryptionProperties.isPublicKeyEncryptionUsed();
}
}