src/reportlab/lib/pdfencrypt.py
author rptlab
Tue, 30 Apr 2013 14:28:14 +0100
branchpy33
changeset 3723 99aa837b6703
parent 3721 0c93dd8ff567
child 3746 b7143a1c34c6
permissions -rw-r--r--
second stage of port to Python 3.3; working hello world
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
3617
ae5744e97c42 reportlab: copyright date changes
robin
parents: 3328
diff changeset
     1
#copyright ReportLab Europe Limited. 2000-2012
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
     2
#see license.txt for license details
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
     3
__version__=''' $Id$ '''
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
     4
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
     5
"""helpers for pdf encryption/decryption"""
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
     6
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
     7
import sys, os
3098
318ba6cb2cb1 reportlab: fix md5 usage in pdfencrypt.py & fontfinder.py
rgbecker
parents: 3073
diff changeset
     8
try:
318ba6cb2cb1 reportlab: fix md5 usage in pdfencrypt.py & fontfinder.py
rgbecker
parents: 3073
diff changeset
     9
    from hashlib import md5
318ba6cb2cb1 reportlab: fix md5 usage in pdfencrypt.py & fontfinder.py
rgbecker
parents: 3073
diff changeset
    10
except ImportError:
318ba6cb2cb1 reportlab: fix md5 usage in pdfencrypt.py & fontfinder.py
rgbecker
parents: 3073
diff changeset
    11
    from md5 import md5
318ba6cb2cb1 reportlab: fix md5 usage in pdfencrypt.py & fontfinder.py
rgbecker
parents: 3073
diff changeset
    12
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
    13
from reportlab.lib.utils import getBytesIO
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    14
import tempfile
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    15
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    16
from reportlab.pdfgen.canvas import Canvas
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    17
from reportlab.pdfbase import pdfutils
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    18
from reportlab.platypus.flowables import Flowable
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    19
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    20
#AR debug hooks - leaving in for now
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    21
CLOBBERID = 0  # set a constant Doc ID to allow comparison with other software like iText
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    22
CLOBBERPERMISSIONS = 0
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    23
DEBUG = 0  # print stuff to trace calculations
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    24
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    25
# permission bits
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    26
reserved1 = 1               # bit 1 must be 0
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    27
reserved2 = 1<<1            # bit 2 must be 0
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    28
printable = 1<<2
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    29
modifiable = 1<<3
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    30
copypastable = 1<<4
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    31
annotatable = 1<<5
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    32
# others [7..32] are reserved, must be 1
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    33
higherbits = 0
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    34
for i in range(6,31):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    35
    higherbits = higherbits | (1<<i)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    36
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    37
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    38
# no encryption
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    39
class StandardEncryption:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    40
    prepared = 0
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    41
    def __init__(self, userPassword, ownerPassword=None, canPrint=1, canModify=1, canCopy=1, canAnnotate=1, strength=40):
3053
e238a5851dd0 Added docstring to the reportlab.lib.pdfencrypt.StandardEncryption constructor.
jonas
parents: 3035
diff changeset
    42
        '''
e238a5851dd0 Added docstring to the reportlab.lib.pdfencrypt.StandardEncryption constructor.
jonas
parents: 3035
diff changeset
    43
        This class defines the encryption properties to be used while creating a pdf document.
e238a5851dd0 Added docstring to the reportlab.lib.pdfencrypt.StandardEncryption constructor.
jonas
parents: 3035
diff changeset
    44
        Once initiated, a StandardEncryption object can be applied to a Canvas or a BaseDocTemplate.
e238a5851dd0 Added docstring to the reportlab.lib.pdfencrypt.StandardEncryption constructor.
jonas
parents: 3035
diff changeset
    45
        The userPassword parameter sets the user password on the encrypted pdf.
e238a5851dd0 Added docstring to the reportlab.lib.pdfencrypt.StandardEncryption constructor.
jonas
parents: 3035
diff changeset
    46
        The ownerPassword parameter sets the owner password on the encrypted pdf.
e238a5851dd0 Added docstring to the reportlab.lib.pdfencrypt.StandardEncryption constructor.
jonas
parents: 3035
diff changeset
    47
        The boolean flags canPrint, canModify, canCopy, canAnnotate determine wether a user can
e238a5851dd0 Added docstring to the reportlab.lib.pdfencrypt.StandardEncryption constructor.
jonas
parents: 3035
diff changeset
    48
        perform the corresponding actions on the pdf when only a user password has been supplied.
e238a5851dd0 Added docstring to the reportlab.lib.pdfencrypt.StandardEncryption constructor.
jonas
parents: 3035
diff changeset
    49
        If the user supplies the owner password while opening the pdf, all actions can be performed regardless
e238a5851dd0 Added docstring to the reportlab.lib.pdfencrypt.StandardEncryption constructor.
jonas
parents: 3035
diff changeset
    50
        of the flags.
e238a5851dd0 Added docstring to the reportlab.lib.pdfencrypt.StandardEncryption constructor.
jonas
parents: 3035
diff changeset
    51
        Note that the security provided by these encryption settings (and even more so for the flags) is very weak.
e238a5851dd0 Added docstring to the reportlab.lib.pdfencrypt.StandardEncryption constructor.
jonas
parents: 3035
diff changeset
    52
        '''
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    53
        self.ownerPassword = ownerPassword
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    54
        self.userPassword = userPassword
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    55
        if strength == 40:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    56
            self.revision = 2
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    57
        elif strength == 128:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    58
            self.revision = 3
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    59
        self.canPrint = canPrint
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    60
        self.canModify = canModify
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    61
        self.canCopy = canCopy
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    62
        self.canAnnotate = canAnnotate
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    63
        self.O = self.U = self.P = self.key = None
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    64
    def setAllPermissions(self, value):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    65
        self.canPrint = \
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    66
        self.canModify = \
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    67
        self.canCopy = \
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    68
        self.canAnnotate = value
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    69
    def permissionBits(self):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    70
        p = 0
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    71
        if self.canPrint: p = p | printable
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    72
        if self.canModify: p = p | modifiable
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    73
        if self.canCopy: p = p | copypastable
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    74
        if self.canAnnotate: p = p | annotatable
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    75
        p = p | higherbits
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    76
        return p
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    77
    def encode(self, t):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    78
        "encode a string, stream, text"
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    79
        if not self.prepared:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
    80
            raise ValueError("encryption not prepared!")
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    81
        if self.objnum is None:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
    82
            raise ValueError("not registered in PDF object")
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    83
        return encodePDF(self.key, self.objnum, self.version, t, revision=self.revision)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    84
    def prepare(self, document, overrideID=None):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    85
        # get ready to do encryption
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
    86
        if DEBUG: print('StandardEncryption.prepare(...) - revision %d' % self.revision)
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    87
        if self.prepared:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
    88
            raise ValueError("encryption already prepared!")
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    89
        # get the unescaped string value of the document id (first array element).
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    90
        # we allow one to be passed in instead to permit reproducible tests
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    91
        # of our algorithm, but in real life overrideID will always be None
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    92
        if overrideID:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    93
            internalID = overrideID
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    94
        else:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    95
            externalID = document.ID() # initialize it...
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    96
            internalID = document.signature.digest()
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    97
            #AR debugging
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    98
            if CLOBBERID:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
    99
                internalID = "xxxxxxxxxxxxxxxx"
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   100
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   101
        if DEBUG:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   102
            print('userPassword    = %s' % self.userPassword)
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   103
            print('ownerPassword   = %s' % self.ownerPassword)
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   104
            print('internalID      = %s' % internalID)
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   105
        self.P = int(self.permissionBits() - 2**31)
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   106
        if CLOBBERPERMISSIONS: self.P = -44 # AR hack
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   107
        if DEBUG:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   108
            print("self.P          = %s" % repr(self.P))
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   109
        self.O = computeO(self.userPassword, self.ownerPassword, self.revision)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   110
        if DEBUG:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   111
            print("self.O (as hex) = %s" % hexText(self.O))
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   112
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   113
        #print "\nself.O", self.O, repr(self.O)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   114
        self.key = encryptionkey(self.userPassword, self.O, self.P, internalID, revision=self.revision)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   115
        if DEBUG:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   116
            print("self.key (hex)  = %s" % hexText(self.key))
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   117
        self.U = computeU(self.key, revision=self.revision, documentId=internalID)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   118
        if DEBUG:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   119
            print("self.U (as hex) = %s" % hexText(self.U))
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   120
        self.objnum = self.version = None
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   121
        self.prepared = 1
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   122
    def register(self, objnum, version):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   123
        # enter a new direct object
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   124
        if not self.prepared:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   125
            raise ValueError("encryption not prepared!")
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   126
        self.objnum = objnum
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   127
        self.version = version
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   128
    def info(self):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   129
        # the representation of self in file if any (should be None or PDFDict)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   130
        if not self.prepared:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   131
            raise ValueError("encryption not prepared!")
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   132
        return StandardEncryptionDictionary(O=self.O, U=self.U, P=self.P, revision=self.revision)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   133
3099
cc00552d0450 reportlab: fix pdfencrypt.py
rgbecker
parents: 3098
diff changeset
   134
class StandardEncryptionDictionary:
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   135
    __RefOnly__ = 1
3101
ec18b8a44cd2 reportlab:attempt to make PDF objects more explicit
rgbecker
parents: 3099
diff changeset
   136
    __PDFObject__ = True
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   137
    def __init__(self, O, U, P, revision):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   138
        self.O, self.U, self.P = O,U,P
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   139
        self.revision = revision
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   140
    def format(self, document):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   141
        # use a dummy document to bypass encryption
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   142
        from reportlab.pdfbase.pdfdoc import DummyDoc, PDFDictionary, PDFString, PDFName
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   143
        dummy = DummyDoc()
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   144
        dict = {"Filter": PDFName("Standard"),
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   145
                "O": hexText(self.O), #PDFString(self.O),
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   146
                "U": hexText(self.U), #PDFString(self.U),
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   147
                "P": self.P}
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   148
        if self.revision == 3:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   149
            dict['Length'] = 128
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   150
            dict['R'] = 3
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   151
            dict['V'] = 2
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   152
        else:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   153
            dict['R'] = 2
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   154
            dict['V'] = 1
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   155
        pdfdict = PDFDictionary(dict)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   156
        return pdfdict.format(dummy)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   157
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   158
# from pdf spec
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   159
padding = """
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   160
28 BF 4E 5E 4E 75 8A 41 64 00 4E 56 FF FA 01 08
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   161
2E 2E 00 B6 D0 68 3E 80 2F 0C A9 FE 64 53 69 7A
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   162
"""
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   163
if hasattr(padding,'join'):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   164
    def xorKey(num,key):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   165
        "xor's each bytes of the key with the number, which is <256"
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   166
        if num==0: return key
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   167
        from operator import xor
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   168
        return ''.join(map(chr,list(map(xor,len(key)*[num],list(map(ord,key))))))
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   169
else:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   170
    def xorKey(num, key):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   171
        "xor's each bytes of the key with the number, which is <256"
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   172
        from operator import xor
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   173
        out = ''
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   174
        for ch in key:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   175
            out = out + chr(xor(num, ord(ch)))
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   176
        return out
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   177
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   178
def hexchar(x):
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   179
    return chr(int(x, 16))
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   180
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   181
def hexText(text):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   182
    "a legitimate way to show strings in PDF"
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   183
    out = ''
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   184
    for char in text:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   185
        out = out + '%02X' % ord(char)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   186
    return '<' + out + '>'
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   187
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   188
def unHexText(hexText):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   189
    assert hexText[0] == '<', 'bad hex text'
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   190
    assert hexText[-1] == '>', 'bad hex text'
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   191
    hexText = hexText[1:-1]
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   192
    out = ''
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3101
diff changeset
   193
    for i in range(int(len(hexText)/2.0)):
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   194
        slice = hexText[i*2: i*2+2]
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   195
        char = chr(eval('0x'+slice))
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   196
        out = out + char
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   197
    return out
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   198
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   199
PadString = ''.join(map(hexchar, padding.strip().split()))
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   200
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   201
def encryptionkey(password, OwnerKey, Permissions, FileId1, revision=2):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   202
    # FileId1 is first string of the fileid array
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   203
    # add padding string
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   204
    #AR force same as iText example
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   205
    #Permissions =  -1836   #int(Permissions - 2**31)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   206
    password = password + PadString
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   207
    # truncate to 32 bytes
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   208
    password = password[:32]
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   209
    # translate permissions to string, low order byte first
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   210
    p = Permissions# + 2**32L
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   211
    permissionsString = ""
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   212
    for i in range(4):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   213
        byte = (p & 0xff)    # seems to match what iText does
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   214
        p = p>>8
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   215
        permissionsString = permissionsString + chr(byte % 256)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   216
3098
318ba6cb2cb1 reportlab: fix md5 usage in pdfencrypt.py & fontfinder.py
rgbecker
parents: 3073
diff changeset
   217
    hash = md5(password)
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   218
    hash.update(OwnerKey)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   219
    hash.update(permissionsString)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   220
    hash.update(FileId1)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   221
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   222
    md5output = hash.digest()
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   223
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   224
    if revision==2:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   225
        key = md5output[:5]
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   226
    elif revision==3:  #revision 3 algorithm - loop 50 times
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   227
        for x in range(50):
3098
318ba6cb2cb1 reportlab: fix md5 usage in pdfencrypt.py & fontfinder.py
rgbecker
parents: 3073
diff changeset
   228
            md5output = md5(md5output).digest()
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   229
        key = md5output[:16]
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   230
    if DEBUG: print('encryptionkey(%s,%s,%s,%s,%s)==>%s' % tuple([hexText(str(x)) for x in (password, OwnerKey, Permissions, FileId1, revision, key)]))
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   231
    return key
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   232
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   233
def computeO(userPassword, ownerPassword, revision):
3071
ff411e85ba36 make pdfencrypt.py use ArcIV
rgbecker
parents: 3053
diff changeset
   234
    from reportlab.lib.arciv import ArcIV
3098
318ba6cb2cb1 reportlab: fix md5 usage in pdfencrypt.py & fontfinder.py
rgbecker
parents: 3073
diff changeset
   235
    #print 'digest of hello is %s' % md5('hello').digest()
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   236
    assert revision in (2,3), 'Unknown algorithm revision %s' % revision
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   237
    if ownerPassword in (None, ''):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   238
        ownerPassword = userPassword
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   239
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   240
    ownerPad = ownerPassword + PadString
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   241
    ownerPad = ownerPad[0:32]
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   242
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   243
    password = userPassword + PadString
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   244
    userPad = password[:32]
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   245
3098
318ba6cb2cb1 reportlab: fix md5 usage in pdfencrypt.py & fontfinder.py
rgbecker
parents: 3073
diff changeset
   246
    digest = md5(ownerPad).digest()
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   247
    if revision == 2:
3071
ff411e85ba36 make pdfencrypt.py use ArcIV
rgbecker
parents: 3053
diff changeset
   248
        O = ArcIV(digest[:5]).encode(userPad)
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   249
    elif revision == 3:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   250
        for i in range(50):
3098
318ba6cb2cb1 reportlab: fix md5 usage in pdfencrypt.py & fontfinder.py
rgbecker
parents: 3073
diff changeset
   251
            digest = md5(digest).digest()
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   252
        digest = digest[:16]
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   253
        O = userPad
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   254
        for i in range(20):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   255
            thisKey = xorKey(i, digest)
3071
ff411e85ba36 make pdfencrypt.py use ArcIV
rgbecker
parents: 3053
diff changeset
   256
            O = ArcIV(thisKey).encode(O)
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   257
    if DEBUG: print('computeO(%s,%s,%s)==>%s' % tuple([hexText(str(x)) for x in (userPassword, ownerPassword, revision,O)]))
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   258
    return O
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   259
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   260
def computeU(encryptionkey, encodestring=PadString,revision=2,documentId=None):
3071
ff411e85ba36 make pdfencrypt.py use ArcIV
rgbecker
parents: 3053
diff changeset
   261
    from reportlab.lib.arciv import ArcIV
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   262
    if revision == 2:
3071
ff411e85ba36 make pdfencrypt.py use ArcIV
rgbecker
parents: 3053
diff changeset
   263
        result = ArcIV(encryptionkey).encode(encodestring)
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   264
    elif revision == 3:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   265
        assert documentId is not None, "Revision 3 algorithm needs the document ID!"
3098
318ba6cb2cb1 reportlab: fix md5 usage in pdfencrypt.py & fontfinder.py
rgbecker
parents: 3073
diff changeset
   266
        h = md5(PadString)
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   267
        h.update(documentId)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   268
        tmp = h.digest()
3071
ff411e85ba36 make pdfencrypt.py use ArcIV
rgbecker
parents: 3053
diff changeset
   269
        tmp = ArcIV(encryptionkey).encode(tmp)
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   270
        for n in range(1,20):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   271
            thisKey = xorKey(n, encryptionkey)
3071
ff411e85ba36 make pdfencrypt.py use ArcIV
rgbecker
parents: 3053
diff changeset
   272
            tmp = ArcIV(thisKey).encode(tmp)
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   273
        while len(tmp) < 32:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   274
            tmp = tmp + '\000'
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   275
        result = tmp
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   276
    if DEBUG: print('computeU(%s,%s,%s,%s)==>%s' % tuple([hexText(str(x)) for x in (encryptionkey, encodestring,revision,documentId,result)]))
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   277
    return result
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   278
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   279
def checkU(encryptionkey, U):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   280
    decoded = computeU(encryptionkey, U)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   281
    #print len(decoded), len(U), len(PadString)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   282
    if decoded!=PadString:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   283
        if len(decoded)!=len(PadString):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   284
            raise ValueError("lengths don't match! (password failed)")
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   285
        raise ValueError("decode of U doesn't match fixed padstring (password failed)")
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   286
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   287
def encodePDF(key, objectNumber, generationNumber, string, revision=2):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   288
    "Encodes a string or stream"
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   289
    #print 'encodePDF (%s, %d, %d, %s)' % (hexText(key), objectNumber, generationNumber, string)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   290
    # extend 3 bytes of the object Number, low byte first
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   291
    newkey = key
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   292
    n = objectNumber
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   293
    for i in range(3):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   294
        newkey = newkey + chr(n & 0xff)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   295
        n = n>>8
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   296
    # extend 2 bytes of the generationNumber
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   297
    n = generationNumber
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   298
    for i in range(2):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   299
        newkey = newkey + chr(n & 0xff)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   300
        n = n>>8
3098
318ba6cb2cb1 reportlab: fix md5 usage in pdfencrypt.py & fontfinder.py
rgbecker
parents: 3073
diff changeset
   301
    md5output = md5(newkey).digest()
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   302
    if revision == 2:
3071
ff411e85ba36 make pdfencrypt.py use ArcIV
rgbecker
parents: 3053
diff changeset
   303
        key = md5output[:10]
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   304
    elif revision == 3:
3071
ff411e85ba36 make pdfencrypt.py use ArcIV
rgbecker
parents: 3053
diff changeset
   305
        key = md5output #all 16 bytes
ff411e85ba36 make pdfencrypt.py use ArcIV
rgbecker
parents: 3053
diff changeset
   306
    from reportlab.lib.arciv import ArcIV
ff411e85ba36 make pdfencrypt.py use ArcIV
rgbecker
parents: 3053
diff changeset
   307
    encrypted = ArcIV(key).encode(string)
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   308
    #print 'encrypted=', hexText(encrypted)
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   309
    if DEBUG: print('encodePDF(%s,%s,%s,%s,%s)==>%s' % tuple([hexText(str(x)) for x in (key, objectNumber, generationNumber, string, revision,encrypted)]))
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   310
    return encrypted
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   311
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   312
    ######################################################################
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   313
    #
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   314
    #  quick tests of algorithm, should be moved elsewhere
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   315
    #
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   316
    ######################################################################
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   317
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   318
def test():
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   319
    # do a 40 bit example known to work in Acrobat Reader 4.0
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   320
    enc = StandardEncryption('userpass','ownerpass', strength=40)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   321
    enc.prepare(None, overrideID = 'xxxxxxxxxxxxxxxx')
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   322
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   323
    expectedO = '<6A835A92E99DCEA39D51CF34FDBDA42162690D2BD5F8E08E3008F91FE5B8512E>'
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   324
    expectedU = '<9997BDB61E7F288DAE6A8C4246A8F9CDCDBBC3D909D703CABA5D65A0CC6D4083>'
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   325
    expectedKey = '<A3A68B5CB1>'  # 5 byte key = 40 bits
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   326
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   327
    assert hexText(enc.O) == expectedO, '40 bit unexpected O value %s' % hexText(enc.O)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   328
    assert hexText(enc.U) == expectedU, '40 bit unexpected U value %s' % hexText(enc.U)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   329
    assert hexText(enc.key) == expectedKey, '40 bit unexpected key value %s' % hexText(enc.key)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   330
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   331
    # now for 128 bit example
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   332
    enc = StandardEncryption('userpass','ownerpass', strength=128)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   333
    enc.prepare(None, overrideID = 'xxxxxxxxxxxxxxxx')
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   334
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   335
    expectedO = '<19BDBD240E0866B84C49AEEF7E2350045DB8BDAE96E039BF4E3F12DAC3427DB6>'
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   336
    expectedU = '<564747DADFF35F5F2078A2CA1705B50800000000000000000000000000000000>'
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   337
    expectedKey = '<DC1E019846B1EEABA0CDB8ED6D53B5C4>'  # 16 byte key = 128 bits
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   338
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   339
    assert hexText(enc.O) == expectedO, '128 bit unexpected O value %s' % hexText(enc.O)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   340
    assert hexText(enc.U) == expectedU, '128 bit unexpected U value %s' % hexText(enc.U)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   341
    assert hexText(enc.key) == expectedKey, '128 bit unexpected key value %s' % hexText(enc.key)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   342
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   343
    ######################################################################
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   344
    #
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   345
    #  These represent the higher level API functions
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   346
    #
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   347
    ######################################################################
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   348
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   349
def encryptCanvas(canvas,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   350
                  userPassword, ownerPassword=None,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   351
                  canPrint=1, canModify=1, canCopy=1, canAnnotate=1,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   352
                  strength=40):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   353
    "Applies encryption to the document being generated"
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   354
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   355
    enc = StandardEncryption(userPassword, ownerPassword,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   356
                             canPrint, canModify, canCopy, canAnnotate,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   357
                             strength=strength)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   358
    canvas._doc.encrypt = enc
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   359
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   360
# Platypus stuff needs work, sadly.  I wanted to do it without affecting
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   361
# needing changes to latest release.
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   362
class EncryptionFlowable(StandardEncryption, Flowable):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   363
    """Drop this in your Platypus story and it will set up the encryption options.
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   364
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   365
    If you do it multiple times, the last one before saving will win."""
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   366
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   367
    def wrap(self, availWidth, availHeight):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   368
        return (0,0)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   369
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   370
    def draw(self):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   371
        encryptCanvas(self.canv,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   372
                      self.userPassword,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   373
                      self.ownerPassword,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   374
                      self.canPrint,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   375
                      self.canModify,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   376
                      self.canCopy,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   377
                      self.canAnnotate)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   378
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   379
##  I am thinking about this one.  Needs a change to reportlab to
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   380
##  work.
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   381
def encryptDocTemplate(dt,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   382
                  userPassword, ownerPassword=None,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   383
                  canPrint=1, canModify=1, canCopy=1, canAnnotate=1,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   384
                       strength=40):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   385
    "For use in Platypus.  Call before build()."
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   386
    raise Exception("Not implemented yet")
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   387
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   388
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   389
def encryptPdfInMemory(inputPDF,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   390
                  userPassword, ownerPassword=None,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   391
                  canPrint=1, canModify=1, canCopy=1, canAnnotate=1,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   392
                       strength=40):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   393
    """accepts a PDF file 'as a byte array in memory'; return encrypted one.
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   394
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   395
    This is a high level convenience and does not touch the hard disk in any way.
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   396
    If you are encrypting the same file over and over again, it's better to use
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   397
    pageCatcher and cache the results."""
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   398
3073
6554a30b7450 Stop pdfencrypt from expecting rlextra to be present.
jonas
parents: 3071
diff changeset
   399
    try:
6554a30b7450 Stop pdfencrypt from expecting rlextra to be present.
jonas
parents: 3071
diff changeset
   400
        from rlextra.pageCatcher.pageCatcher import storeFormsInMemory, restoreFormsInMemory
6554a30b7450 Stop pdfencrypt from expecting rlextra to be present.
jonas
parents: 3071
diff changeset
   401
    except ImportError:
6554a30b7450 Stop pdfencrypt from expecting rlextra to be present.
jonas
parents: 3071
diff changeset
   402
        raise ImportError('''reportlab.lib.pdfencrypt.encryptPdfInMemory failed because rlextra cannot be imported.
6554a30b7450 Stop pdfencrypt from expecting rlextra to be present.
jonas
parents: 3071
diff changeset
   403
See http://developer.reportlab.com''')
6554a30b7450 Stop pdfencrypt from expecting rlextra to be present.
jonas
parents: 3071
diff changeset
   404
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   405
    (bboxInfo, pickledForms) = storeFormsInMemory(inputPDF, all=1, BBoxes=1)
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   406
    names = list(bboxInfo.keys())
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   407
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   408
    firstPageSize = bboxInfo['PageForms0'][2:]
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   409
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   410
    #now make a new PDF document
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   411
    buf = getBytesIO()
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   412
    canv = Canvas(buf, pagesize=firstPageSize)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   413
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   414
    # set a standard ID while debugging
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   415
    if CLOBBERID:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   416
        canv._doc._ID = "[(xxxxxxxxxxxxxxxx)(xxxxxxxxxxxxxxxx)]"
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   417
    encryptCanvas(canv,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   418
                  userPassword, ownerPassword,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   419
                  canPrint, canModify, canCopy, canAnnotate,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   420
                  strength=strength)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   421
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   422
    formNames = restoreFormsInMemory(pickledForms, canv)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   423
    for formName in formNames:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   424
        #need to extract page size in future
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   425
        canv.doForm(formName)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   426
        canv.showPage()
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   427
    canv.save()
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   428
    return buf.getvalue()
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   429
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   430
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   431
def encryptPdfOnDisk(inputFileName, outputFileName,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   432
                  userPassword, ownerPassword=None,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   433
                  canPrint=1, canModify=1, canCopy=1, canAnnotate=1,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   434
                     strength=40):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   435
    "Creates encrypted file OUTPUTFILENAME.  Returns size in bytes."
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   436
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   437
    inputPDF = open(inputFileName, 'rb').read()
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   438
    outputPDF = encryptPdfInMemory(inputPDF,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   439
                  userPassword, ownerPassword,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   440
                  canPrint, canModify, canCopy, canAnnotate,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   441
                                   strength=strength)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   442
    open(outputFileName, 'wb').write(outputPDF)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   443
    return len(outputPDF)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   444
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   445
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   446
def scriptInterp():
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   447
    sys_argv = sys.argv[:] # copy
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   448
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   449
    usage = """PDFENCRYPT USAGE:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   450
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   451
PdfEncrypt encrypts your PDF files.
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   452
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   453
Line mode usage:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   454
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   455
% pdfencrypt.exe pdffile [-o ownerpassword] | [owner ownerpassword],
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   456
\t[-u userpassword] | [user userpassword],
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   457
\t[-p 1|0] | [printable 1|0],
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   458
\t[-m 1|0] | [modifiable 1|0],
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   459
\t[-c 1|0] | [copypastable 1|0],
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   460
\t[-a 1|0] | [annotatable 1|0],
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   461
\t[-s savefilename] | [savefile savefilename],
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   462
\t[-v 1|0] | [verbose 1|0],
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   463
\t[-e128], [encrypt128],
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   464
\t[-h] | [help]
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   465
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   466
-o or owner set the owner password.
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   467
-u or user set the user password.
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   468
-p or printable set the printable attribute (must be 1 or 0).
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   469
-m or modifiable sets the modifiable attribute (must be 1 or 0).
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   470
-c or copypastable sets the copypastable attribute (must be 1 or 0).
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   471
-a or annotatable sets the annotatable attribute (must be 1 or 0).
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   472
-s or savefile sets the name for the output PDF file
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   473
-v or verbose prints useful output to the screen.
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   474
      (this defaults to 'pdffile_encrypted.pdf').
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   475
'-e128' or 'encrypt128' allows you to use 128 bit encryption (in beta).
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   476
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   477
-h or help prints this message.
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   478
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   479
See PdfEncryptIntro.pdf for more information.
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   480
"""
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   481
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   482
    known_modes = ['-o', 'owner',
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   483
                   '-u', 'user',
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   484
                   '-p', 'printable',
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   485
                   '-m', 'modifiable',
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   486
                   '-c', 'copypastable',
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   487
                   '-a', 'annotatable',
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   488
                   '-s', 'savefile',
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   489
                   '-v', 'verbose',
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   490
                   '-h', 'help',
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   491
                   '-e128', 'encrypt128']
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   492
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   493
    OWNER        = ''
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   494
    USER         = ''
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   495
    PRINTABLE    = 1
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   496
    MODIFIABLE   = 1
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   497
    COPYPASTABLE = 1
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   498
    ANNOTATABLE  = 1
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   499
    SAVEFILE     = 'encrypted.pdf'
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   500
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   501
    #try:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   502
    caller = sys_argv[0] # may be required later - eg if called by security.py
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   503
    argv = list(sys_argv)[1:]
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   504
    if len(argv)>0:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   505
        if argv[0] == '-h' or argv[0] == 'help':
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   506
            print(usage)
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   507
            return
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   508
        if len(argv)<2:
3328
4d7f836cd947 reportlab: fix 2to3 warnings
rgbecker
parents: 3326
diff changeset
   509
            raise ValueError("Must include a filename and one or more arguments!")
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   510
        if argv[0] not in known_modes:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   511
            infile = argv[0]
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   512
            argv = argv[1:]
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   513
            if not os.path.isfile(infile):
3328
4d7f836cd947 reportlab: fix 2to3 warnings
rgbecker
parents: 3326
diff changeset
   514
                raise ValueError("Can't open input file '%s'!" % infile)
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   515
        else:
3328
4d7f836cd947 reportlab: fix 2to3 warnings
rgbecker
parents: 3326
diff changeset
   516
            raise ValueError("First argument must be name of the PDF input file!")
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   517
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   518
        # meaningful name at this stage
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   519
        STRENGTH = 40
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   520
        if 'encrypt128' in argv:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   521
            STRENGTH = 128
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   522
            argv.remove('encrypt128')
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   523
        if '-e128' in argv:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   524
            STRENGTH = 128
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   525
            argv.remove('-e128')
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   526
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   527
        if ('-v' in argv) or ('verbose' in argv):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   528
            if '-v' in argv:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   529
                pos = argv.index('-v')
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   530
                arg = "-v"
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   531
            elif 'verbose' in argv:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   532
                pos = argv.index('verbose')
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   533
                arg = "verbose"
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   534
            try:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   535
                verbose = int(argv[pos+1])
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   536
            except:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   537
                verbose = 1
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   538
            argv.remove(argv[pos+1])
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   539
            argv.remove(arg)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   540
        else:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   541
            from reportlab.rl_config import verbose
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   542
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   543
        #argument, valid license variable, invalid license variable, text for print
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   544
        arglist = (('-o', 'OWNER', OWNER, 'Owner password'),
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   545
                   ('owner', 'OWNER', OWNER, 'Owner password'),
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   546
                   ('-u', 'USER', USER, 'User password'),
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   547
                   ('user', 'USER', USER, 'User password'),
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   548
                   ('-p', 'PRINTABLE', PRINTABLE, "'Printable'"),
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   549
                   ('printable', 'PRINTABLE', PRINTABLE, "'Printable'"),
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   550
                   ('-m', 'MODIFIABLE', MODIFIABLE, "'Modifiable'"),
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   551
                   ('modifiable', 'MODIFIABLE',  MODIFIABLE, "'Modifiable'"),
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   552
                   ('-c', 'COPYPASTABLE', COPYPASTABLE, "'Copypastable'"),
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   553
                   ('copypastable', 'COPYPASTABLE', COPYPASTABLE, "'Copypastable'"),
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   554
                   ('-a', 'ANNOTATABLE', ANNOTATABLE, "'Annotatable'"),
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   555
                   ('annotatable', 'ANNOTATABLE', ANNOTATABLE, "'Annotatable'"),
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   556
                   ('-s', 'SAVEFILE', SAVEFILE, "Output file"),
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   557
                   ('savefile', 'SAVEFILE', SAVEFILE, "Output file"),
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   558
                   )
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   559
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   560
        binaryrequired = ('-p', 'printable', '-m', 'modifiable', 'copypastable', '-c', 'annotatable', '-a')
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   561
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   562
        for thisarg in arglist:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   563
            if thisarg[0] in argv:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   564
                pos = argv.index(thisarg[0])
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   565
                if thisarg[0] in binaryrequired:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   566
                    #try:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   567
                    if argv[pos+1] not in ('1', '0'):
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   568
                        raise "%s value must be either '1' or '0'!" % thisarg[1]
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   569
                    #except:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   570
                        #raise "Unable to set %s." % thisarg[4]
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   571
                try:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   572
                    if argv[pos+1] not in known_modes:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   573
                        if thisarg[0] in binaryrequired:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   574
                            exec(thisarg[1] +' = int(argv[pos+1])')
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   575
                        else:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   576
                            exec(thisarg[1] +' = argv[pos+1]')
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   577
                        if verbose:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   578
                            print("%s set to: '%s'." % (thisarg[3], argv[pos+1]))
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   579
                        argv.remove(argv[pos+1])
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   580
                        argv.remove(thisarg[0])
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   581
                except:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   582
                    raise "Unable to set %s." % thisarg[3]
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   583
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   584
        if verbose>4:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   585
            #useful if feeling paranoid and need to double check things at this point...
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   586
            print("\ninfile:", infile)
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   587
            print("STRENGTH:", STRENGTH)
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   588
            print("SAVEFILE:", SAVEFILE)
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   589
            print("USER:", USER)
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   590
            print("OWNER:", OWNER)
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   591
            print("PRINTABLE:", PRINTABLE)
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   592
            print("MODIFIABLE:", MODIFIABLE)
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   593
            print("COPYPASTABLE:", COPYPASTABLE)
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   594
            print("ANNOTATABLE:", ANNOTATABLE)
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   595
            print("SAVEFILE:", SAVEFILE)
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   596
            print("VERBOSE:", verbose)
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   597
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   598
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   599
        if SAVEFILE == 'encrypted.pdf':
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   600
            if infile[-4:] == '.pdf' or infile[-4:] == '.PDF':
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   601
                tinfile = infile[:-4]
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   602
            else:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   603
                tinfile = infile
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   604
            SAVEFILE = tinfile+"_encrypted.pdf"
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   605
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   606
        filesize = encryptPdfOnDisk(infile, SAVEFILE, USER, OWNER,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   607
                  PRINTABLE, MODIFIABLE, COPYPASTABLE, ANNOTATABLE,
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   608
                                    strength=STRENGTH)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   609
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   610
        if verbose:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   611
            print("wrote output file '%s'(%s bytes)\n  owner password is '%s'\n  user password is '%s'" % (SAVEFILE, filesize, OWNER, USER))
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   612
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   613
        if len(argv)>0:
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   614
            raise "\nUnrecognised arguments : %s\nknown arguments are:\n%s" % (str(argv)[1:-1], known_modes)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   615
    else:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   616
        print(usage)
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   617
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   618
def main():
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   619
    from reportlab.rl_config import verbose
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   620
    scriptInterp()
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   621
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   622
if __name__=="__main__": #NO RUNTESTS
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   623
    a = [x for x in sys.argv if x[:7]=='--debug']
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   624
    if a:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   625
        sys.argv = [x for x in sys.argv if x[:7]!='--debug']
3035
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   626
        DEBUG = len(a)
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   627
    if '--test' in sys.argv: test()
41408333df89 Add pdfencrypt to reportlab.lib.
jonas
parents:
diff changeset
   628
    else: main()