/* * Copyright 2006-2017 ICEsoft Technologies Canada Corp. * * Licensed 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.icepdf.core.pobjects.security; /** * <p>Standard encryption has permissions associated with it which is defined * by a key in the encryption dictionary. It is up to the viewer application * to respect these permissions.</p> * <br> * <p>The value of the P key is an unsigned 32-bit integer containing a set of * flags specifying which access permissions should be granted when the document * is opened with user access. The below list shows the meanings of these flags. * Bit positions within the flag word are numbered from 1 (low-order) to 32 * (high-order); a 1 bit in any position enables the corresponding access * permission. Which bits are meaningful, and in some cases how they are * interpreted, depends on the security handler's revision number (specified in * the encryption dictionary's R entry).</p> * <br> * <table border="1" cellpadding="1" cellspacing="1" summary=""> * <tr> * <td><b> Bits</b></td> * <td><b> Meaning</b></td> * </tr> * <tr> * <td valign="top" >1-2</td> * <td>Reserved; must be 0.</td> * </tr> * <tr> * <td valign="top" > 3</td> * <td> (Revision 2) Print the document.<br> * (Revision 3) Print the document (possibly not at the highest * quality (possibly not at the highest quality level, depending on * whether bit 12 is also set). * </td> * </tr> * <tr> * <td valign="top" >4</td> * <td>Modify the contents of the document by operations other than those * controlled by bits 6, 9, and 11.</td> * </tr> * <tr> * <td valign="top" >5</td> * <td>(Revision 2) Copy or otherwise extract text and graphics from the * document, including extracting text and graphics (in support of * accessibility to disabled users or for other purposes). (Revision 3) * Copy or otherwise extract text and graphics from the document by * operations other than that controlled by bit 10.</td> * </tr> * <tr> * <td valign="top" >6</td> * <td>Add or modify text annotations, fill in interactive form fields, * and, if bit 4 is also set, create or modify interactive form fields * (including signature fields).</td> * </tr> * <tr> * <td valign="top" >7-8</td> * <td>Reserved; must be 1.</td> * </tr> * <tr> * <td valign="top" >9</td> * <td>(Revision 3 only) Fill in existing interactive form fields * (including signature fields), even if bit 6 is clear.</td> * </tr> * <tr> * <td valign="top" >10</td> * <td>(Revision 3 only) Extract text and graphics (in support of * accessibility to disabled users or for other purposes).</td> * </tr> * <tr> * <td valign="top" >11</td> * <td>(Revision 3 only) Assemble the document (insert, rotate, or delete * pages and create bookmarks or thumbnail images), even if bit 4 is * clear.</td> * </tr> * <tr> * <td valign="top" >12</td> * <td>(Revision 3 only) Print the document to a representation from which * a faithful digital copy of the PDF content could be generated. When * this bit is clear (and bit 3 is set), printing is limited to a * lowlevel representation of the appearance, possibly of degraded * quality.</td> * </tr> * <tr> * <td valign="top" >13-32</td> * <td>(Revision 3 only) Reserved; must be 1.</td> * </tr> * </table> * <br> * <b>Note:</b><br> * PDF integer objects in fact are represented internally in signed * twos complement form. Since all the reserved high-order flag bits in the * encryption dictionary's P value are required to be 1, the value must be * specified as a negative integer. For example, assuming revision 2 of the * security handler, the value -44 allows printing and copying but disallows * modifying the contents and annotations. * * @since 1.1 */ public class Permissions { // constants for parsing bits from P value // bit 3, 11111111111111111111000011000100 private static final int PRINT_DOCUMENT_BIT_3 = 0xFFFFF0C4; // bit 4, 11111111111111111111000011001000 private static final int MODIFY_DOCUMENT_BIT_4 = 0xFFFFF0C8; // bit 5, 11111111111111111111000011010000 private static final int DATA_EXTRACTION_BIT_5 = 0xFFFFF0D0; // bit 6, 11111111111111111111000011100000 private static final int MODIFY_TEXT_BIT_6 = 0xFFFFF0E0; // bit 9, 11111111111111111111000111000000 private static final int MODIFY_FORMS_BIT_9 = 0xFFFFF1C0; // bit 10, 11111111111111111111001011000000 private static final int ACCESSIBILITY_BIT_10 = 0xFFFFF2C0; // bit 11, 11111111111111111111010011000000 private static final int ASSEMBLE_DOCUMENT_BIT_11 = 0xFFFFF4C0; // bit 12 11111111111111111111100011000000 private static final int PRINT_QUALITY_BIT_12 = 0xFFFFF8C0; // Constants for retrieving permission values /** * Determine if printing of document is allowed. */ public static final int PRINT_DOCUMENT = 0; /** * Determine the quality of printed allowed. */ public static final int PRINT_DOCUMENT_QUALITY = 1; /** * Determine if changing the document is allowed. */ public static final int MODIFY_DOCUMENT = 2; /** * Determine if content copying or extraction is allowed. */ public static final int CONTENT_EXTRACTION = 3; /** * Determine if authoring comments and form fields is allowed. */ public static final int AUTHORING_FORM_FIELDS = 4; /** * Determine if form field fill-in or signing is allowed. */ public static final int FORM_FIELD_FILL_SIGNING = 5; /** * Determine if content accessibility is allowed. */ public static final int CONTENT_ACCESSABILITY = 6; /** * Determine if document assembly is allowed. */ public static final int DOCUMENT_ASSEMBLY = 7; // Permission values, indexes are mapped to constant values private boolean[] permissions = new boolean[10]; // original permission integer from encrypt dictionary // not permission bits and revered bits. 11111111111111111111000011000000 private int permissionFlags = 0xFFFFF0C0; // Revision of standard encryption algorithms private int revision = 2; // Initiated flag boolean isInit = false; /** * Creates a new object which can determine a document's user permissions. * * @param dictionary Encryption dictionary which contains a P key. */ public Permissions(EncryptionDictionary dictionary) { this.permissionFlags = dictionary.getPermissions(); revision = dictionary.getRevisionNumber(); } /** * Initiate the permission object. Extracts Permission bit values from * P key. */ public void init() { for (int i = 0; i < permissions.length; i++) { permissions[i] = false; } // Create permissions based on Revision 2 rules if (revision == 2) { // print document rules if ((permissionFlags & PRINT_DOCUMENT_BIT_3) == PRINT_DOCUMENT_BIT_3) { permissions[PRINT_DOCUMENT] = true; } // modify document if ((permissionFlags & MODIFY_DOCUMENT_BIT_4) == MODIFY_DOCUMENT_BIT_4) { permissions[MODIFY_DOCUMENT] = true; } // copy or extract text and graphics if ((permissionFlags & DATA_EXTRACTION_BIT_5) == DATA_EXTRACTION_BIT_5) { permissions[CONTENT_EXTRACTION] = true; } // authoring forms, not in 2, but use CONTENT_EXTRACTION permission if (permissions[CONTENT_EXTRACTION]) { permissions[AUTHORING_FORM_FIELDS] = true; } // Fill in existing interactive form fields, not in 2, but use // CONTENT_EXTRACTION permission if (permissions[CONTENT_EXTRACTION]) { permissions[FORM_FIELD_FILL_SIGNING] = true; } // document accessibility, not in 2, but use CONTENT_EXTRACTION // permission if (permissions[CONTENT_EXTRACTION]) { permissions[CONTENT_ACCESSABILITY] = true; } // allow assembly of document, not in 2, but use MODIFY_DOCUMENT // permission if (permissions[MODIFY_DOCUMENT]) { permissions[DOCUMENT_ASSEMBLY] = true; } // Print document quality, if true, print low quality version if ((permissionFlags & PRINT_QUALITY_BIT_12) == PRINT_QUALITY_BIT_12) { permissions[PRINT_DOCUMENT_QUALITY] = true; } isInit = true; } // Revision 3 rules else if (revision >= 3) { // print document rules if ((permissionFlags & PRINT_DOCUMENT_BIT_3) == PRINT_DOCUMENT_BIT_3) { permissions[PRINT_DOCUMENT] = true; } // modify document if ((permissionFlags & MODIFY_DOCUMENT_BIT_4) == MODIFY_DOCUMENT_BIT_4) { permissions[MODIFY_DOCUMENT] = true; } // copy or extract text and graphics if ((permissionFlags & DATA_EXTRACTION_BIT_5) == DATA_EXTRACTION_BIT_5) { permissions[CONTENT_EXTRACTION] = true; } // authoring forms if ((permissionFlags & MODIFY_TEXT_BIT_6) == MODIFY_TEXT_BIT_6) { permissions[AUTHORING_FORM_FIELDS] = true; } // Fill in existing interactive form fields if ((permissionFlags & MODIFY_FORMS_BIT_9) == MODIFY_FORMS_BIT_9) { permissions[FORM_FIELD_FILL_SIGNING] = true; } // document accessibility if ((permissionFlags & ACCESSIBILITY_BIT_10) == ACCESSIBILITY_BIT_10) { permissions[CONTENT_ACCESSABILITY] = true; } // allow assembly of document if ((permissionFlags & ASSEMBLE_DOCUMENT_BIT_11) == ASSEMBLE_DOCUMENT_BIT_11) { permissions[DOCUMENT_ASSEMBLY] = true; } // Print document quality, if true, print low quality version if ((permissionFlags & PRINT_QUALITY_BIT_12) == PRINT_QUALITY_BIT_12) { permissions[PRINT_DOCUMENT_QUALITY] = true; } isInit = true; } } /** * Gets the permission value of the specified Permission constant. * * @param permissionIndex one of the classes constants for determining a * specific user permission. * @return boolean value of the permission being called. */ public boolean getPermissions(final int permissionIndex) { if (!isInit) { init(); } // return false if the permission index is out of bounds. return !(permissionIndex < 0 || permissionIndex > permissions.length) && permissions[permissionIndex]; } }