[elbe-devel] [PATCH] soapclient: Fix base64 encoding

Olivier Dion dion at linutronix.de
Mon Jul 20 16:21:54 CEST 2020


On Mon, 20 Jul 2020, Bastian Germann <bage at linutronix.de> wrote:
> Am 20.07.20 um 01:32 schrieb Olivier Dion:
>> In Py2, binascii.b2a_base64 returns a 'str' object, but in Py3
>> a 'bytes' object is returned.
>> 
>> The soap service apparently get confused when the data is a 'bytes'
>> object and will somehow add an extra 4 bytes at the end of the data.
>> This is the reason why cdrom upload did not work, because the upload
>> got corrupted.
>> 
>> Thus, the static method 'upload_file' defined for ClientAction can be
>> used by sub-classes.  This method ensures that the data is of type
>> 'str'.
>> 
>> Signed-off-by: Olivier Dion <dion at linutronix.de>
>> ---
>>  elbepack/soapclient.py | 87 ++++++++++++++++++++----------------------
>>  1 file changed, 42 insertions(+), 45 deletions(-)
>> 
>> diff --git a/elbepack/soapclient.py b/elbepack/soapclient.py
>> index a465b615..3907c849 100644
>> --- a/elbepack/soapclient.py
>> +++ b/elbepack/soapclient.py
>> @@ -146,6 +146,26 @@ class ClientAction(object):
>>      def __init__(self, node):
>>          self.node = node
>>  
>> +    @staticmethod
>> +    def upload_file(append, build_dir, filename):
>> +
>> +        size = 1024 * 1024
>> +
>> +        with open(filename, "rb") as f:
>> +
>> +            while True:
>> +
>> +                bin_data = f.read(size)
>> +                data = binascii.b2a_base64(bin_data)
>> +
>> +                if not isinstance(data, str):
>> +                    data = data.decode("ascii")
>> +
>> +                append(build_dir, data)
>> +
>> +                if len(bin_data) != size:
>> +                    break
>> +
>>      def execute(self, _client, _opt, _args):
>>          raise NotImplementedError('execute() not implemented')
>>  
>> @@ -331,7 +351,12 @@ class SetXmlAction(ClientAction):
>>          part = 0
>>          with open(filename, "rb") as fp:
>>              while True:
>> -                xml_base64 = binascii.b2a_base64(fp.read(size)).decode('ascii')
>> +
>> +                xml_base64 = binascii.b2a_base64(fp.read(size))
>> +
>> +                if not isinstance(xml_base64, str):
>> +                    xml_base64 = xml_base64.decode('ascii')
>> +
>>                  # finish upload
>>                  if len(xml_base64) == 1:
>>                      part = client.service.upload_file(builddir,
>> @@ -634,7 +659,6 @@ class SetCdromAction(ClientAction):
>>          ClientAction.__init__(self, node)
>>  
>>      def execute(self, client, _opt, args):
>> -        size = 1024 * 1024
>>  
>>          if len(args) != 2:
>>              print(
>> @@ -642,19 +666,9 @@ class SetCdromAction(ClientAction):
>>                  file=sys.stderr)
>>              sys.exit(20)
>>  
>> -        builddir = args[0]
>> -        filename = args[1]
>> -
>> -        fp = open(filename, "rb")
>> -        client.service.start_cdrom(builddir)
>> -        while True:
>> -            bindata = fp.read(size)
>> -            client.service.append_cdrom(builddir, binascii.b2a_base64(bindata))
>> -            if len(bindata) != size:
>> -                break
>> -
>> -        client.service.finish_cdrom(builddir)
>> -
>> +        client.service.start_cdrom(args[0])
>> +        self.upload_file(client.service.append_cdrom, args[0], args[1])
>> +        client.service.finish_cdrom(args[0])
>>  
>>  ClientAction.register(SetCdromAction)
>>  
>> @@ -667,7 +681,6 @@ class SetOrigAction(ClientAction):
>>          ClientAction.__init__(self, node)
>>  
>>      def execute(self, client, _opt, args):
>> -        size = 1024 * 1024
>>  
>>          if len(args) != 2:
>>              print(
>> @@ -675,20 +688,9 @@ class SetOrigAction(ClientAction):
>>                  file=sys.stderr)
>>              sys.exit(20)
>>  
>> -        builddir = args[0]
>> -        filename = args[1]
>> -
>> -        fp = open(filename, "r")
>> -        client.service.start_upload_orig(builddir, os.path.basename(filename))
>> -        while True:
>> -            bindata = fp.read(size)
>> -            client.service.append_upload_orig(
>> -                builddir, binascii.b2a_base64(bindata))
>> -            if len(bindata) != size:
>> -                break
>> -
>> -        client.service.finish_upload_orig(builddir)
>> -
>> +        client.service.start_upload_orig(args[0])
>
> You are missing the second parameter here! Result:

You're right.  Good catch!  Pylint can't see that apparently.

-- 
Olivier Dion
Linutronix GmbH | Bahnhofstrasse 3 | D-88690 Uhldingen-Mühlhofen


More information about the elbe-devel mailing list