1515import sqlite3
1616import collections
1717from random import randint
18+ import regex as re
1819from .internal .constants import Encoding
1920from .internal .helpers import (
2021 detect_delimiter ,
2324 UUEncoderDecoder ,
2425 Base92 ,
2526 Base45 ,
27+ _Base64 ,
28+ expand_alpha_range ,
2629)
2730
2831yaml = lazy_import .lazy_module ("yaml" )
@@ -494,7 +497,7 @@ def from_bytes(self) -> DataFormatT:
494497 return self
495498
496499 @ChepyDecorators .call_stack
497- def to_base64 (self , custom : str = None , url_safe : bool = False ) -> DataFormatT :
500+ def to_base64 (self , alphabet : str = "standard" ) -> DataFormatT :
498501 """Encode as Base64
499502
500503 Base64 is a notation for encoding arbitrary byte data using a
@@ -503,8 +506,7 @@ def to_base64(self, custom: str = None, url_safe: bool = False) -> DataFormatT:
503506 into an ASCII Base64 string.
504507
505508 Args:
506- custom (str, optional): Provide a custom charset to base64 with
507- url_safe (bool, optional): Encode with url safe charset.
509+ alphabet (str, optional): Provide a custom charset to base64 with. Valid values are: filename_safe, itoa64, radix_64, rot13, standard, unix_crypt, url_safe, xml, xxencoding, z64
508510
509511 Returns:
510512 Chepy: The Chepy object.
@@ -515,27 +517,23 @@ def to_base64(self, custom: str = None, url_safe: bool = False) -> DataFormatT:
515517 >>> Chepy("Some data").to_base64(custom=custom).o
516518 b'IqxhNG/YMLFV'
517519 """
518- if url_safe :
519- self .state = base64 .urlsafe_b64encode (self ._convert_to_bytes ()).replace (
520- b"=" , b""
521- )
522- return self
523- if custom is not None :
524- x = base64 .b64encode (self ._convert_to_bytes ())
525- std_base64chars = (
526- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
527- )
528- self .state = bytes (
529- str (x )[2 :- 1 ].translate (str (x )[2 :- 1 ].maketrans (std_base64chars , custom )),
530- "utf-8" ,
520+ data = self ._convert_to_bytes ()
521+ alphabet = alphabet .strip ()
522+
523+ char_set = expand_alpha_range (
524+ _Base64 .base_64_chars .get (alphabet , alphabet ), join_by = ""
525+ )
526+ if len (char_set ) < 63 or len (char_set ) > 66 : # pragma: no cover
527+ raise ValueError (
528+ "Invalid base64 chars. Should be 63-66 chars. " + str (len (char_set ))
531529 )
532- else :
533- self .state = base64 . b64encode ( self . _convert_to_bytes () )
530+
531+ self .state = _Base64 . encode_base64 ( data , alphabet = char_set )
534532 return self
535533
536534 @ChepyDecorators .call_stack
537535 def from_base64 (
538- self , custom : str = None , url_safe : bool = False , remove_whitespace : bool = True
536+ self , alphabet : str = "standard" , remove_non_alpha : bool = True
539537 ) -> DataFormatT :
540538 """Decode as Base64
541539
@@ -545,33 +543,46 @@ def from_base64(
545543 into an ASCII Base64 string.
546544
547545 Args:
548- custom (str, optional): Provide a custom charset to base64 with
549- url_safe (bool, optional): If true, decode url safe. Defaults to False
550- remove_whitespace (bool, optional): If true, all whitespaces are removed
546+ alphabet (str, optional): Provide a custom charset to base64 with. Valid values are: filename_safe, itoa64, radix_64, rot13, standard, unix_crypt, url_safe, xml, xxencoding, z64
547+ remove_whitespace (bool, optional): If true, all whitespaces are removed ( Defaults to True)
548+ remove_non_alpha (bool, optional): If true, all whitespaces are removed. (Defaults to True)
551549
552550 Returns:
553551 Chepy: The Chepy object.
554552
555553 Examples:
556554 Base64 decode using a custom string
557555 >>> c = Chepy("QqxhNG/mMKtYPqoz64FVR42=")
558- >>> c.from_base64(custom ="./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
556+ >>> c.from_base64(alphabet ="./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
559557 >>> c.out
560558 b"some random? data"
561559 """
562- if remove_whitespace :
563- data = self .remove_whitespace ().o
564- data = self ._convert_to_str ()
565- if custom is not None :
566- std_base64chars = (
567- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
560+ alphabet = alphabet .strip ()
561+ char_set = expand_alpha_range (
562+ _Base64 .base_64_chars .get (alphabet , alphabet ), join_by = ""
563+ )
564+ if len (char_set ) < 63 or len (char_set ) > 65 : # pragma: no cover
565+ raise ValueError (
566+ "Invalid base64 chars. Should be 63-65 chars. " + str (len (char_set ))
568567 )
569- data = data .translate (str .maketrans (custom , std_base64chars ))
570- data += "=="
571- if url_safe :
572- self .state = base64 .urlsafe_b64decode (data )
573- else :
574- self .state = base64 .b64decode (data )
568+
569+ data = self ._convert_to_str ()
570+
571+ if remove_non_alpha :
572+ data = re .sub ("[^" + char_set + "]" , "" , data )
573+
574+ # if is_standard or alphabet == 'url_safe':
575+ # data += "=="
576+ padding_needed = len (data ) % 4
577+ if padding_needed and alphabet != "url_safe" :
578+ data += "=" * (4 - padding_needed )
579+
580+ # if is_standard:
581+ # self.state = base64.b64decode(data)
582+ # if alphabet == 'url_safe':
583+ # self.state = base64.urlsafe_b64decode(data)
584+ # else:
585+ self .state = _Base64 .decode_base64 (data , char_set )
575586 return self
576587
577588 @ChepyDecorators .call_stack
0 commit comments