File: tor_tools.py

package info (click to toggle)
python-stem 1.2.2-1.1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 4,568 kB
  • ctags: 2,036
  • sloc: python: 20,108; makefile: 127; sh: 3
file content (126 lines) | stat: -rw-r--r-- 3,537 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# Copyright 2012-2014, Damian Johnson and The Tor Project
# See LICENSE for licensing information

"""
Miscellaneous utility functions for working with tor.

.. versionadded:: 1.2.0

**Module Overview:**

::

  is_valid_fingerprint - checks if a string is a valid tor relay fingerprint
  is_valid_nickname - checks if a string is a valid tor relay nickname
  is_valid_circuit_id - checks if a string is a valid tor circuit id
  is_valid_stream_id - checks if a string is a valid tor stream id
  is_valid_connection_id - checks if a string is a valid tor connection id
  is_hex_digits - checks if a string is only made up of hex digits
"""

import re

# The control-spec defines the following as...
#
#   Fingerprint = "$" 40*HEXDIG
#   NicknameChar = "a"-"z" / "A"-"Z" / "0" - "9"
#   Nickname = 1*19 NicknameChar
#
#   CircuitID = 1*16 IDChar
#   IDChar = ALPHA / DIGIT
#
# HEXDIG is defined in RFC 5234 as being uppercase and used in RFC 5987 as
# case insensitive. Tor doesn't define this in the spec so flipping a coin
# and going with case insensitive.

HEX_DIGIT = '[0-9a-fA-F]'
FINGERPRINT_PATTERN = re.compile('^%s{40}$' % HEX_DIGIT)
NICKNAME_PATTERN = re.compile('^[a-zA-Z0-9]{1,19}$')
CIRC_ID_PATTERN = re.compile('^[a-zA-Z0-9]{1,16}$')


def is_valid_fingerprint(entry, check_prefix = False):
  """
  Checks if a string is a properly formatted relay fingerprint. This checks for
  a '$' prefix if check_prefix is true, otherwise this only validates the hex
  digits.

  :param str entry: string to be checked
  :param bool check_prefix: checks for a '$' prefix

  :returns: **True** if the string could be a relay fingerprint, **False** otherwise
  """

  if not isinstance(entry, (str, unicode)):
    return False
  elif check_prefix:
    if not entry or entry[0] != '$':
      return False

    entry = entry[1:]

  return bool(FINGERPRINT_PATTERN.match(entry))


def is_valid_nickname(entry):
  """
  Checks if a string is a valid format for being a nickname.

  :param str entry: string to be checked

  :returns: **True** if the string could be a nickname, **False** otherwise
  """

  if not isinstance(entry, (str, unicode)):
    return False

  return bool(NICKNAME_PATTERN.match(entry))


def is_valid_circuit_id(entry):
  """
  Checks if a string is a valid format for being a circuit identifier.

  :returns: **True** if the string could be a circuit id, **False** otherwise
  """

  if not isinstance(entry, (str, unicode)):
    return False

  return bool(CIRC_ID_PATTERN.match(entry))


def is_valid_stream_id(entry):
  """
  Checks if a string is a valid format for being a stream identifier.
  Currently, this is just an alias to :func:`~stem.util.tor_tools.is_valid_circuit_id`.

  :returns: **True** if the string could be a stream id, **False** otherwise
  """

  return is_valid_circuit_id(entry)


def is_valid_connection_id(entry):
  """
  Checks if a string is a valid format for being a connection identifier.
  Currently, this is just an alias to :func:`~stem.util.tor_tools.is_valid_circuit_id`.

  :returns: **True** if the string could be a connection id, **False** otherwise
  """

  return is_valid_circuit_id(entry)


def is_hex_digits(entry, count):
  """
  Checks if a string is the given number of hex digits. Digits represented by
  letters are case insensitive.

  :param str entry: string to be checked
  :param int count: number of hex digits to be checked for

  :returns: **True** if the string matches this number
  """

  return bool(re.match('^%s{%i}$' % (HEX_DIGIT, count), entry))