Parse bridge blocking info from SQL database.
[tor-bridgedb.git] / bridgedb / parse / __init__.py
blob0f3f20da554c9d151c2549f329f2f6a0f04fd3e0
1 # -*- coding: utf-8 -*-
3 # This file is part of BridgeDB, a Tor bridge distribution system.
5 # :authors: Isis Lovecruft 0xA3ADB67A2CDB8B35 <isis@torproject.org>
6 # please also see AUTHORS file
7 # :copyright: (c) 2013 Isis Lovecruft
8 # (c) 2007-2013, The Tor Project, Inc.
9 # (c) 2007-2013, all entities within the AUTHORS file
10 # :license: 3-clause BSD, see included LICENSE for information
12 '''Package containing modules for parsing data.
14 .. py:module:: bridgedb.parse
15 :synopsis: Package containing modules for parsing data.
16 '''
18 from __future__ import absolute_import
19 from __future__ import print_function
20 from __future__ import unicode_literals
22 import binascii
25 class InvalidBase64(ValueError):
26 """Raised if parsing or decoding cannot continue due to invalid base64."""
29 def padBase64(b64string):
30 """Re-add any stripped equals sign character padding to a b64 string.
32 :param string b64string: A base64-encoded string which might have had its
33 trailing equals sign (``=``) padding removed.
34 :raises ValueError: if there was any error while manipulating the string.
35 :returns: A properly-padded (according to the base64 spec: :rfc:`4648`)
36 string.
37 """
38 addchars = 0
39 try:
40 b64string = b64string.strip()
41 remainder = len(b64string) % 4
42 if 2 <= remainder <= 3:
43 addchars = 4 - remainder
44 except AttributeError as error:
45 raise ValueError(error)
46 else:
47 if not addchars:
48 raise ValueError("Invalid base64-encoded string: %r" % b64string)
49 b64string += '=' * addchars
51 return b64string
53 def parseUnpaddedBase64(field):
54 """Parse an unpadded, base64-encoded field.
56 The **field** will be re-padded, if need be, and then base64 decoded.
58 :param str field: Should be some base64-encoded thing, with any trailing
59 ``=``-characters removed.
60 :raises InvalidBase64: if there is an error in either unpadding or decoding
61 **field**.
62 :rtype: str
63 :returns: The base64-decoded **field**.
64 """
65 if field.endswith('='):
66 raise InvalidBase64("Unpadded, base64-encoded networkstatus field "\
67 "must not end with '=': %r" % field)
69 try:
70 paddedField = padBase64(field) # Add the trailing equals sign back in
71 except ValueError as error:
72 raise InvalidBase64(error)
74 debasedField = binascii.a2b_base64(paddedField)
75 if not debasedField:
76 raise InvalidBase64("Base64-encoded networkstatus field %r is invalid!"
77 % field)
79 return debasedField