org.sejda.sambox.pdmodel.encryption.AccessPermission Maven / Gradle / Ivy
Show all versions of sambox Show documentation
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sejda.sambox.pdmodel.encryption;
/**
* This class represents the access permissions to a document. These permissions are specified in
* the PDF format specifications, they include:
*
* - print the document
* - modify the content of the document
* - copy or extract content of the document
* - add or modify annotations
* - fill in interactive form fields
* - extract text and graphics for accessibility to visually impaired people
* - assemble the document
* - print in degraded quality
*
*
* This class can be used to protect a document by assigning access permissions to recipients. In this case, it must be
* used with a specific ProtectionPolicy.
*
*
* When a document is decrypted, it has a currentAccessPermission property which is the access permissions granted to
* the user who decrypted the document.
*
* @author Ben Litchfield
* @author Benoit Guillon
* @see ProtectionPolicy
* @see org.sejda.sambox.pdmodel.PDDocument#getCurrentAccessPermission()
*/
// TODO make this immutable
public class AccessPermission
{
private static final int DEFAULT_PERMISSIONS = ~3;// bits 0 & 1 need to be zero
private static final int PRINT_BIT = 3;
private static final int MODIFICATION_BIT = 4;
private static final int EXTRACT_BIT = 5;
private static final int MODIFY_ANNOTATIONS_BIT = 6;
private static final int FILL_IN_FORM_BIT = 9;
private static final int EXTRACT_FOR_ACCESSIBILITY_BIT = 10;
private static final int ASSEMBLE_DOCUMENT_BIT = 11;
private static final int FAITHFUL_PRINT_BIT = 12;
private int bytes;
private boolean readOnly = false;
/**
* Create a new access permission object. By default, all permissions are granted.
*/
public AccessPermission()
{
bytes = DEFAULT_PERMISSIONS;
}
/**
* Create a new access permission object from a byte array. Bytes are ordered most significant
* byte first.
*
* @param b the bytes as defined in PDF specs
*/
public AccessPermission(byte[] b)
{
bytes = 0;
bytes |= b[0] & 0xFF;
bytes <<= 8;
bytes |= b[1] & 0xFF;
bytes <<= 8;
bytes |= b[2] & 0xFF;
bytes <<= 8;
bytes |= b[3] & 0xFF;
}
/**
* Creates a new access permission object from a single integer.
*
* @param permissions The permission bits.
*/
public AccessPermission(int permissions)
{
bytes = permissions;
}
private boolean isPermissionBitOn(int bit)
{
return (bytes & (1 << (bit - 1))) != 0;
}
private boolean setPermissionBit(int bit, boolean value)
{
int permissions = bytes;
if (value)
{
permissions = permissions | (1 << (bit - 1));
}
else
{
permissions = permissions & (~(1 << (bit - 1)));
}
bytes = permissions;
return (bytes & (1 << (bit - 1))) != 0;
}
/**
* This will tell if the access permission corresponds to owner access permission (no
* restriction).
*
* @return true if the access permission does not restrict the use of the document
*/
public boolean isOwnerPermission()
{
return (this.canAssembleDocument() && this.canExtractContent()
&& this.canExtractForAccessibility() && this.canFillInForm() && this.canModify()
&& this.canModifyAnnotations() && this.canPrint() && this.canPrintFaithful());
}
/**
* returns an access permission object for a document owner.
*
* @return A standard owner access permission set.
*/
public static AccessPermission getOwnerAccessPermission()
{
AccessPermission ret = new AccessPermission();
ret.setCanAssembleDocument(true);
ret.setCanExtractContent(true);
ret.setCanExtractForAccessibility(true);
ret.setCanFillInForm(true);
ret.setCanModify(true);
ret.setCanModifyAnnotations(true);
ret.setCanPrint(true);
ret.setCanPrintFaithful(true);
return ret;
}
/**
* This returns an integer representing the access permissions. This integer can be used for
* public key encryption. This format is not documented in the PDF specifications but is
* necessary for compatibility with Adobe Acrobat and Adobe Reader.
*
* @return the integer representing access permissions
*/
public int getPermissionBytesForPublicKey()
{
setPermissionBit(1, true);
setPermissionBit(7, false);
setPermissionBit(8, false);
for (int i = 13; i <= 32; i++)
{
setPermissionBit(i, false);
}
return bytes;
}
/**
* The returns an integer representing the access permissions. This integer can be used for
* standard PDF encryption as specified in the PDF specifications.
*
* @return the integer representing the access permissions
*/
public int getPermissionBytes()
{
return bytes;
}
/**
* This will tell if the user can print.
*
* @return true If supplied with the user password they are allowed to print.
*/
public boolean canPrint()
{
return isPermissionBitOn(PRINT_BIT);
}
/**
* Set if the user can print.
*
* This method will have no effect if the object is in read only mode
*
* @param allowPrinting A boolean determining if the user can print.
*/
public void setCanPrint(boolean allowPrinting)
{
if (!readOnly)
{
setPermissionBit(PRINT_BIT, allowPrinting);
}
}
/**
* This will tell if the user can modify contents of the document.
*
* @return true If supplied with the user password they are allowed to modify the document
*/
public boolean canModify()
{
return isPermissionBitOn(MODIFICATION_BIT);
}
/**
* Set if the user can modify the document.
*
* This method will have no effect if the object is in read only mode
*
* @param allowModifications A boolean determining if the user can modify the document.
*/
public void setCanModify(boolean allowModifications)
{
if (!readOnly)
{
setPermissionBit(MODIFICATION_BIT, allowModifications);
}
}
/**
* This will tell if the user can extract text and images from the PDF document.
*
* @return true If supplied with the user password they are allowed to extract content from the
* PDF document
*/
public boolean canExtractContent()
{
return isPermissionBitOn(EXTRACT_BIT);
}
/**
* Set if the user can extract content from the document.
*
* This method will have no effect if the object is in read only mode
*
* @param allowExtraction A boolean determining if the user can extract content from the
* document.
*/
public void setCanExtractContent(boolean allowExtraction)
{
if (!readOnly)
{
setPermissionBit(EXTRACT_BIT, allowExtraction);
}
}
/**
* This will tell if the user can add or modify text annotations and fill in interactive forms
* fields and, if {@link #canModify() canModify()} returns true, create or modify interactive
* form fields (including signature fields). Note that if {@link #canFillInForm()
* canFillInForm()} returns true, it is still possible to fill in interactive forms (including
* signature fields) even if this method here returns false.
*
* @return true If supplied with the user password they are allowed to modify annotations.
*/
public boolean canModifyAnnotations()
{
return isPermissionBitOn(MODIFY_ANNOTATIONS_BIT);
}
/**
* Set if the user can add or modify text annotations and fill in interactive forms fields and,
* (including signature fields). Note that if {@link #canFillInForm() canFillInForm()} returns
* true, it is still possible to fill in interactive forms (including signature fields) even the
* parameter here is false.
*
* This method will have no effect if the object is in read only mode.
*
* @param allowAnnotationModification A boolean determining the new setting.
*/
public void setCanModifyAnnotations(boolean allowAnnotationModification)
{
if (!readOnly)
{
setPermissionBit(MODIFY_ANNOTATIONS_BIT, allowAnnotationModification);
}
}
/**
* This will tell if the user can fill in interactive form fields (including signature fields)
* even if {@link #canModifyAnnotations() canModifyAnnotations()} returns false.
*
* @return true If supplied with the user password they are allowed to fill in form fields.
*/
public boolean canFillInForm()
{
return isPermissionBitOn(FILL_IN_FORM_BIT);
}
/**
* Set if the user can fill in interactive form fields (including signature fields) even if
* {@link #canModifyAnnotations() canModifyAnnotations()} returns false. Therefore, if you want
* to prevent a user from filling in interactive form fields, you need to call {@link
* #setCanModifyAnnotations(boolean) setCanModifyAnnotations(false)} as well.
*
* This method will have no effect if the object is in read only mode.
*
* @param allowFillingInForm A boolean determining if the user can fill in interactive forms.
*/
public void setCanFillInForm(boolean allowFillingInForm)
{
if (!readOnly)
{
setPermissionBit(FILL_IN_FORM_BIT, allowFillingInForm);
}
}
/**
* This will tell if the user can extract text and images from the PDF document for
* accessibility purposes.
*
* @return true If supplied with the user password they are allowed to extract content from the
* PDF document
*/
public boolean canExtractForAccessibility()
{
return isPermissionBitOn(EXTRACT_FOR_ACCESSIBILITY_BIT);
}
/**
* Set if the user can extract content from the document for accessibility purposes.
*
* This method will have no effect if the object is in read only mode.
*
* @param allowExtraction A boolean determining if the user can extract content from the
* document.
*/
public void setCanExtractForAccessibility(boolean allowExtraction)
{
if (!readOnly)
{
setPermissionBit(EXTRACT_FOR_ACCESSIBILITY_BIT, allowExtraction);
}
}
/**
* This will tell if the user can insert/rotate/delete pages.
*
* @return true If supplied with the user password they are allowed to extract content from the
* PDF document
*/
public boolean canAssembleDocument()
{
return isPermissionBitOn(ASSEMBLE_DOCUMENT_BIT);
}
/**
* Set if the user can insert/rotate/delete pages.
*
* This method will have no effect if the object is in read only mode
*
* @param allowAssembly A boolean determining if the user can assemble the document.
*/
public void setCanAssembleDocument(boolean allowAssembly)
{
if (!readOnly)
{
setPermissionBit(ASSEMBLE_DOCUMENT_BIT, allowAssembly);
}
}
@Deprecated
public boolean canPrintDegraded()
{
return canPrintFaithful();
}
/**
* This will tell if the user can print the document in a faithful format or in a degraded
* format (if print is enabled).
*
* @return true If supplied with the user password they are allowed to print the document in a
* degraded format.
*/
public boolean canPrintFaithful()
{
return isPermissionBitOn(FAITHFUL_PRINT_BIT);
}
@Deprecated
public void setCanPrintDegraded(boolean canPrintDegraded)
{
setCanPrintFaithful(canPrintDegraded);
}
/**
* Set if the user can print the document in a faithful format or in a degraded format (if print
* is enabled). The PDF version must be 1.5 or higher.
*
* This method will have no effect if the object is in read only mode.
*
* @param canPrintFaithful A boolean determining if the user can print the document in a
* degraded format.
*/
public void setCanPrintFaithful(boolean canPrintFaithful)
{
if (!readOnly)
{
setPermissionBit(FAITHFUL_PRINT_BIT, canPrintFaithful);
}
}
/**
* Locks the access permission read only (ie, the setters will have no effects). After that, the
* object cannot be unlocked. This method is used for the currentAccessPermssion of a document
* to avoid users to change access permission.
*/
public void setReadOnly()
{
readOnly = true;
}
/**
* This will tell if the object has been set as read only.
*
* @return true if the object is in read only mode.
*/
public boolean isReadOnly()
{
return readOnly;
}
/**
* Indicates if any revision 3 access permission is set or not.
*
* @return true if any revision 3 access permission is set
*/
protected boolean hasAnyRevision3PermissionSet()
{
if (canFillInForm())
{
return true;
}
if (canExtractForAccessibility())
{
return true;
}
if (canAssembleDocument())
{
return true;
}
return canPrintFaithful();
}
}