|
| 1 | + |
| 2 | +PAD = '=' |
| 3 | + |
| 4 | +table_a2b_base64 = [ |
| 5 | + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, |
| 6 | + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, |
| 7 | + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, |
| 8 | + 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, # Note PAD->-1 here |
| 9 | + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, |
| 10 | + 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, |
| 11 | + -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, |
| 12 | + 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1, |
| 13 | + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, |
| 14 | + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, |
| 15 | + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, |
| 16 | + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, |
| 17 | + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, |
| 18 | + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, |
| 19 | + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, |
| 20 | + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, |
| 21 | +] |
| 22 | +def _transform(n): |
| 23 | + if n == -1: |
| 24 | + return '\xff' |
| 25 | + else: |
| 26 | + return chr(n) |
| 27 | +table_a2b_base64 = ''.join(map(_transform, table_a2b_base64)) |
| 28 | +assert len(table_a2b_base64) == 256 |
| 29 | + |
| 30 | +def a2b_base64(ascii): |
| 31 | + "Decode a line of base64 data." |
| 32 | + |
| 33 | + res = [] |
| 34 | + quad_pos = 0 |
| 35 | + leftchar = 0 |
| 36 | + leftbits = 0 |
| 37 | + last_char_was_a_pad = False |
| 38 | + |
| 39 | + for c in ascii: |
| 40 | + c = chr(c) |
| 41 | + if c == PAD: |
| 42 | + if quad_pos > 2 or (quad_pos == 2 and last_char_was_a_pad): |
| 43 | + break # stop on 'xxx=' or on 'xx==' |
| 44 | + last_char_was_a_pad = True |
| 45 | + else: |
| 46 | + n = ord(table_a2b_base64[ord(c)]) |
| 47 | + if n == 0xff: |
| 48 | + continue # ignore strange characters |
| 49 | + # |
| 50 | + # Shift it in on the low end, and see if there's |
| 51 | + # a byte ready for output. |
| 52 | + quad_pos = (quad_pos + 1) & 3 |
| 53 | + leftchar = (leftchar << 6) | n |
| 54 | + leftbits += 6 |
| 55 | + # |
| 56 | + if leftbits >= 8: |
| 57 | + leftbits -= 8 |
| 58 | + res.append((leftchar >> leftbits).to_bytes(1, 'big')) |
| 59 | + leftchar &= ((1 << leftbits) - 1) |
| 60 | + # |
| 61 | + last_char_was_a_pad = False |
| 62 | + else: |
| 63 | + if leftbits != 0: |
| 64 | + raise Exception("Incorrect padding") |
| 65 | + |
| 66 | + return b''.join(res) |
| 67 | + |
| 68 | +# ____________________________________________________________ |
| 69 | + |
| 70 | +table_b2a_base64 = ( |
| 71 | + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/") |
| 72 | + |
| 73 | +def b2a_base64(bin_data): |
| 74 | + "Base64-code line of data." |
| 75 | + |
| 76 | + newlength = (len(bin_data) + 2) // 3 |
| 77 | + newlength = newlength * 4 + 1 |
| 78 | + res = [] |
| 79 | + |
| 80 | + leftchar = 0 |
| 81 | + leftbits = 0 |
| 82 | + for c in bin_data: |
| 83 | + # Shift into our buffer, and output any 6bits ready |
| 84 | + leftchar = (leftchar << 8) | c |
| 85 | + leftbits += 8 |
| 86 | + res.append(table_b2a_base64[(leftchar >> (leftbits-6)) & 0x3f]) |
| 87 | + leftbits -= 6 |
| 88 | + if leftbits >= 6: |
| 89 | + res.append(table_b2a_base64[(leftchar >> (leftbits-6)) & 0x3f]) |
| 90 | + leftbits -= 6 |
| 91 | + # |
| 92 | + if leftbits == 2: |
| 93 | + res.append(table_b2a_base64[(leftchar & 3) << 4]) |
| 94 | + res.append(PAD) |
| 95 | + res.append(PAD) |
| 96 | + elif leftbits == 4: |
| 97 | + res.append(table_b2a_base64[(leftchar & 0xf) << 2]) |
| 98 | + res.append(PAD) |
| 99 | + return ''.join(res).encode('ascii') |
0 commit comments