[tor-commits] [bridgedb/master] Move base64 re-padding logic into separate function.

isis at torproject.org isis at torproject.org
Sun Jan 12 06:06:34 UTC 2014


commit 2a3c688715d4ac4dd5ad1dae46be14ed65623d5b
Author: Isis Lovecruft <isis at torproject.org>
Date:   Wed Dec 11 13:23:15 2013 +0000

    Move base64 re-padding logic into separate function.
    
    This logic is not specific to parsing networkstatus descriptors, so for now
    I've placed it in parse.parseUnpaddedBase64() ― though it could live somewhere
    else later.
---
 lib/bridgedb/parse/__init__.py      |   38 +++++++++++++++++++++++++++++++++++
 lib/bridgedb/parse/networkstatus.py |   28 ++++++++++----------------
 2 files changed, 49 insertions(+), 17 deletions(-)

diff --git a/lib/bridgedb/parse/__init__.py b/lib/bridgedb/parse/__init__.py
index f4b75d1..0618dae 100644
--- a/lib/bridgedb/parse/__init__.py
+++ b/lib/bridgedb/parse/__init__.py
@@ -26,6 +26,16 @@
    \__ :mod:`bridgedb.parse.versions`
 """
 
+from __future__ import absolute_import
+from __future__ import print_function
+from __future__ import unicode_literals
+
+import binascii
+
+
+class InvalidBase64(ValueError):
+    """Cannot decode base64 value."""
+
 
 def padBase64(b64string):
     """Re-add any stripped equals sign character padding to a b64 string.
@@ -50,3 +60,31 @@ def padBase64(b64string):
         b64string += '=' * addchars
 
     return b64string
+
+def parseUnpaddedBase64(field):
+    """Parse an unpadded, base64-encoded field.
+
+    The **field** will be re-padded, if need be, and then base64 decoded.
+
+    :param str field: Should be some base64-encoded thing, with any trailing
+                      '=' characters removed.
+    :raises: :exc:`InvalidBase64`, if there is an error in either unpadding or
+             decoding **field**.
+    :rtype: str
+    :returns: The base64-decoded **field**.
+    """
+    if field.endswith('='):
+        raise InvalidBase64("Unpadded, base64-encoded networkstatus field "\
+                            "must not end with '=': %r" % field)
+
+    try:
+        paddedField = padBase64(field)  # Add the trailing equals sign back in
+    except ValueError as error:
+        raise InvalidBase64(error)
+
+    debasedField = binascii.a2b_base64(paddedField)
+    if not debasedField:
+        raise InvalidBase64("Base64-encoded networkstatus field %r is invalid!"
+                            % field)
+
+    return debasedField
diff --git a/lib/bridgedb/parse/networkstatus.py b/lib/bridgedb/parse/networkstatus.py
index 7fd9e18..09c9a65 100644
--- a/lib/bridgedb/parse/networkstatus.py
+++ b/lib/bridgedb/parse/networkstatus.py
@@ -32,7 +32,8 @@ import warnings
 from twisted.python.log import showwarning
 
 from bridgedb.parse import addr
-from bridgedb.parse import padBase64
+from bridgedb.parse import parseUnpaddedBase64
+from bridgedb.parse import InvalidBase64
 
 
 class NetworkstatusParsingError(Exception):
@@ -103,19 +104,10 @@ def parseRLine(line):
         nickname, ID = fields[:2]
         isValidRouterNickname(nickname)
 
-        if ID.endswith('='):
-            raise InvalidNetworkstatusRouterIdentity(
-                "Skipping networkstatus parsing for router with nickname "\
-                "'%s':\n  Unpadded, base64-encoded networkstatus router identity "\
-                "string ends with '=': %r" % (nickname, ID))
-        paddedID = padBase64(ID) # Add the trailing equals sign back in
-        debasedID = binascii.a2b_base64(paddedID)
-        if not debasedID:
-            raise InvalidNetworkstatusRouterIdentity(
-                "Skipping networkstatus parsing for router with nickname "\
-                "'%s':\n  Base64-encoding for networkstatus router identity "\
-                "string is invalid!\n  Line: %r" % (nickname, line))
-        ID = debasedID
+        try:
+            ID = parseUnpaddedBase64(ID)
+        except InvalidBase64 as error:
+            raise InvalidNetworkstatusRouterIdentity(error)
 
     except NetworkstatusParsingError as error:
         logging.error(error)
@@ -128,16 +120,18 @@ def parseRLine(line):
         ID = None
     else:
         try:
-            paddedDigest = padBase64(fields[2])
-            descDigest = binascii.b2a_base64(paddedDigest)
+            descDigest = parseUnpaddedBase64(fields[2])
             timestamp = time.mktime(time.strptime(" ".join(fields[3:5]),
                                                   "%Y-%m-%d %H:%M:%S"))
             ORaddr = fields[5]
             ORport = fields[6]
             dirport = fields[7]
-        except (AttributeError, ValueError, IndexError) as error:
+        except InvalidBase64 as error:
             logging.error(error)
             descDigest = None
+        except (AttributeError, ValueError, IndexError) as error:
+            logging.error(error)
+            timestamp = None
     finally:
         return (nickname, ID, descDigest, timestamp, ORaddr, ORport, dirport)
 





More information about the tor-commits mailing list