py3: decode bytes for json.loads()

In py 3.5 json.loads requires to have string as input, all bytes must be
decoded.

Note: python 3.6 supports bytes for json.loads()

https://fedorahosted.org/freeipa/ticket/4985

Reviewed-By: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
This commit is contained in:
Martin Basti
2017-01-12 16:20:43 +01:00
parent 0eb5a0e0ec
commit 18337bf7f7
5 changed files with 59 additions and 6 deletions

View File

@@ -969,7 +969,7 @@ class vault_retrieve(Local):
json_vault_data = decoding_ctx.cipher_op(wrapped_vault_data)\ json_vault_data = decoding_ctx.cipher_op(wrapped_vault_data)\
+ decoding_ctx.digest_final() + decoding_ctx.digest_final()
vault_data = json.loads(json_vault_data) vault_data = json.loads(json_vault_data.decode('utf-8'))
data = base64.b64decode(vault_data[u'data'].encode('utf-8')) data = base64.b64decode(vault_data[u'data'].encode('utf-8'))
encrypted_key = None encrypted_key = None

View File

@@ -1101,7 +1101,8 @@ class JSONServerProxy(object):
) )
try: try:
response = json_decode_binary(json.loads(response.decode('ascii'))) response = json_decode_binary(
json.loads(response.decode('utf-8')))
except ValueError as e: except ValueError as e:
raise JSONError(error=str(e)) raise JSONError(error=str(e))

View File

@@ -209,6 +209,7 @@ def _httplib_request(
http_body = res.read() http_body = res.read()
conn.close() conn.close()
except Exception as e: except Exception as e:
root_logger.exception("httplib request failed:")
raise NetworkError(uri=uri, error=str(e)) raise NetworkError(uri=uri, error=str(e))
root_logger.debug('response status %d', http_status) root_logger.debug('response status %d', http_status)

View File

@@ -19,6 +19,7 @@
from __future__ import print_function from __future__ import print_function
import codecs
import string import string
import tempfile import tempfile
import subprocess import subprocess
@@ -1361,6 +1362,55 @@ def escape_seq(seq, *args):
return tuple(a.replace(seq, u'\\{}'.format(seq)) for a in args) return tuple(a.replace(seq, u'\\{}'.format(seq)) for a in args)
def decode_json(data):
"""Decode JSON bytes to string with proper encoding
Only for supporting Py 3.5
Py 3.6 supports bytes as parameter for json.load, we can drop this when
there is no need for python 3.5 anymore
Code from:
https://bugs.python.org/file43513/json_detect_encoding_3.patch
:param data: JSON bytes
:return: return JSON string
"""
def detect_encoding(b):
bstartswith = b.startswith
if bstartswith((codecs.BOM_UTF32_BE, codecs.BOM_UTF32_LE)):
return 'utf-32'
if bstartswith((codecs.BOM_UTF16_BE, codecs.BOM_UTF16_LE)):
return 'utf-16'
if bstartswith(codecs.BOM_UTF8):
return 'utf-8-sig'
if len(b) >= 4:
if not b[0]:
# 00 00 -- -- - utf-32-be
# 00 XX -- -- - utf-16-be
return 'utf-16-be' if b[1] else 'utf-32-be'
if not b[1]:
# XX 00 00 00 - utf-32-le
# XX 00 XX XX - utf-16-le
return 'utf-16-le' if b[2] or b[3] else 'utf-32-le'
elif len(b) == 2:
if not b[0]:
# 00 XX - utf-16-be
return 'utf-16-be'
if not b[1]:
# XX 00 - utf-16-le
return 'utf-16-le'
# default
return 'utf-8'
if isinstance(data, six.text_type):
return data
return data.decode(detect_encoding(data), 'surrogatepass')
class APIVersion(tuple): class APIVersion(tuple):
"""API version parser and handler """API version parser and handler

View File

@@ -1232,7 +1232,8 @@ class RestClient(Backend):
@staticmethod @staticmethod
def _parse_dogtag_error(body): def _parse_dogtag_error(body):
try: try:
return pki.PKIException.from_json(json.loads(body)) return pki.PKIException.from_json(
json.loads(ipautil.decode_json(body)))
except Exception: except Exception:
return None return None
@@ -1667,7 +1668,7 @@ class ra(rabase.rabase, RestClient):
) )
try: try:
resp_obj = json.loads(http_body) resp_obj = json.loads(ipautil.decode_json(http_body))
except ValueError: except ValueError:
raise errors.RemoteRetrieveError(reason=_("Response from CA was not valid JSON")) raise errors.RemoteRetrieveError(reason=_("Response from CA was not valid JSON"))
@@ -2115,7 +2116,7 @@ class ra_lightweight_ca(RestClient):
body=json.dumps({"parentID": "host-authority", "dn": unicode(dn)}), body=json.dumps({"parentID": "host-authority", "dn": unicode(dn)}),
) )
try: try:
return json.loads(resp_body) return json.loads(ipautil.decode_json(resp_body))
except Exception as e: except Exception as e:
self.log.debug(e, exc_info=True) self.log.debug(e, exc_info=True)
raise errors.RemoteRetrieveError( raise errors.RemoteRetrieveError(
@@ -2125,7 +2126,7 @@ class ra_lightweight_ca(RestClient):
_status, _resp_headers, resp_body = self._ssldo( _status, _resp_headers, resp_body = self._ssldo(
'GET', ca_id, headers={'Accept': 'application/json'}) 'GET', ca_id, headers={'Accept': 'application/json'})
try: try:
return json.loads(resp_body) return json.loads(ipautil.decode_json(resp_body))
except Exception as e: except Exception as e:
self.log.debug(e, exc_info=True) self.log.debug(e, exc_info=True)
raise errors.RemoteRetrieveError( raise errors.RemoteRetrieveError(