codekingpro/portable-devtools
114k
1"""
2"""
3
4# Created on 2014.07.04
5#
6# Author: Giovanni Cannata
7#
8# Copyright 2014 - 2020 Giovanni Cannata
9#
10# This file is part of ldap3.
11#
12# ldap3 is free software: you can redistribute it and/or modify
13# it under the terms of the GNU Lesser General Public License as published
14# by the Free Software Foundation, either version 3 of the License, or
15# (at your option) any later version.
16#
17# ldap3 is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20# GNU Lesser General Public License for more details.
21#
22# You should have received a copy of the GNU Lesser General Public License
23# along with ldap3 in the COPYING and COPYING.LESSER files.
24# If not, see <http://www.gnu.org/licenses/>.
25
26from ..core.results import RESULT_SUCCESS
27from ..core.exceptions import LDAPExtensionError
28from ..utils.asn1 import decoder
29
30
31class ExtendedOperation(object):
32 def __init__(self, connection, controls=None):
33 self.connection = connection
34 self.decoded_response = None
35 self.result = None
36 self.asn1_spec = None # if None the response_value is returned without encoding
37 self.request_name = None
38 self.response_name = None
39 self.request_value = None
40 self.response_value = None
41 self.response_attribute = None
42 self.controls = controls
43 self.config()
44
45 def send(self):
46 if self.connection.check_names and self.connection.server.info is not None and self.connection.server.info.supported_extensions is not None: # checks if extension is supported
47 for request_name in self.connection.server.info.supported_extensions:
48 if request_name[0] == self.request_name:
49 break
50 else:
51 raise LDAPExtensionError('extension not in DSA list of supported extensions')
52
53 resp = self.connection.extended(self.request_name, self.request_value, self.controls)
54 if not self.connection.strategy.sync:
55 _, result = self.connection.get_response(resp)
56 else:
57 if self.connection.strategy.thread_safe:
58 _, result, _, _ = resp
59 else:
60 result = self.connection.result
61 self.result = result
62 self.decode_response(result)
63 self.populate_result()
64 self.set_response()
65 return self.response_value
66
67 def populate_result(self):
68 pass
69
70 def decode_response(self, response=None):
71 if not response:
72 response = self.result
73 if not response:
74 return None
75 if response['result'] not in [RESULT_SUCCESS]:
76 if self.connection.raise_exceptions:
77 raise LDAPExtensionError('extended operation error: ' + response['description'] + ' - ' + response['message'])
78 else:
79 return None
80 if not self.response_name or response['responseName'] == self.response_name:
81 if response['responseValue']:
82 if self.asn1_spec is not None:
83 decoded, unprocessed = decoder.decode(response['responseValue'], asn1Spec=self.asn1_spec)
84 if unprocessed:
85 raise LDAPExtensionError('error decoding extended response value')
86 self.decoded_response = decoded
87 else:
88 self.decoded_response = response['responseValue']
89 else:
90 raise LDAPExtensionError('invalid response name received')
91
92 def set_response(self):
93 self.response_value = self.result[self.response_attribute] if self.result and self.response_attribute in self.result else None
94 if not self.connection.strategy.thread_safe:
95 self.connection.response = self.response_value
96
97 def config(self):
98 pass
99 