Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions cl_sii/libs/encoding_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import base64
import binascii
from typing import Union


def clean_base64(value: Union[str, bytes]) -> bytes:
"""
Force bytes and remove line breaks and spaces.

Does not validate base64 format.

:raises ValueError:
:raises TypeError:

"""
if isinstance(value, bytes):
value_base64_bytes = value
elif isinstance(value, str):
try:
value_base64_bytes = value.strip().encode(encoding='ascii', errors='strict')
except UnicodeEncodeError as exc:
raise ValueError("Only ASCII characters are accepted.", str(exc)) from exc
else:
raise TypeError("Value must be str or bytes.")

# remove line breaks and spaces
value_base64_bytes_cleaned = value_base64_bytes.replace(b'\n', b'').replace(b' ', b'')

return value_base64_bytes_cleaned


def decode_base64_strict(value: Union[str, bytes]) -> bytes:
"""
Strict conversion for str/bytes, tolerating only line breaks and spaces.

:raises ValueError: non-base64 input or non-ASCII characters included

"""
value_base64_bytes_cleaned = clean_base64(value)
try:
value_bytes = base64.b64decode(value_base64_bytes_cleaned, validate=True)
except binascii.Error as exc:
raise ValueError("Input is not a valid base64 value.", str(exc)) from exc
return value_bytes


def validate_base64(value: Union[str, bytes]) -> None:
"""
Validate that ``value`` is base64-encoded data.

:raises ValueError:
:raises TypeError:

"""
decode_base64_strict(value)
18 changes: 18 additions & 0 deletions tests/test_libs_encoding_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import unittest

from cl_sii.libs.encoding_utils import clean_base64, decode_base64_strict, validate_base64 # noqa: F401,E501


class FunctionsTest(unittest.TestCase):

def test_clean_base64(self):
# TODO: implement for function 'clean_base64'.
pass

def test_decode_base64_strict(self):
# TODO: implement for function 'decode_base64_strict'.
pass

def test_validate_base64(self):
# TODO: implement for function 'validate_base64'.
pass