From 15f30beadd98cfda18d20f68257e7694c9442fbb Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 24 Mar 2012 18:05:39 -0400 Subject: [PATCH] Add AssuanClient.send_data(). --- pyassuan/client.py | 44 ++++++++++++++++++++++++++++++++++++++------ pyassuan/common.py | 10 ++++++++-- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/pyassuan/client.py b/pyassuan/client.py index 7abe617..ccedff8 100644 --- a/pyassuan/client.py +++ b/pyassuan/client.py @@ -60,7 +60,7 @@ class AssuanClient (object): self.logger.info('S: {}'.format(response)) return response - def make_request(self, request, response=True, expect=['OK']): + def _write_request(self, request): rstring = str(request) self.logger.info('C: {}'.format(rstring)) self.output.write(rstring) @@ -68,11 +68,14 @@ class AssuanClient (object): try: self.output.flush() except IOError: - raise + raise + + def make_request(self, request, response=True, expect=['OK']): + self._write_request(request=request) if response: - return self.get_responses(request=request, expect=expect) + return self.get_responses(requests=[request], expect=expect) - def get_responses(self, request=None, expect=['OK']): + def get_responses(self, requests=None, expect=['OK']): responses = list(self.responses()) if responses[-1].type == 'ERR': eresponse = responses[-1] @@ -83,8 +86,8 @@ class AssuanClient (object): else: message = None error = _error.AssuanError(code=code, message=message) - if request is not None: - error.request = request + if requests is not None: + error.requests = requests error.responses = responses raise error if expect: @@ -105,3 +108,32 @@ class AssuanClient (object): yield response if response.type not in ['S', '#', 'D']: break + + def send_data(self, data=None, response=True, expect=['OK']): + """Iterate through requests necessary to send ``data`` to a server. + + http://www.gnupg.org/documentation/manuals/assuan/Client-requests.html + """ + requests = [] + if data: + encoded_data = _common.encode(data) + start = 0 + stop = min(_common.LINE_LENGTH-4, len(encoded_data)) # 'D ', CR, CL + self.logger.debug('sending {} bytes of encoded data'.format( + len(encoded_data))) + while stop > start: + d = encoded_data[start:stop] + request = _common.Request( + command='D', parameters=encoded_data[start:stop], + encoded=True) + requests.append(request) + self.logger.debug('send {} byte chunk'.format(stop-start)) + self._write_request(request=request) + start = stop + stop = start + min(_common.LINE_LENGTH-4, + len(encoded_data) - start) + request = _common.Request('END') + requests.append(request) + self._write_request(request=request) + if response: + return self.get_responses(requests=requests, expect=expect) diff --git a/pyassuan/common.py b/pyassuan/common.py index dbae91a..684078c 100644 --- a/pyassuan/common.py +++ b/pyassuan/common.py @@ -8,6 +8,7 @@ import re as _re from . import error as _error +LINE_LENGTH = 1002 # 1000 + [CR,]LF _ENCODE_REGEXP = _re.compile( '(' + '|'.join(['%', '\r', '\n']) + ')') _DECODE_REGEXP = _re.compile('(%[0-9A-F]{2})') @@ -83,13 +84,18 @@ class Request (object): ... pyassuan.error.AssuanError: 170 Invalid request """ - def __init__(self, command=None, parameters=None): + def __init__(self, command=None, parameters=None, encoded=False): self.command = command self.parameters = parameters + self.encoded = encoded def __str__(self): if self.parameters: - return '{} {}'.format(self.command, encode(self.parameters)) + if self.encoded: + encoded_parameters = self.parameters + else: + encoded_parameters = encode(self.parameters) + return '{} {}'.format(self.command, encoded_parameters) return self.command def from_string(self, string): -- 2.26.2