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

Bastian Germann bage at linutronix.de
Mon Jul 20 15:13:52 CEST 2020


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:

Traceback (most recent call last):
  File "/var/cache/elbe/devel/elbepack/daemons/soap/faults.py", line
150, in wrapped
    return func(self, arg1, arg2, arg3)
  File "/var/cache/elbe/devel/elbepack/daemons/soap/esoap.py", line 318,
in start_upload_orig
    orig_fname = os.path.join(builddir, fname)
  File "/usr/lib/python2.7/posixpath.py", line 68, in join
    if b.startswith('/'):
AttributeError: 'NoneType' object has no attribute 'startswith'

> +        self.upload_file(client.service.append_upload_orig, args[0], args[1])
> +        client.service.finish_upload_orig(args[0])
>  
>  ClientAction.register(SetOrigAction)
>  
> @@ -723,27 +725,16 @@ class SetPdebuilderAction(ClientAction):
>          ClientAction.__init__(self, node)
>  
>      def execute(self, client, opt, args):
> -        size = 1024 * 1024
>  
>          if len(args) != 2 and len(args) != 3:
>              print("usage: elbe control set_pdebuild "
>                    "<project_dir> <pdebuild file>", file=sys.stderr)
>              sys.exit(20)
>  
> -        builddir = args[0]
> -        filename = args[1]
> -
> -        fp = open(filename, "r")
> -        client.service.start_pdebuild(builddir)
> -        while True:
> -            bindata = fp.read(size)
> -            client.service.append_pdebuild(
> -                builddir, binascii.b2a_base64(bindata))
> -            if len(bindata) != size:
> -                break
> -
> -        client.service.finish_pdebuild(builddir, opt.cpuset,
> -                                       opt.profile, opt.cross)
> +        client.service.start_pdebuild(args[0])
> +        self.upload_file(client.service.append_pdebuild, args[0], args[1])
> +        client.service.finish_pdebuild(args[0],
> +                                       opt.cpuset, opt.profile, opt.cross)
>  
>  
>  ClientAction.register(SetPdebuilderAction)
> @@ -902,13 +893,19 @@ class UploadPackageAction(RepoAction):
>          RepoAction.__init__(self, node)
>  
>      @staticmethod
> +    # pylint: disable=arguments-differ
>      def upload_file(client, f, builddir):
>          # Uploads file f into builddir in intivm
>          size = 1024 * 1024
>          part = 0
>          with open(f, "rb") as fp:
>              while True:
> +
>                  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,
> 


More information about the elbe-devel mailing list