1from __future__ import absolute_import
2# Copyright (c) 2010-2019 openpyxl
3
4from openpyxl.descriptors import (
5    Bool,
6    String,
7    Alias,
8    Integer,
9)
10from openpyxl.descriptors.serialisable import Serialisable
11from openpyxl.descriptors.excel import (
12    Base64Binary,
13)
14from openpyxl.utils.protection import hash_password
15
16
17class _Protected(object):
18    _password = None
19
20    def set_password(self, value='', already_hashed=False):
21        """Set a password on this sheet."""
22        if not already_hashed:
23            value = hash_password(value)
24        self._password = value
25
26    @property
27    def password(self):
28        """Return the password value, regardless of hash."""
29        return self._password
30
31    @password.setter
32    def password(self, value):
33        """Set a password directly, forcing a hash step."""
34        self.set_password(value)
35
36
37class SheetProtection(Serialisable, _Protected):
38    """
39    Information about protection of various aspects of a sheet. True values
40    mean that protection for the object or action is active This is the
41    **default** when protection is active, ie. users cannot do something
42    """
43
44    tagname = "sheetProtection"
45
46    sheet = Bool()
47    enabled = Alias('sheet')
48    objects = Bool()
49    scenarios = Bool()
50    formatCells = Bool()
51    formatColumns = Bool()
52    formatRows = Bool()
53    insertColumns = Bool()
54    insertRows = Bool()
55    insertHyperlinks = Bool()
56    deleteColumns = Bool()
57    deleteRows = Bool()
58    selectLockedCells = Bool()
59    selectUnlockedCells = Bool()
60    sort = Bool()
61    autoFilter = Bool()
62    pivotTables = Bool()
63    saltValue = Base64Binary(allow_none=True)
64    spinCount = Integer(allow_none=True)
65    algorithmName = String(allow_none=True)
66    hashValue = Base64Binary(allow_none=True)
67
68
69    __attrs__ = ('selectLockedCells', 'selectUnlockedCells', 'algorithmName',
70              'sheet', 'objects', 'insertRows', 'insertHyperlinks', 'autoFilter',
71              'scenarios', 'formatColumns', 'deleteColumns', 'insertColumns',
72              'pivotTables', 'deleteRows', 'formatCells', 'saltValue', 'formatRows',
73              'sort', 'spinCount', 'password', 'hashValue')
74
75
76    def __init__(self, sheet=False, objects=False, scenarios=False,
77                 formatCells=True, formatRows=True, formatColumns=True,
78                 insertColumns=True, insertRows=True, insertHyperlinks=True,
79                 deleteColumns=True, deleteRows=True, selectLockedCells=False,
80                 selectUnlockedCells=False, sort=True, autoFilter=True, pivotTables=True,
81                 password=None, algorithmName=None, saltValue=None, spinCount=None, hashValue=None):
82        self.sheet = sheet
83        self.objects = objects
84        self.scenarios = scenarios
85        self.formatCells = formatCells
86        self.formatColumns = formatColumns
87        self.formatRows = formatRows
88        self.insertColumns = insertColumns
89        self.insertRows = insertRows
90        self.insertHyperlinks = insertHyperlinks
91        self.deleteColumns = deleteColumns
92        self.deleteRows = deleteRows
93        self.selectLockedCells = selectLockedCells
94        self.selectUnlockedCells = selectUnlockedCells
95        self.sort = sort
96        self.autoFilter = autoFilter
97        self.pivotTables = pivotTables
98        if password is not None:
99            self.password = password
100        self.algorithmName = algorithmName
101        self.saltValue = saltValue
102        self.spinCount = spinCount
103        self.hashValue = hashValue
104
105
106    def set_password(self, value='', already_hashed=False):
107        super(SheetProtection, self).set_password(value, already_hashed)
108        self.enable()
109
110
111    def enable(self):
112        self.sheet = True
113
114
115    def disable(self):
116        self.sheet = False
117
118
119    def  __bool__(self):
120        return self.sheet
121
122    __nonzero__ = __bool__
123