tor-commits
Threads by month
- ----- 2026 -----
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 1 participants
- 215380 discussions
[torspec/master] Add proposals 321 and 322 for walking-onions-related stuff
by nickm@torproject.org 27 May '20
by nickm@torproject.org 27 May '20
27 May '20
commit 4f8d5a4b24741680c231a99f2f1af9172bf126e5
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Wed May 27 15:12:01 2020 -0400
Add proposals 321 and 322 for walking-onions-related stuff
---
proposals/000-index.txt | 4 +
proposals/321-happy-families.md | 231 ++++++++++++++++++++++++++++++++++++++
proposals/322-dirport-linkspec.md | 41 +++++++
3 files changed, 276 insertions(+)
diff --git a/proposals/000-index.txt b/proposals/000-index.txt
index 3374a26..512f64f 100644
--- a/proposals/000-index.txt
+++ b/proposals/000-index.txt
@@ -241,6 +241,8 @@ Proposals by number:
318 Limit protover values to 0-63 [OPEN]
319 RELAY_FRAGMENT cells [OPEN]
320 Removing TAP usage from v2 onion services [OPEN]
+321 Better performance and usability for the MyFamily option (v2) [OPEN]
+322 Extending link specifiers to include the directory port [OPEN]
Proposals by status:
@@ -287,6 +289,8 @@ Proposals by status:
318 Limit protover values to 0-63
319 RELAY_FRAGMENT cells
320 Removing TAP usage from v2 onion services
+ 321 Better performance and usability for the MyFamily option (v2)
+ 322 Extending link specifiers to include the directory port
ACCEPTED:
188 Bridge Guards and other anti-enumeration defenses
249 Allow CREATE cells with >505 bytes of handshake data
diff --git a/proposals/321-happy-families.md b/proposals/321-happy-families.md
new file mode 100644
index 0000000..288ba66
--- /dev/null
+++ b/proposals/321-happy-families.md
@@ -0,0 +1,231 @@
+```
+Filename: 321-happy-families.md
+Title: Better performance and usability for the MyFamily option (v2)
+Author: Nick Mathewson
+Created: 27 May 2020
+Status: Open
+```
+
+## Problem statement.
+
+The current family mechanism allows well-behaved relays to
+identify that they all belong to the same 'family', and should
+not be used in the same circuits.
+
+Right now, families work by having every family member list every
+other family member in its server descriptor. This winds up using
+O(n^2) space in microdescriptors and server descriptors. (For RAM,
+we can de-duplicate families which sometimes helps.) Adding or
+removing a server from the family requires all the other servers to
+change their torrc settings.
+
+The is growth in size is not just a theoretical problem. Family
+declarations currently make up a little over 55% of the
+microdescriptors in the directory--around 24% after compression.
+The largest family has around 270 members. With Walking Onions, 270
+members times a 160-bit hashed identifier leads to over 5 kilobytes
+per SNIP, which is much greater than we'd want to use.
+
+This is an updated version of proposal 242. It differs by clarifying
+requirements and providing a more detailed migration plan.
+
+## Design overview.
+
+In this design, every family has a master ed25519 "family key". A node
+is in the family iff its server descriptor includes a certificate of its
+ed25519 identity key with the family key. The certificate
+format the one in the tor-certs.txt spec; we would allocate a new
+certificate type for this usage. These certificates would need to
+include the signing key in the appropriate extension.
+
+Note that because server descriptors are signed with the node's
+ed25519 signing key, this creates a bidirectional relationship
+between the two keys, so that nodes can't be put in families without
+their consent.
+
+## Changes to router descriptors
+
+We add a new entry to server descriptors:
+
+ "family-cert" NL
+ "-----BEGIN FAMILY CERT-----" NL
+ cert
+ "-----END FAMILY CERT-----".
+
+This entry contains a base64-encoded certificate as described
+above. It may appear any number of times; authorities MAY reject
+descriptors that include it more than three times.
+
+## Changes to microdescriptors
+
+We add a new entry to microdescriptors: `family-keys`.
+
+This line contains one or more space-separated strings describing
+families to which the node belongs. These strings MUST be sorted in
+lexicographic order. Clients MUST NOT depend on any particular property
+of these strings.
+
+## Changes to voting algorithm
+
+We allocate a new consensus method number for voting on these keys.
+
+When generating microdescriptors using a suitable consensus method,
+the authorities include a "family-keys" line if the underlying
+server descriptor contains any valid family-cert lines. For each
+valid family-cert in the server descriptor, they add a
+base-64-encoded string of that family-cert's signing key.
+
+> See also "deriving family lines from family-keys?" below for an
+> interesting but more difficult extension mechanism that I would
+> not recommend.
+
+## Relay configuration
+
+There are several ways that we could configure relays to let them
+include family certificates in their descriptors.
+
+The easiest would be putting the private family key on each relay,
+so that the relays could generate their own certificates. This is
+easy to configure, but slightly risky: if the private key is
+compromised on any relay, anybody can claim membership in the
+family. That isn't so very bad, however -- all the relays would
+need to do in this event would be to move to a new private family
+key.
+
+A more orthodox method would be to keep the private key somewhere
+offline, and using it to generate a certificate for each relay in
+the family as needed. These certificates should be made with
+long-enough lifetimes, and relays should warn when they are going to
+expire soon.
+
+## Changes to relay behavior
+
+Each relay should track which other relays they have seen using the
+same family-key as itself. When generating a router descriptor,
+each relay should list all of these relays on the legacy 'family'
+line. This keeps the "family" lines up-to-date with "family-keys"
+lines for compliant relays.
+
+Relays should continue listing relays in their family lines if they
+have seen a relay with that identity using the same family-key at
+any time in the last 7 days.
+
+The presence of this line should be configured by a network
+parameter, `derive-family-line`.
+
+Relays whose family lines do not stay at least mostly in sync with
+their family keys should be marked invalid by the authorities.
+
+## Client behavior
+
+Clients should treat node A and node B as belonging to the same
+family if ANY of these is true:
+
+* The client has descriptors for A and B, and A's descriptor lists B
+ in its family line, and B's descriptor lists A in its family line.
+
+* Client A has descriptors for A and B, and they both contain the
+ same entry in their family-keys or family-cert.
+
+## Migration
+
+For some time, existing relays and clients will not support family
+certificates. Because of this, we try to make sure above the
+well-behaved relays will list the same entries in both places.
+
+Once enough clients have migrated to using family
+certificates, authorities SHOULD disable `derive-family-line`.
+
+## Security
+
+Listing families remains as voluntary in this design as in today's
+Tor, though bad-relay hunters can continue to look for families that
+have not adopted a family key.
+
+A hostile relay family could list a "family" line that did not match
+its "family-certs" values. However, the only reason to do so would
+be in order to launch a client partitioning attack, which is
+probably less valuable than the kinds of attacks that they could run
+by simply not listing families at all.
+
+## Appendix: deriving family lines from family-keys?
+
+As an alternative, we might declare that _authorities_ should keep
+family lines in sync with family-certs. Here is a design sketch of
+how we might do that, but I don't think it's actually a good idea,
+since it would require major changes to the data flow of the
+voting system.
+
+In this design, authorties would include a "family-keys" line in
+each router section in their votes corresponding to a relay with any
+family-cert. When generating final microdescriptors using this
+method, the authorities would use these lines to add entries to the
+microdescriptors' family lines:
+
+1. For every relay appearing in a routerstatus's family-keys, the
+ relays calculate a consensus family-keys value by listing including
+ all those keys that are listed by a majority of those voters listing
+ the same router with the same descriptor. (This is the algorithm we
+ use for voting on other values derived from the descriptor.)
+
+2. The authorities then compute a set of "expanded families": one
+ for each family key. Each "expanded family" is a set containing
+ every router in the consensus associated with that key in its consensus
+ family-keys value.
+
+3. The authorities discard all "expanded families" of size 1 or
+ smaller.
+
+4. Every router listed for the "expanded family" has every other
+ router added to the "family" line in its microdescriptor. (The
+ "family" line is then re-canonicalized according to the rules of
+ proposal 298 to remove its )
+
+5. Note that the final microdescriptor consensus will include the
+ digest of the derived microdescriptor in step 4, rather than the
+ digest of the microdescriptor listed in the original votes. (This
+ calculation is deterministic.)
+
+The problem with this approach is that authorities would have to s
+to fetch microdescriptors they do not have in order to replace their
+family lines. Currently, voting never requires an authority to
+fetch a microdescriptor from another authority. If we implement
+vote compression and diffs as in the Walking Onions proposal,
+however, we might suppose that votes could include microdescriptors
+directly.
+
+Still, this is likely more complexity than we want for a transition
+mechanism.
+
+## Appendix: Deriving family-keys from families??
+
+We might also imagine that authorities could infer which families
+exist from the graph of family relationships, and then include
+synthetic "family-keys" entries for routers that belong to the same
+family.
+
+This has two challenges: first, to compute these synthetic family
+keys, the authorities would need to have the same graph of family
+relationships to begin with, which once again would require them to
+include the complete list of families in their votes.
+
+Secondly, finding all the families is equivalent to finding all
+maximal cliques in a graph. This problem is NP-hard in its general
+case. Although polynomial solutions exist for nice well-behaved
+graphs, we'd still need to worry about hostile relays including
+strange family relationships in order to drive the algorithm into
+its exponential cases.
+
+## Appendix: New assigned values
+
+We need a new assigned value for the certificate type used for
+family signing keys.
+
+We need a new consensus method for placing family-keys lines in
+microdescriptors.
+
+## Appendix: New network parameters
+
+* `derive-family-line`: If 1, relays should derive family lines from
+ observed family-keys. If 0, they do not. Min: 0, Max: 1. Default: 1.
+
diff --git a/proposals/322-dirport-linkspec.md b/proposals/322-dirport-linkspec.md
new file mode 100644
index 0000000..5fd42ac
--- /dev/null
+++ b/proposals/322-dirport-linkspec.md
@@ -0,0 +1,41 @@
+```
+Filename: 322-dirport-linkspec.md
+Title: Extending link specifiers to include the directory port
+Author: Nick Mathewson
+Created: 27 May 2020
+Status: Open
+```
+
+## Motivation
+
+Directory ports remain the only way to contact a (non-bridge) Tor
+relay that isn't expressible as a Link Specifier. We haven't
+specified a link specifier of this kind so far, since it isn't a way
+to contact a relay to create a channel.
+
+But authorities still expose directory ports, and encourage relays
+to use them preferentially for uploading and downloading. And with
+Walking Onions, it would be convenient to try to make every kind of
+"address" a link specifier -- we'd like want authorities to be able
+to specify a list of link specifiers that can be used to contact
+them for uploads and downloads.
+
+> It is possible that after revision, Walking Onions won't need a way
+> to specify this information. If so, this proposal should be moved
+> to "Reserve" status as generally unuseful.
+
+## Proposal
+
+We reserve a new link specifier type "dir-url", for use with the
+directory system. This is a variable-length link specifier, containing
+a URL prefix. The only currently supported URL schema is "http://".
+Implementations SHOULD ignore unrecognized schemas. IPv4 and IPv6
+addresses MAY be used directory; hostnames are also allowed.
+Implementations MAY ignore hostnames and only use raw addresses.
+
+The URL prefix includes everything through the string "tor" in the
+directory hierarchy.
+
+A dir-url link specifier SHOULD NOT appear in an EXTEND cell;
+implementations SHOULD reject them if they do appear.
+
1
0
[torspec/master] Merge remote-tracking branch 'tor-github/pr/116'
by nickm@torproject.org 27 May '20
by nickm@torproject.org 27 May '20
27 May '20
commit 73060b223c0bdb9140aa49d686591fa9a201eebc
Merge: 238a098 560c918
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Fri May 22 10:22:57 2020 -0400
Merge remote-tracking branch 'tor-github/pr/116'
tor-spec.txt | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
1
0
commit e608e771fce3e484f7c2419c07892a0119826802
Author: Philipp Winter <phw(a)nymity.ch>
Date: Thu Mar 26 21:16:02 2020 -0700
Make script Python 3-compatible.
...by changing "urllib.quote" to "urllib.parse.quote".
---
doc/sphinx/ext/traclinks.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/doc/sphinx/ext/traclinks.py b/doc/sphinx/ext/traclinks.py
index 732295d..90f596c 100644
--- a/doc/sphinx/ext/traclinks.py
+++ b/doc/sphinx/ext/traclinks.py
@@ -16,6 +16,7 @@ Adapted from recipe here_.
"""
import urllib
+import urllib.parse
from docutils import nodes, utils
def make_trac_link(name, rawtext, text, lineno, inliner,
@@ -33,7 +34,7 @@ def make_trac_link(name, rawtext, text, lineno, inliner,
env = inliner.document.settings.env
base_url = env.config.traclinks_base_url
label = utils.unescape('ticket #' + label)
- ref = base_url + urllib.quote(full_name, safe='')
+ ref = base_url + urllib.parse.quote(full_name, safe='')
node = nodes.reference(rawtext, label, refuri=ref, **options)
return [node],[]
1
0
commit 6ee87fb70e887c06af8f93335a6731d1bc608b9f
Author: Philipp Winter <phw(a)nymity.ch>
Date: Thu Mar 26 20:12:11 2020 -0700
Rename Bridges.py to bridgerings.py.
On file systems that are case insensitive (i.e., Mac OS and Windows),
these filenames are conflicting and cause a lot of development pain.
This fixes <https://bugs.torproject.org/29686>.
---
CHANGELOG | 4 ++++
bridgedb/{Bridges.py => bridgerings.py} | 4 ++--
bridgedb/bridges.py | 4 ++--
bridgedb/distributors/email/distributor.py | 8 ++++----
bridgedb/distributors/https/distributor.py | 11 ++++++-----
bridgedb/distributors/moat/distributor.py | 5 +++--
bridgedb/main.py | 18 +++++++++---------
bridgedb/persistent.py | 11 +++++++----
bridgedb/test/deprecated.py | 4 ++--
bridgedb/test/legacy_Tests.py | 12 ++++++------
bridgedb/test/test_Tests.py | 10 +++++-----
bridgedb/test/test_bridgedb_script.py | 1 +
.../test/{test_Bridges.py => test_bridgerings.py} | 22 +++++++++++-----------
bridgedb/test/test_bridges.py | 12 ++++++------
bridgedb/test/test_https_distributor.py | 4 ++--
bridgedb/test/util.py | 4 ++--
...idgedb.Bridges.rst => bridgedb.bridgerings.rst} | 6 +++---
doc/sphinx/source/bridgedb.rst | 2 +-
doc/sphinx/source/conf.py | 2 +-
19 files changed, 77 insertions(+), 67 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index a92824c..3e179e1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,7 @@
+ * FIXES https://bugs.torproject.org/29686
+ Rename files that contain "Bridges" to "bridgerings", to eliminate
+ headache on file systems that are case insensitive.
+
Changes in version 0.10.0 - 2020-04-01
* FIXES https://bugs.torproject.org/30317
diff --git a/bridgedb/Bridges.py b/bridgedb/bridgerings.py
similarity index 99%
rename from bridgedb/Bridges.py
rename to bridgedb/bridgerings.py
index 2126a7d..5b55610 100644
--- a/bridgedb/Bridges.py
+++ b/bridgedb/bridgerings.py
@@ -199,7 +199,7 @@ class BridgeRing(object):
If the (presumably same) bridge is already at that determined position
in this hashring, replace the old one.
- :type bridge: :class:`~bridgedb.Bridges.Bridge`
+ :type bridge: :class:`~bridgedb.bridges.Bridge`
:param bridge: The bridge to insert into this hashring.
"""
for tp, val, _, subring in self.subrings:
@@ -257,7 +257,7 @@ class BridgeRing(object):
first position after this one which has a bridge assigned to it.
:param int N: The number of bridges to return.
:rtype: list
- :returns: A list of :class:`~bridgedb.Bridges.Bridge`s.
+ :returns: A list of :class:`~bridgedb.bridges.Bridge`s.
"""
assert len(pos) == DIGEST_LEN
if N >= len(self.sortedKeys):
diff --git a/bridgedb/bridges.py b/bridgedb/bridges.py
index 1dc32af..cd01948 100644
--- a/bridgedb/bridges.py
+++ b/bridgedb/bridges.py
@@ -814,12 +814,12 @@ class BridgeBackwardsCompatibility(BridgeBase):
This method is provided for backwards compatibility and should not
be relied upon.
- The old ``bridgedb.Bridges.Bridge.getConfigLine()`` method didn't know
+ The old ``bridgedb.bridges.Bridge.getConfigLine()`` method didn't know
about :class:`~bridgedb.bridgerequest.BridgeRequestBase`s, and so this
modified version is backwards compatible by creating a
:class:`~bridgedb.bridgerequest.BridgeRequestBase` for
:meth:`getBridgeLine`. The default parameters are the same as they
- were in the old ``bridgedb.Bridges.Bridge`` class.
+ were in the old ``bridgedb.bridges.Bridge`` class.
:param bool includeFingerprint: If ``True``, include the
``fingerprint`` of this :class:`Bridge` in the returned bridge
diff --git a/bridgedb/distributors/email/distributor.py b/bridgedb/distributors/email/distributor.py
index fbf1a50..a90e725 100644
--- a/bridgedb/distributors/email/distributor.py
+++ b/bridgedb/distributors/email/distributor.py
@@ -29,8 +29,8 @@ import time
import bridgedb.Storage
-from bridgedb.Bridges import BridgeRing
-from bridgedb.Bridges import FilteredBridgeSplitter
+from bridgedb.bridgerings import BridgeRing
+from bridgedb.bridgerings import FilteredBridgeSplitter
from bridgedb.crypto import getHMAC
from bridgedb.crypto import getHMACFunc
from bridgedb.distribute import Distributor
@@ -67,7 +67,7 @@ class EmailDistributor(Distributor):
"""Object that hands out bridges based on the email address of an incoming
request and the current time period.
- :type hashring: :class:`~bridgedb.Bridges.BridgeRing`
+ :type hashring: :class:`~bridgedb.bridgerings.BridgeRing`
:ivar hashring: A hashring to hold all the bridges we hand out.
"""
@@ -135,7 +135,7 @@ class EmailDistributor(Distributor):
than :api:`time.time`. This should likely only be used for
testing.
:rtype: :any:`list` or ``None``
- :returns: A list of :class:`~bridgedb.bridges.Bridges` for the
+ :returns: A list of :class:`~bridgedb.bridges.Bridge` for the
``bridgeRequest.client``, if allowed. Otherwise, returns ``None``.
"""
if (not bridgeRequest.client) or (bridgeRequest.client == 'default'):
diff --git a/bridgedb/distributors/https/distributor.py b/bridgedb/distributors/https/distributor.py
index f3e2e9b..d01a252 100644
--- a/bridgedb/distributors/https/distributor.py
+++ b/bridgedb/distributors/https/distributor.py
@@ -27,8 +27,8 @@ import logging
import bridgedb.Storage
from bridgedb import proxy
-from bridgedb.Bridges import BridgeRing
-from bridgedb.Bridges import FilteredBridgeSplitter
+from bridgedb.bridgerings import BridgeRing
+from bridgedb.bridgerings import FilteredBridgeSplitter
from bridgedb.crypto import getHMAC
from bridgedb.crypto import getHMACFunc
from bridgedb.distribute import Distributor
@@ -45,7 +45,7 @@ class HTTPSDistributor(Distributor):
:type proxies: :class:`~bridgedb.proxies.ProxySet`
:ivar proxies: All known proxies, which we treat differently. See
:param:`proxies`.
- :type hashring: :class:`bridgedb.Bridges.FilteredBridgeSplitter`
+ :type hashring: :class:`bridgedb.bridgerings.FilteredBridgeSplitter`
:ivar hashring: A hashring that assigns bridges to subrings with fixed
proportions. Used to assign bridges into the subrings of this
distributor.
@@ -69,7 +69,8 @@ class HTTPSDistributor(Distributor):
the extra cluster, and any client requesting bridges from one of
these **proxies** will be distributed bridges from a separate
subhashring that is specific to Tor/proxy users.
- :type answerParameters: :class:`bridgedb.Bridges.BridgeRingParameters`
+ :type answerParameters:
+ :class:`bridgedb.bridgerings.BridgeRingParameters`
:param answerParameters: A mechanism for ensuring that the set of
bridges that this distributor answers a client with fit certain
parameters, i.e. that an answer has "at least two obfsproxy
@@ -293,7 +294,7 @@ class HTTPSDistributor(Distributor):
:param str interval: The time period when we got this request. This
can be any string, so long as it changes with every period.
:rtype: list
- :return: A list of :class:`~bridgedb.Bridges.Bridge`s to include in
+ :return: A list of :class:`~bridgedb.bridges.Bridge`s to include in
the response. See
:meth:`bridgedb.distributors.https.server.WebResourceBridges.getBridgeRequestAnswer`
for an example of how this is used.
diff --git a/bridgedb/distributors/moat/distributor.py b/bridgedb/distributors/moat/distributor.py
index a8f0e1d..c4687eb 100644
--- a/bridgedb/distributors/moat/distributor.py
+++ b/bridgedb/distributors/moat/distributor.py
@@ -30,7 +30,7 @@ class MoatDistributor(HTTPSDistributor):
:type proxies: :class:`~bridgedb.proxies.ProxySet`
:ivar proxies: All known proxies, which we treat differently. See
:param:`proxies`.
- :type hashring: :class:`bridgedb.Bridges.FilteredBridgeSplitter`
+ :type hashring: :class:`bridgedb.bridgerings.FilteredBridgeSplitter`
:ivar hashring: A hashring that assigns bridges to subrings with fixed
proportions. Used to assign bridges into the subrings of this
distributor.
@@ -54,7 +54,8 @@ class MoatDistributor(HTTPSDistributor):
the extra cluster, and any client requesting bridges from one of
these **proxies** will be distributed bridges from a separate
subhashring that is specific to Tor/proxy users.
- :type answerParameters: :class:`bridgedb.Bridges.BridgeRingParameters`
+ :type answerParameters:
+ :class:`bridgedb.bridgerings.BridgeRingParameters`
:param answerParameters: A mechanism for ensuring that the set of
bridges that this distributor answers a client with fit certain
parameters, i.e. that an answer has "at least two obfsproxy
diff --git a/bridgedb/main.py b/bridgedb/main.py
index bc309c5..70001a9 100644
--- a/bridgedb/main.py
+++ b/bridgedb/main.py
@@ -41,7 +41,7 @@ from bridgedb.parse.blacklist import parseBridgeBlacklistFile
import bridgedb.Storage
-from bridgedb import Bridges
+from bridgedb import bridgerings
from bridgedb.Stability import updateBridgeHistory
@@ -59,7 +59,7 @@ def expandBridgeAuthDir(authdir, filename):
def writeAssignments(hashring, filename):
"""Dump bridge distributor assignments to disk.
- :type hashring: A :class:`~bridgedb.Bridges.BridgeSplitter`
+ :type hashring: A :class:`~bridgedb.bridgerings.BridgeSplitter`
:ivar hashring: A class which takes an HMAC key and splits bridges
into their hashring assignments.
:param str filename: The filename to write the assignments to.
@@ -98,7 +98,7 @@ def load(state, hashring, clear=False):
store them into our ``state.hashring`` instance. The ``state`` will be
saved again at the end of this function.
- :type hashring: :class:`~bridgedb.Bridges.BridgeSplitter`
+ :type hashring: :class:`~bridgedb.bridgerings.BridgeSplitter`
:param hashring: A class which provides a mechanism for HMACing
Bridges in order to assign them to hashrings.
:param boolean clear: If True, clear all previous bridges from the
@@ -248,19 +248,19 @@ def createBridgeRings(cfg, proxyList, key):
known open proxies.
:param bytes key: Hashring master key
:rtype: tuple
- :returns: A :class:`~bridgedb.Bridges.BridgeSplitter` hashring, an
+ :returns: A :class:`~bridgedb.bridgerings.BridgeSplitter` hashring, an
:class:`~bridgedb.distributors.https.distributor.HTTPSDistributor` or None, and an
:class:`~bridgedb.distributors.email.distributor.EmailDistributor` or None, and an
:class:`~bridgedb.distributors.moat.distributor.MoatDistributor` or None.
"""
# Create a BridgeSplitter to assign the bridges to the different
# distributors.
- hashring = Bridges.BridgeSplitter(crypto.getHMAC(key, "Hashring-Key"))
+ hashring = bridgerings.BridgeSplitter(crypto.getHMAC(key, "Hashring-Key"))
logging.debug("Created hashring: %r" % hashring)
# Create ring parameters.
- ringParams = Bridges.BridgeRingParameters(needPorts=cfg.FORCE_PORTS,
- needFlags=cfg.FORCE_FLAGS)
+ ringParams = bridgerings.BridgeRingParameters(needPorts=cfg.FORCE_PORTS,
+ needFlags=cfg.FORCE_FLAGS)
emailDistributor = ipDistributor = moatDistributor = None
@@ -297,7 +297,7 @@ def createBridgeRings(cfg, proxyList, key):
# As appropriate, tell the hashring to leave some bridges unallocated.
if cfg.RESERVED_SHARE:
- hashring.addRing(Bridges.UnallocatedHolder(),
+ hashring.addRing(bridgerings.UnallocatedHolder(),
"unallocated",
cfg.RESERVED_SHARE)
@@ -394,7 +394,7 @@ def run(options, reactor=reactor):
:ivar cfg: The current configuration, including any in-memory
settings (i.e. settings whose values were not obtained from the
config file, but were set via a function somewhere)
- :type hashring: A :class:`~bridgedb.Bridges.BridgeSplitter`
+ :type hashring: A :class:`~bridgedb.bridgerings.BridgeSplitter`
:ivar hashring: A class which takes an HMAC key and splits bridges
into their hashring assignments.
"""
diff --git a/bridgedb/persistent.py b/bridgedb/persistent.py
index 3d52ec5..c572758 100644
--- a/bridgedb/persistent.py
+++ b/bridgedb/persistent.py
@@ -23,7 +23,7 @@ except (ImportError, NameError): # pragma: no cover
from twisted.python.reflect import safe_repr
from twisted.spread import jelly
-from bridgedb import Bridges
+from bridgedb import bridgerings
from bridgedb import filters
from bridgedb.distributors.email import distributor as emailDistributor
from bridgedb.distributors.https import distributor as httpsDistributor
@@ -35,7 +35,10 @@ _state = None
#: Types and classes which are allowed to be jellied:
_security = jelly.SecurityOptions()
#_security.allowInstancesOf(ProxySet)
-_security.allowModules(filters, Bridges, emailDistributor, httpsDistributor)
+_security.allowModules(filters,
+ bridgerings,
+ emailDistributor,
+ httpsDistributor)
class MissingState(Exception):
@@ -91,8 +94,8 @@ class State(jelly.Jellyable):
modules which are known to be unjelliable/unpicklable so far are:
- bridgedb.Dist
- - bridgedb.Bridges, and all "splitter" and "ring" classes contained
- within
+ - bridgedb.bridgerings, and all "splitter" and "ring" classes
+ contained within
:property statefile: The filename to retrieve a pickled, jellied
:class:`~bridgedb.persistent.State` instance from. (default:
diff --git a/bridgedb/test/deprecated.py b/bridgedb/test/deprecated.py
index 1a71bf1..0ddd9e3 100644
--- a/bridgedb/test/deprecated.py
+++ b/bridgedb/test/deprecated.py
@@ -282,7 +282,7 @@ class Bridge(object):
class PluggableTransport(object):
"""A PT with reference to the parent bridge on which it is running.
- Deprecated :class:`bridgedb.Bridges.PluggableTransport`, replaced in
+ Deprecated :class:`bridgedb.bridgerings.PluggableTransport`, replaced in
bridgedb-0.2.4, by :class:`bridgedb.bridges.PluggableTransport`.
"""
@@ -392,7 +392,7 @@ class PluggableTransport(object):
Version('bridgedb', 0, 0, 1),
replacement='bridgedb.parse.addr.PortList')
class PortList:
- """Deprecated :class:`bridgedb.Bridges.PortList`, replaced in
+ """Deprecated :class:`bridgedb.bridgerings.PortList`, replaced in
bridgedb-0.1.0, in commit 1f111e5, by
:class:`bridgedb.parse.addr.PortList`.
diff --git a/bridgedb/test/legacy_Tests.py b/bridgedb/test/legacy_Tests.py
index 93b52a7..55a8315 100644
--- a/bridgedb/test/legacy_Tests.py
+++ b/bridgedb/test/legacy_Tests.py
@@ -17,7 +17,7 @@ import warnings
import time
from datetime import datetime
-import bridgedb.Bridges
+import bridgedb.bridgerings
import bridgedb.main
import bridgedb.schedule
import bridgedb.Storage
@@ -62,7 +62,7 @@ def fakeBridge(orport=8080, running=True, stable=True, or_addresses=False,
ip = randomIPv4()
nn = "bridge-%s" % int(ip)
fp = "".join([random.choice("0123456789ABCDEF") for _ in range(40)])
- b = bridgedb.Bridges.Bridge(nn,ip,orport,fingerprint=fp)
+ b = bridgedb.bridges.Bridge(nn,ip,orport,fingerprint=fp)
b.setStatus(running, stable)
oraddrs = []
@@ -72,7 +72,7 @@ def fakeBridge(orport=8080, running=True, stable=True, or_addresses=False,
if transports:
for i in range(0,8):
- b.transports.append(bridgedb.Bridges.PluggableTransport(b,
+ b.transports.append(bridgedb.bridgerings.PluggableTransport(b,
random.choice(["obfs", "obfs2", "pt1"]),
randomIP(), randomPort()))
return b
@@ -82,7 +82,7 @@ def fakeBridge6(orport=8080, running=True, stable=True, or_addresses=False,
ip = randomIPv6()
nn = "bridge-%s" % int(ip)
fp = "".join([random.choice("0123456789ABCDEF") for _ in range(40)])
- b = bridgedb.Bridges.Bridge(nn,ip,orport,fingerprint=fp)
+ b = bridgedb.bridges.Bridge(nn,ip,orport,fingerprint=fp)
b.setStatus(running, stable)
oraddrs = []
@@ -92,7 +92,7 @@ def fakeBridge6(orport=8080, running=True, stable=True, or_addresses=False,
if transports:
for i in range(0,8):
- b.transports.append(bridgedb.Bridges.PluggableTransport(b,
+ b.transports.append(bridgedb.bridgerings.PluggableTransport(b,
random.choice(["obfs", "obfs2", "pt1"]),
randomIP(), randomPort()))
return b
@@ -115,7 +115,7 @@ class SQLStorageTests(unittest.TestCase):
def testBridgeStorage(self):
db = self.db
- B = bridgedb.Bridges.Bridge
+ B = bridgedb.bridges.Bridge
t = time.time()
cur = self.cur
diff --git a/bridgedb/test/test_Tests.py b/bridgedb/test/test_Tests.py
index 41bd4ca..89b7d94 100644
--- a/bridgedb/test/test_Tests.py
+++ b/bridgedb/test/test_Tests.py
@@ -71,23 +71,23 @@ def monkeypatchTests():
:func:`~bridgedb.parse.networkstatus.parseALine`, with the older,
:func:`deprecated one <deprecated.parseORAddressLine>` (the
old function was previously located at
- ``bridgedb.Bridges.parseORAddressLine``).
+ ``bridgedb.bridgerings.parseORAddressLine``).
The second patch replaces the new :class:`~bridgedb.parse.addr.PortList`,
with the :class:`older one <deprecated.PortList>` (which
- was previously located at ``bridgedb.Bridges.PortList``).
+ was previously located at ``bridgedb.bridgerings.PortList``).
The third, forth, and fifth monkeypatches add some module-level attributes
- back into :mod:`bridgedb.Bridges`.
+ back into :mod:`bridgedb.bridgerings`.
:rtype: :api:`~twisted.python.monkey.MonkeyPatcher`
:returns: A :api:`~twisted.python.monkey.MonkeyPatcher`, preloaded with
patches from :mod:`deprecated`.
"""
patcher = monkey.MonkeyPatcher()
- patcher.addPatch(Tests.bridgedb.Bridges, 'PluggableTransport',
+ patcher.addPatch(Tests.bridgedb.bridgerings, 'PluggableTransport',
deprecated.PluggableTransport)
- patcher.addPatch(Tests.bridgedb.Bridges, 'Bridge',
+ patcher.addPatch(Tests.bridgedb.bridgerings, 'Bridge',
deprecated.Bridge)
return patcher
diff --git a/bridgedb/test/test_bridgedb_script.py b/bridgedb/test/test_bridgedb_script.py
index fb8bb3e..76b4001 100644
--- a/bridgedb/test/test_bridgedb_script.py
+++ b/bridgedb/test/test_bridgedb_script.py
@@ -66,6 +66,7 @@ class BridgeDBCliTest(unittest.TestCase):
if not self.pid or not processExists(self.pid):
raise SkipTest("Can't run test: no BridgeDB process running.")
+ self.doSleep()
self.assertTrue(os.path.isfile(self.assignmentsFile))
def test_bridgedb_SIGHUP_assignments_log(self):
diff --git a/bridgedb/test/test_Bridges.py b/bridgedb/test/test_bridgerings.py
similarity index 92%
rename from bridgedb/test/test_Bridges.py
rename to bridgedb/test/test_bridgerings.py
index 96e6a72..cca27d5 100644
--- a/bridgedb/test/test_Bridges.py
+++ b/bridgedb/test/test_bridgerings.py
@@ -9,7 +9,7 @@
# :license: see LICENSE for licensing information
#_____________________________________________________________________________
-"""Unittests for :mod:`bridgedb.Bridges`."""
+"""Unittests for :mod:`bridgedb.bridgerings`."""
from __future__ import print_function
@@ -24,7 +24,7 @@ from twisted.trial import unittest
import bridgedb.Storage
-from bridgedb import Bridges
+from bridgedb import bridgerings
from bridgedb import crypto
from bridgedb.test import util
from bridgedb.distributors.https.distributor import HTTPSDistributor
@@ -33,14 +33,14 @@ from bridgedb.distributors.moat.distributor import MoatDistributor
# For additional logger output for debugging, comment out the following:
logging.disable(50)
# and then uncomment the following line:
-#Bridges.logging.getLogger().setLevel(10)
+#bridgerings.logging.getLogger().setLevel(10)
class BridgeRingTests(unittest.TestCase):
- """Unittests for :class:`bridgedb.Bridges.BridgeRing`."""
+ """Unittests for :class:`bridgedb.bridgerings.BridgeRing`."""
def setUp(self):
- self.ring = Bridges.BridgeRing('fake-hmac-key')
+ self.ring = bridgerings.BridgeRing('fake-hmac-key')
def addRandomBridges(self):
bridges = copy.deepcopy(util.generateFakeBridges())
@@ -99,7 +99,7 @@ class BridgeRingTests(unittest.TestCase):
filtering by distinct subnets.
"""
self.addRandomBridges()
- bridges = self.ring.getBridges(b'a' * Bridges.DIGEST_LEN, N=3, filterBySubnet=True)
+ bridges = self.ring.getBridges(b'a' * bridgerings.DIGEST_LEN, N=3, filterBySubnet=True)
self.assertEqual(len(bridges), 3)
def test_dumpAssignments(self):
@@ -121,7 +121,7 @@ class BridgeRingTests(unittest.TestCase):
class BridgeSplitterTests(unittest.TestCase):
- """Unittests for :class:`bridgedb.Bridges.BridgeSplitter`."""
+ """Unittests for :class:`bridgedb.bridgerings.BridgeSplitter`."""
def setUp(self):
@@ -133,9 +133,9 @@ class BridgeSplitterTests(unittest.TestCase):
bridgedb.Storage.setDBFilename(self.fname)
key = 'fake-hmac-key'
- self.splitter = Bridges.BridgeSplitter(key)
- ringParams = Bridges.BridgeRingParameters(needPorts=[(443, 1)],
- needFlags=[("Stable", 1)])
+ self.splitter = bridgerings.BridgeSplitter(key)
+ ringParams = bridgerings.BridgeRingParameters(needPorts=[(443, 1)],
+ needFlags=[("Stable", 1)])
self.https_distributor = HTTPSDistributor(
4,
crypto.getHMAC(key, "HTTPS-IP-Dist-Key"),
@@ -146,7 +146,7 @@ class BridgeSplitterTests(unittest.TestCase):
crypto.getHMAC(key, "Moat-Dist-Key"),
None,
answerParameters=ringParams)
- self.unallocated_distributor = Bridges.UnallocatedHolder()
+ self.unallocated_distributor = bridgerings.UnallocatedHolder()
self.splitter.addRing(self.https_distributor.hashring, "https", p=10)
self.splitter.addRing(self.moat_distributor.hashring, "moat", p=10)
diff --git a/bridgedb/test/test_bridges.py b/bridgedb/test/test_bridges.py
index fea2d33..fd14e87 100644
--- a/bridgedb/test/test_bridges.py
+++ b/bridgedb/test/test_bridges.py
@@ -22,7 +22,7 @@ import warnings
from twisted.trial import unittest
from bridgedb import bridges
-from bridgedb.Bridges import FilteredBridgeSplitter
+from bridgedb.bridgerings import FilteredBridgeSplitter
from bridgedb.bridgerequest import BridgeRequestBase
from bridgedb.parse import descriptors
from bridgedb.parse.addr import PortList
@@ -143,14 +143,14 @@ XILT4o+SveEQUG72R4bENsKxqV4rRNh1g6CNAbYhAITqrU9B+jImDgrBBW+XWT5K
class BridgeIntegrationTests(unittest.TestCase):
"""Integration tests to ensure that the new :class:`bridgedb.bridges.Bridge`
class has compatible behaviour with the expected behaviour of the old
- :class:`bridgedb.Bridges.Bridge` class.
+ :class:`bridgedb.bridgerings.Bridge` class.
.. data: OldTest (enum)
These tests were refactored from the old tests for
``deprecated.Bridge`, which lived in
- ``lib/bridgedb/test/test_Bridges.py``. For the translations from the old
- tests in ``test_Bridges.BridgeClassTest`` to their new
+ ``lib/bridgedb/test/test_bridgerings.py``. For the translations from the
+ old tests in ``test_bridgerings.BridgeClassTest`` to their new
equivalents here in ``test_bridges.BridgeIntegrationTests``,
which should test for the same things as their old equivalents, see the
following table:
@@ -183,7 +183,7 @@ class BridgeIntegrationTests(unittest.TestCase):
def test_integration_init_0(self):
"""Ensure that we can initialise the new :class:`bridgedb.bridges.Bridge`
- class in the same manner as the old :class:`bridgedb.Bridges.Bridge`
+ class in the same manner as the old :class:`bridgedb.bridgerings.Bridge`
class. This test ensures that initialisation with a fingerprint is
successful.
"""
@@ -193,7 +193,7 @@ class BridgeIntegrationTests(unittest.TestCase):
def test_integration_init_1(self):
"""Ensure that we can initialise the new :class:`bridgedb.bridges.Bridge`
- class in the same manner as the old :class:`bridgedb.Bridges.Bridge`
+ class in the same manner as the old :class:`bridgedb.bridgerings.Bridge`
class. This test ensures that initialisation with a digest of a
bridge's ID key is successful.
"""
diff --git a/bridgedb/test/test_https_distributor.py b/bridgedb/test/test_https_distributor.py
index a96238d..c87fb1d 100644
--- a/bridgedb/test/test_https_distributor.py
+++ b/bridgedb/test/test_https_distributor.py
@@ -20,8 +20,8 @@ import random
from twisted.trial import unittest
from bridgedb.bridges import PluggableTransport
-from bridgedb.Bridges import BridgeRing
-from bridgedb.Bridges import BridgeRingParameters
+from bridgedb.bridgerings import BridgeRing
+from bridgedb.bridgerings import BridgeRingParameters
from bridgedb.filters import byIPv4
from bridgedb.filters import byIPv6
from bridgedb.distributors.https import distributor
diff --git a/bridgedb/test/util.py b/bridgedb/test/util.py
index 43219d5..75acd9a 100644
--- a/bridgedb/test/util.py
+++ b/bridgedb/test/util.py
@@ -174,7 +174,7 @@ randomValidIPString = valid(randomIPString)
_FAKE_BRIDGES = []
def generateFakeBridges(n=500):
- """Generate a set of **n** :class:`~bridgedb.bridges.Bridges` with random
+ """Generate a set of **n** :class:`~bridgedb.bridges.Bridge`s with random
data.
"""
from bridgedb.bridges import Bridge
@@ -305,7 +305,7 @@ class DummyBridge(object):
@implementer(IBridge)
class DummyMaliciousBridge(DummyBridge):
- """A mock :class:`bridgedb.Bridges.Bridge` which only supports a mocked
+ """A mock :class:`bridgedb.bridges.Bridge` which only supports a mocked
``getConfigLine`` method and which maliciously insert an additional fake
bridgeline and some javascript into its PT arguments.
"""
diff --git a/doc/sphinx/source/bridgedb.Bridges.rst b/doc/sphinx/source/bridgedb.bridgerings.rst
similarity index 50%
rename from doc/sphinx/source/bridgedb.Bridges.rst
rename to doc/sphinx/source/bridgedb.bridgerings.rst
index ad4bb6d..a27b42e 100644
--- a/doc/sphinx/source/bridgedb.Bridges.rst
+++ b/doc/sphinx/source/bridgedb.bridgerings.rst
@@ -1,7 +1,7 @@
-bridgedb.Bridges
-----------------
+bridgedb.bridgerings
+--------------------
-.. automodule:: bridgedb.Bridges
+.. automodule:: bridgedb.bridgerings
:members:
:undoc-members:
:private-members:
diff --git a/doc/sphinx/source/bridgedb.rst b/doc/sphinx/source/bridgedb.rst
index 9a8f092..c49002e 100644
--- a/doc/sphinx/source/bridgedb.rst
+++ b/doc/sphinx/source/bridgedb.rst
@@ -7,8 +7,8 @@ Packages & Modules
:toctree:
bridgedb.bridgerequest
+ bridgedb.bridgerings
bridgedb.bridges
- bridgedb.Bridges
bridgedb.captcha
bridgedb.configure
bridgedb.distribute
diff --git a/doc/sphinx/source/conf.py b/doc/sphinx/source/conf.py
index 31ae0b4..850ccbd 100644
--- a/doc/sphinx/source/conf.py
+++ b/doc/sphinx/source/conf.py
@@ -31,7 +31,7 @@ import bridgedb.main
import bridgedb.bridgerequest
import bridgedb.bridges
import bridgedb.captcha
-import bridgedb.Bridges
+import bridgedb.bridgerings
import bridgedb.crypto
import bridgedb.distribute
import bridgedb.distributors
1
0
commit c45439ceb3a8dd43c658607606fb4a7aad57fd67
Merge: 2ccf7ef 64c29be
Author: Philipp Winter <phw(a)nymity.ch>
Date: Wed May 27 10:05:59 2020 -0700
Merge branch 'release-0.10.1'
.gnupg/TESTING.pub | Bin 4622 -> 0 bytes
.gnupg/TESTING.subkeys.sec | Bin 7212 -> 0 bytes
.gnupg/bridgedb-offline-key.pub.asc | 113 -
.gnupg/bridgedb-online-key.pub.asc | 100 -
.gnupg/gpg.conf | 96 -
.gnupg/pubring.gpg | Bin 4634 -> 0 bytes
.gnupg/secring.gpg | Bin 7224 -> 0 bytes
.test.requirements.txt | 4 +-
.travis.requirements.txt | 19 +-
CHANGELOG | 2427 ++++++++++----------
README.rst | 39 +-
bridgedb.conf | 45 -
bridgedb/Storage.py | 71 +-
bridgedb/{Bridges.py => bridgerings.py} | 4 +-
bridgedb/bridges.py | 4 +-
bridgedb/configure.py | 3 +-
bridgedb/crypto.py | 99 +-
bridgedb/distributors/email/autoresponder.py | 51 +-
bridgedb/distributors/email/distributor.py | 18 +-
bridgedb/distributors/email/request.py | 42 +-
bridgedb/distributors/email/server.py | 12 +-
bridgedb/distributors/email/templates.py | 133 +-
bridgedb/distributors/https/distributor.py | 11 +-
bridgedb/distributors/https/request.py | 5 +-
bridgedb/distributors/https/server.py | 13 +-
.../https/templates/assets/css/main.css | 4 +-
bridgedb/distributors/https/templates/base.html | 2 -
bridgedb/distributors/https/templates/bridges.html | 13 +-
.../distributors/https/templates/error-400.html | 30 +
.../distributors/https/templates/error-500.html | 4 +-
bridgedb/distributors/moat/distributor.py | 5 +-
bridgedb/i18n/ar/LC_MESSAGES/bridgedb.po | 367 +--
bridgedb/i18n/az/LC_MESSAGES/bridgedb.po | 356 +--
bridgedb/i18n/be/LC_MESSAGES/bridgedb.po | 361 +--
bridgedb/i18n/bg/LC_MESSAGES/bridgedb.po | 356 +--
bridgedb/i18n/bn/LC_MESSAGES/bridgedb.po | 358 +--
bridgedb/i18n/bs/LC_MESSAGES/bridgedb.po | 399 ++++
bridgedb/i18n/ca/LC_MESSAGES/bridgedb.po | 398 ++--
bridgedb/i18n/cs/LC_MESSAGES/bridgedb.po | 360 +--
bridgedb/i18n/da/LC_MESSAGES/bridgedb.po | 399 ++--
bridgedb/i18n/de/LC_MESSAGES/bridgedb.po | 360 +--
bridgedb/i18n/el/LC_MESSAGES/bridgedb.po | 360 +--
bridgedb/i18n/en_GB/LC_MESSAGES/bridgedb.po | 358 +--
bridgedb/i18n/eo/LC_MESSAGES/bridgedb.po | 359 +--
bridgedb/i18n/es/LC_MESSAGES/bridgedb.po | 360 +--
bridgedb/i18n/es_AR/LC_MESSAGES/bridgedb.po | 359 +--
bridgedb/i18n/es_MX/LC_MESSAGES/bridgedb.po | 356 +--
bridgedb/i18n/et/LC_MESSAGES/bridgedb.po | 359 +--
bridgedb/i18n/eu/LC_MESSAGES/bridgedb.po | 427 +++-
bridgedb/i18n/fa/LC_MESSAGES/bridgedb.po | 373 +--
bridgedb/i18n/fi/LC_MESSAGES/bridgedb.po | 358 +--
bridgedb/i18n/fr/LC_MESSAGES/bridgedb.po | 363 +--
bridgedb/i18n/ga/LC_MESSAGES/bridgedb.po | 358 +--
bridgedb/i18n/gd/LC_MESSAGES/bridgedb.po | 399 ++++
bridgedb/i18n/gl/LC_MESSAGES/bridgedb.po | 356 +--
bridgedb/i18n/gu/LC_MESSAGES/bridgedb.po | 399 ++++
bridgedb/i18n/he/LC_MESSAGES/bridgedb.po | 366 +--
bridgedb/i18n/hi/LC_MESSAGES/bridgedb.po | 356 +--
bridgedb/i18n/hr/LC_MESSAGES/bridgedb.po | 401 ++--
bridgedb/i18n/hu/LC_MESSAGES/bridgedb.po | 361 +--
bridgedb/i18n/hy/LC_MESSAGES/bridgedb.po | 356 +--
bridgedb/i18n/id/LC_MESSAGES/bridgedb.po | 366 +--
bridgedb/i18n/is/LC_MESSAGES/bridgedb.po | 358 +--
bridgedb/i18n/it/LC_MESSAGES/bridgedb.po | 362 +--
bridgedb/i18n/ja/LC_MESSAGES/bridgedb.po | 380 +--
bridgedb/i18n/ka/LC_MESSAGES/bridgedb.po | 357 +--
bridgedb/i18n/kk/LC_MESSAGES/bridgedb.po | 358 +--
bridgedb/i18n/km/LC_MESSAGES/bridgedb.po | 513 +++--
bridgedb/i18n/ko/LC_MESSAGES/bridgedb.po | 361 +--
bridgedb/i18n/lt/LC_MESSAGES/bridgedb.po | 406 ++++
bridgedb/i18n/lv/LC_MESSAGES/bridgedb.po | 356 +--
bridgedb/i18n/mk/LC_MESSAGES/bridgedb.po | 357 +--
bridgedb/i18n/ml/LC_MESSAGES/bridgedb.po | 404 ++++
bridgedb/i18n/mr/LC_MESSAGES/bridgedb.po | 400 ++++
bridgedb/i18n/ms_MY/LC_MESSAGES/bridgedb.po | 356 +--
bridgedb/i18n/nb/LC_MESSAGES/bridgedb.po | 366 +--
bridgedb/i18n/nl/LC_MESSAGES/bridgedb.po | 395 ++--
bridgedb/i18n/nl_BE/LC_MESSAGES/bridgedb.po | 356 +--
bridgedb/i18n/nn/LC_MESSAGES/bridgedb.po | 356 +--
bridgedb/i18n/pa/LC_MESSAGES/bridgedb.po | 402 ++++
bridgedb/i18n/pl/LC_MESSAGES/bridgedb.po | 359 +--
bridgedb/i18n/pt_BR/LC_MESSAGES/bridgedb.po | 363 +--
bridgedb/i18n/pt_PT/LC_MESSAGES/bridgedb.po | 371 +--
bridgedb/i18n/ro/LC_MESSAGES/bridgedb.po | 358 +--
bridgedb/i18n/ru/LC_MESSAGES/bridgedb.po | 393 ++--
bridgedb/i18n/sk/LC_MESSAGES/bridgedb.po | 357 +--
bridgedb/i18n/sl/LC_MESSAGES/bridgedb.po | 356 +--
bridgedb/i18n/sq/LC_MESSAGES/bridgedb.po | 378 +--
bridgedb/i18n/sr/LC_MESSAGES/bridgedb.po | 357 +--
bridgedb/i18n/sv/LC_MESSAGES/bridgedb.po | 370 +--
bridgedb/i18n/sw/LC_MESSAGES/bridgedb.po | 399 ++++
bridgedb/i18n/ta/LC_MESSAGES/bridgedb.po | 357 +--
bridgedb/i18n/templates/bridgedb.pot | 157 +-
bridgedb/i18n/th/LC_MESSAGES/bridgedb.po | 436 +++-
bridgedb/i18n/tr/LC_MESSAGES/bridgedb.po | 361 +--
bridgedb/i18n/uk/LC_MESSAGES/bridgedb.po | 356 +--
bridgedb/i18n/ur/LC_MESSAGES/bridgedb.po | 399 ++++
bridgedb/i18n/uz/LC_MESSAGES/bridgedb.po | 401 ++++
bridgedb/i18n/vi/LC_MESSAGES/bridgedb.po | 389 ++--
bridgedb/i18n/zh_CN/LC_MESSAGES/bridgedb.po | 363 +--
bridgedb/i18n/zh_HK/LC_MESSAGES/bridgedb.po | 356 +--
bridgedb/i18n/zh_TW/LC_MESSAGES/bridgedb.po | 358 +--
bridgedb/main.py | 18 +-
bridgedb/metrics.py | 7 +-
bridgedb/persistent.py | 11 +-
bridgedb/strings.py | 313 +--
bridgedb/test/deprecated.py | 4 +-
bridgedb/test/email_helpers.py | 23 +-
bridgedb/test/legacy_Tests.py | 12 +-
bridgedb/test/test_Tests.py | 10 +-
bridgedb/test/test_bridgedb_script.py | 2 +
.../test/{test_Bridges.py => test_bridgerings.py} | 22 +-
bridgedb/test/test_bridges.py | 12 +-
bridgedb/test/test_crypto.py | 137 --
bridgedb/test/test_email_autoresponder.py | 20 +-
bridgedb/test/test_email_request.py | 74 +-
bridgedb/test/test_email_templates.py | 52 +-
bridgedb/test/test_https_distributor.py | 4 +-
bridgedb/test/test_https_server.py | 20 +-
bridgedb/test/test_main.py | 5 -
bridgedb/test/util.py | 4 +-
doc/sphinx/ext/traclinks.py | 3 +-
...idgedb.Bridges.rst => bridgedb.bridgerings.rst} | 6 +-
doc/sphinx/source/bridgedb.rst | 2 +-
doc/sphinx/source/conf.py | 2 +-
requirements.txt | 13 +-
scripts/nagios-email-check | 201 ++
scripts/setup-tests | 2 +-
128 files changed, 17656 insertions(+), 12991 deletions(-)
1
0
commit 64c29beb19071271593363b957598fbc56ed4a3b
Author: Philipp Winter <phw(a)nymity.ch>
Date: Wed May 27 10:05:16 2020 -0700
Bump version number to 0.10.1.
---
CHANGELOG | 2 ++
1 file changed, 2 insertions(+)
diff --git a/CHANGELOG b/CHANGELOG
index aad33f2..6dfa43c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,5 @@
+Changes in version 0.10.1 - 2020-05-27
+
* FIXES https://bugs.torproject.org/33945
This patch fixes a bug that caused the email autoresponder to fail after
a while.
1
0
27 May '20
commit 1958bbb7e95df0f810e219955595f353933e1302
Author: Philipp Winter <phw(a)nymity.ch>
Date: Tue Mar 31 09:37:37 2020 -0700
Make our email autoresponder more usable.
So far, our autoresponder would only send you bridges if your request
was valid. Unfortunately, it's not very easy to figure out what a
correct request looks like. This patch returns bridges regardless of if
the request was valid or not. We also remove the "help" autoresponse
because there's no longer a need for it, and we simplify BridgeDB's auto
response, hopefully making it less frustrating for users.
This fixes <https://bugs.torproject.org/30941>.
---
CHANGELOG | 6 ++
bridgedb/distributors/email/autoresponder.py | 10 --
bridgedb/distributors/email/distributor.py | 6 +-
bridgedb/distributors/email/request.py | 20 ++--
bridgedb/distributors/email/templates.py | 83 +++++-----------
bridgedb/i18n/templates/bridgedb.pot | 143 +++++++++++----------------
bridgedb/metrics.py | 7 +-
bridgedb/strings.py | 49 ++++-----
bridgedb/test/test_email_autoresponder.py | 5 +-
bridgedb/test/test_email_request.py | 46 ++++-----
bridgedb/test/test_email_templates.py | 31 +-----
11 files changed, 151 insertions(+), 255 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 3e179e1..f85283b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,9 @@
+ * FIXES https://bugs.torproject.org/30941
+ Make our email responder more usable. This patch removes the concept of
+ "valid" email commands and returns bridges (obfs4, for now) no matter
+ what the user sends. BridgeDB still supports email commands in case the
+ user needs a vanilla or IPv6 bridge.
+
* FIXES https://bugs.torproject.org/29686
Rename files that contain "Bridges" to "bridgerings", to eliminate
headache on file systems that are case insensitive.
diff --git a/bridgedb/distributors/email/autoresponder.py b/bridgedb/distributors/email/autoresponder.py
index 3711eae..5e1fcd0 100644
--- a/bridgedb/distributors/email/autoresponder.py
+++ b/bridgedb/distributors/email/autoresponder.py
@@ -55,7 +55,6 @@ from bridgedb import safelog
from bridgedb.distributors.email import dkim
from bridgedb.distributors.email import request
from bridgedb.distributors.email import templates
-from bridgedb.distributors.email.distributor import EmailRequestedHelp
from bridgedb.distributors.email.distributor import EmailRequestedKey
from bridgedb.distributors.email.distributor import TooSoonEmail
from bridgedb.distributors.email.distributor import IgnoreEmail
@@ -98,18 +97,9 @@ def createResponseBody(lines, context, client, lang='en'):
bridgeRequest = request.determineBridgeRequestOptions(lines)
bridgeRequest.client = str(client)
- # The request was invalid, respond with a help email which explains
- # valid email commands:
- if not bridgeRequest.isValid():
- raise EmailRequestedHelp("Email request from '%s' was invalid."
- % str(client))
-
# Otherwise they must have requested bridges:
interval = context.schedule.intervalStart(time.time())
bridges = context.distributor.getBridges(bridgeRequest, interval)
- except EmailRequestedHelp as error:
- logging.info(error)
- return templates.buildWelcomeText(translator, client)
except EmailRequestedKey as error:
logging.info(error)
return templates.buildKeyMessage(translator, client)
diff --git a/bridgedb/distributors/email/distributor.py b/bridgedb/distributors/email/distributor.py
index a90e725..c6ac2fd 100644
--- a/bridgedb/distributors/email/distributor.py
+++ b/bridgedb/distributors/email/distributor.py
@@ -20,7 +20,7 @@ bridgedb.distributors.email.autoresponder
A :class:`~bridgedb.distribute.Distributor` which hands out :class:`bridges
<bridgedb.bridges.Bridge>` to clients via an email interface.
-.. inheritance-diagram:: IgnoreEmail TooSoonEmail EmailRequestedHelp EmailRequestedKey EmailDistributor
+.. inheritance-diagram:: IgnoreEmail TooSoonEmail EmailRequestedKey EmailDistributor
:parts: 1
"""
@@ -55,10 +55,6 @@ class TooSoonEmail(addr.BadEmail):
"""Raised when we got a request from this address too recently."""
-class EmailRequestedHelp(Exception):
- """Raised when a client has emailed requesting help."""
-
-
class EmailRequestedKey(Exception):
"""Raised when an incoming email requested a copy of our GnuPG keys."""
diff --git a/bridgedb/distributors/email/request.py b/bridgedb/distributors/email/request.py
index 83c203d..90576c1 100644
--- a/bridgedb/distributors/email/request.py
+++ b/bridgedb/distributors/email/request.py
@@ -43,8 +43,8 @@ from __future__ import unicode_literals
import logging
import re
+from bridgedb import strings
from bridgedb import bridgerequest
-from bridgedb.distributors.email.distributor import EmailRequestedHelp
from bridgedb.distributors.email.distributor import EmailRequestedKey
@@ -61,7 +61,6 @@ UNBLOCKED_PATTERN = re.compile(UNBLOCKED_REGEXP)
#: Regular expressions that we use to match for email commands. Any command is
#: valid as long as it wasn't quoted, i.e., the line didn't start with a '>'
#: character.
-HELP_LINE = re.compile("([^>].*)?h[ae]lp")
GET_LINE = re.compile("([^>].*)?get")
KEY_LINE = re.compile("([^>].*)?key")
IPV6_LINE = re.compile("([^>].*)?ipv6")
@@ -69,14 +68,13 @@ TRANSPORT_LINE = re.compile("([^>].*)?transport")
UNBLOCKED_LINE = re.compile("([^>].*)?unblocked")
def determineBridgeRequestOptions(lines):
- """Figure out which :mod:`~bridgedb.filters` to apply, or offer help.
+ """Figure out which :mod:`~bridgedb.filters` to apply.
.. note:: If any ``'transport TYPE'`` was requested, or bridges not
blocked in a specific CC (``'unblocked CC'``), then the ``TYPE``
and/or ``CC`` will *always* be stored as a *lowercase* string.
:param list lines: A list of lines from an email, including the headers.
- :raises EmailRequestedHelp: if the client requested help.
:raises EmailRequestedKey: if the client requested our GnuPG key.
:rtype: :class:`EmailBridgeRequest`
:returns: A :class:`~bridgerequest.BridgeRequest` with all of the requested
@@ -92,9 +90,6 @@ def determineBridgeRequestOptions(lines):
if not line: skippedHeaders = True
if not skippedHeaders: continue
- if HELP_LINE.match(line) is not None:
- raise EmailRequestedHelp("Client requested help.")
-
if GET_LINE.match(line) is not None:
request.isValid(True)
logging.debug("Email request was valid.")
@@ -108,6 +103,17 @@ def determineBridgeRequestOptions(lines):
if UNBLOCKED_LINE.match(line) is not None:
request.withoutBlockInCountry(line)
+ # We cannot expect all users to understand BridgeDB's commands, so we will
+ # return bridges even if the request was invalid.
+ if not request.isValid():
+ logging.debug("Email request was invalid.")
+ request.isValid(True)
+ # We will respond with our default transport protocol.
+ if not len(request.transports):
+ # Note that this variable must satisfy TRANSPORT_PATTERN.
+ default_transport = "transport %s" % strings._getDefaultTransport()
+ request.withPluggableTransportType(default_transport)
+
logging.debug("Generating hashring filters for request.")
request.generateFilters()
return request
diff --git a/bridgedb/distributors/email/templates.py b/bridgedb/distributors/email/templates.py
index d618c37..2eb0a31 100644
--- a/bridgedb/distributors/email/templates.py
+++ b/bridgedb/distributors/email/templates.py
@@ -21,9 +21,6 @@ bridgedb.distributors.email.templates
Templates for formatting emails sent out by the email distributor.
"""
-from __future__ import print_function
-from __future__ import unicode_literals
-
import logging
import os
@@ -34,12 +31,17 @@ from bridgedb.distributors.email.distributor import MAX_EMAIL_RATE
def addCommands(template):
- """Add some text telling a client about supported email command, as well as
- which Pluggable Transports are currently available.
+ """Add text telling a client about supported email command.
+
+ :type template: ``gettext.NullTranslation`` or ``gettext.GNUTranslation``
+ :param template: A gettext translations instance, optionally with fallback
+ languages set.
+ :rtype: str
+ :returns: A string explaining email commands.
"""
# Tell them about the various email commands:
cmdlist = []
- cmdlist.append(template.gettext(strings.EMAIL_MISC_TEXT.get(3)))
+ cmdlist.append(template.gettext(strings.EMAIL_MISC_TEXT.get(3)) + "\n")
for cmd, desc in strings.EMAIL_COMMANDS.items():
command = ' '
command += cmd
@@ -48,29 +50,20 @@ def addCommands(template):
command += template.gettext(desc)
cmdlist.append(command)
- commands = "\n".join(cmdlist) + "\n\n"
- # And include the currently supported transports:
- commands += template.gettext(strings.EMAIL_MISC_TEXT.get(5))
- commands += "\n"
- for pt in strings._getSupportedTransports():
- commands += ' ' + pt + "\n"
+ return "\n".join(cmdlist) + "\n\n"
- return commands
+def addGreeting(template):
+ """Our "greeting" clarifies that this is an automated email response.
-def addGreeting(template, clientName=None, welcome=False):
- greeting = ""
- clientName = clientName.decode('utf-8') if isinstance(clientName, bytes) else clientName
-
- if not clientName:
- greeting = template.gettext(strings.EMAIL_MISC_TEXT[7])
- else:
- greeting = template.gettext(strings.EMAIL_MISC_TEXT[6]) % clientName
+ :type template: ``gettext.NullTranslation`` or ``gettext.GNUTranslation``
+ :param template: A gettext translations instance, optionally with fallback
+ languages set.
+ :rtype: str
+ :returns: A string containing our "greeting".
+ """
- if greeting:
- if welcome:
- greeting += u' '
- greeting += template.gettext(strings.EMAIL_MISC_TEXT[4])
- greeting += u'\n\n'
+ greeting = template.gettext(strings.EMAIL_MISC_TEXT[0])
+ greeting += u"\n\n"
return greeting
@@ -79,11 +72,10 @@ def addKeyfile(template):
def addBridgeAnswer(template, answer):
# Give the user their bridges, i.e. the `answer`:
- bridgeLines = template.gettext(strings.EMAIL_MISC_TEXT[0])
- bridgeLines += u"\n\n"
+ bridgeLines = u""
bridgeLines += template.gettext(strings.EMAIL_MISC_TEXT[1])
bridgeLines += u"\n\n"
- bridgeLines += u"%s\n\n" % answer
+ bridgeLines += u"%s\n" % answer
return bridgeLines
@@ -94,40 +86,15 @@ def addHowto(template):
:param template: A gettext translations instance, optionally with fallback
languages set.
"""
- howToTBB = template.gettext(strings.HOWTO_TBB[1]) % strings.EMAIL_SPRINTF["HOWTO_TBB1"]
- howToTBB += u'\n\n'
- howToTBB += strings.EMAIL_REFERENCE_LINKS.get("HOWTO_TBB1")
- howToTBB += strings.EMAIL_REFERENCE_LINKS.get("HOWTO_TBB2")
- howToTBB += strings.EMAIL_REFERENCE_LINKS.get("HOWTO_TBB3")
- howToTBB += u'\n\n'
- return howToTBB
+ return template.gettext(strings.HOWTO_TBB[2])
def buildKeyMessage(template, clientAddress=None):
message = addKeyfile(template)
return message
-def buildWelcomeText(template, clientAddress=None):
- sections = []
- sections.append(addGreeting(template, clientAddress.local, welcome=True))
-
- commands = addCommands(template)
- sections.append(commands)
-
- # Include the same messages as the homepage of the HTTPS distributor:
- welcome = template.gettext(strings.WELCOME[0]) % strings.EMAIL_SPRINTF["WELCOME0"]
- welcome += template.gettext(strings.WELCOME[1])
- welcome += template.gettext(strings.WELCOME[2]) % strings.EMAIL_SPRINTF["WELCOME2"]
- sections.append(welcome)
-
- message = u"\n\n".join(sections)
- # Add the markdown links at the end:
- message += strings.EMAIL_REFERENCE_LINKS.get("WELCOME0")
-
- return message
-
def buildAnswerMessage(template, clientAddress=None, answer=None):
try:
- message = addGreeting(template, clientAddress.local)
+ message = addGreeting(template)
message += addBridgeAnswer(template, answer)
message += addHowto(template)
message += u'\n\n'
@@ -139,11 +106,9 @@ def buildAnswerMessage(template, clientAddress=None, answer=None):
return message
def buildSpamWarning(template, clientAddress=None):
- message = addGreeting(template, clientAddress.local)
+ message = addGreeting(template)
try:
- message += template.gettext(strings.EMAIL_MISC_TEXT[0])
- message += u"\n\n"
message += template.gettext(strings.EMAIL_MISC_TEXT[2]) \
% str(MAX_EMAIL_RATE / 3600)
except Exception as error: # pragma: no cover
diff --git a/bridgedb/i18n/templates/bridgedb.pot b/bridgedb/i18n/templates/bridgedb.pot
index 8fa69c6..65f8ca6 100644
--- a/bridgedb/i18n/templates/bridgedb.pot
+++ b/bridgedb/i18n/templates/bridgedb.pot
@@ -5,11 +5,11 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: bridgedb 0.9.4+8.g5afd164.dirty\n"
+"Project-Id-Version: bridgedb 0.10.0+8.g97621c0\n"
"Report-Msgid-Bugs-To: "
"'https://trac.torproject.org/projects/tor/newticket?component=BridgeDB&keywo…"
"=bridgedb-reported,msgid&cc=isis,sysrqb&owner=isis'\n"
-"POT-Creation-Date: 2020-03-24 10:22-0700\n"
+"POT-Creation-Date: 2020-04-06 13:53-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL(a)li.org>\n"
@@ -66,6 +66,10 @@ msgstr ""
msgid "Changelog"
msgstr ""
+#: bridgedb/distributors/https/templates/base.html:102
+msgid "Public Keys"
+msgstr ""
+
#: bridgedb/distributors/https/templates/bridges.html:35
msgid "Select All"
msgstr ""
@@ -83,7 +87,7 @@ msgstr ""
#. for Italian, you might translate this into "Mama mia!",
#. or for French: "Sacrebleu!". :)
#: bridgedb/distributors/https/templates/bridges.html:67
-#: bridgedb/distributors/https/templates/bridges.html:125
+#: bridgedb/distributors/https/templates/bridges.html:119
msgid "Uh oh, spaghettios!"
msgstr ""
@@ -97,12 +101,12 @@ msgid ""
"your bridge lines onto mobile and other devices."
msgstr ""
-#: bridgedb/distributors/https/templates/bridges.html:131
+#: bridgedb/distributors/https/templates/bridges.html:125
msgid "There currently aren't any bridges available..."
msgstr ""
-#: bridgedb/distributors/https/templates/bridges.html:133
-#: bridgedb/distributors/https/templates/bridges.html:137
+#: bridgedb/distributors/https/templates/bridges.html:127
+#: bridgedb/distributors/https/templates/bridges.html:131
#, python-format
msgid " Perhaps you should try %s going back %s and choosing a different bridge type!"
msgstr ""
@@ -176,15 +180,15 @@ msgstr ""
msgid "%sG%set Bridges"
msgstr ""
-#: bridgedb/strings.py:43
-msgid "[This is an automated message; please do not reply.]"
+#: bridgedb/strings.py:42
+msgid "[This is an automated email.]"
msgstr ""
-#: bridgedb/strings.py:45
+#: bridgedb/strings.py:44
msgid "Here are your bridges:"
msgstr ""
-#: bridgedb/strings.py:47
+#: bridgedb/strings.py:46
#, python-format
msgid ""
"You have exceeded the rate limit. Please slow down! The minimum time between\n"
@@ -192,48 +196,17 @@ msgid ""
"ignored."
msgstr ""
-#: bridgedb/strings.py:50
-msgid "COMMANDs: (combine COMMANDs to specify multiple options simultaneously)"
-msgstr ""
-
-#. TRANSLATORS: Please DO NOT translate the word "BridgeDB".
-#: bridgedb/strings.py:53
-msgid "Welcome to BridgeDB!"
-msgstr ""
-
-#. TRANSLATORS: Please DO NOT translate the words "transport" or "TYPE".
-#: bridgedb/strings.py:55
-msgid "Currently supported transport TYPEs:"
-msgstr ""
-
-#: bridgedb/strings.py:56
-#, python-format
-msgid "Hey, %s!"
-msgstr ""
-
-#: bridgedb/strings.py:57
-msgid "Hello, friend!"
-msgstr ""
-
-#: bridgedb/distributors/https/templates/base.html:102 bridgedb/strings.py:58
-msgid "Public Keys"
-msgstr ""
-
-#. TRANSLATORS: This string will end up saying something like:
-#. "This email was generated with rainbows, unicorns, and sparkles
-#. for alice(a)example.com on Friday, 09 May, 2014 at 18:59:39."
-#: bridgedb/strings.py:62
-#, python-format
+#: bridgedb/strings.py:49
msgid ""
-"This email was generated with rainbows, unicorns, and sparkles\n"
-"for %s on %s at %s."
+"If these bridges are not what you need, reply to this email with one of\n"
+"the following commands in the message body:"
msgstr ""
#. TRANSLATORS: Please DO NOT translate "BridgeDB".
#. TRANSLATORS: Please DO NOT translate "Pluggable Transports".
#. TRANSLATORS: Please DO NOT translate "Tor".
#. TRANSLATORS: Please DO NOT translate "Tor Network".
-#: bridgedb/strings.py:72
+#: bridgedb/strings.py:59
#, python-format
msgid ""
"BridgeDB can provide bridges with several %stypes of Pluggable Transports%s,\n"
@@ -245,7 +218,7 @@ msgid ""
msgstr ""
#. TRANSLATORS: Please DO NOT translate "Pluggable Transports".
-#: bridgedb/strings.py:79
+#: bridgedb/strings.py:66
msgid ""
"Some bridges with IPv6 addresses are also available, though some Pluggable\n"
"Transports aren't IPv6 compatible.\n"
@@ -257,7 +230,7 @@ msgstr ""
#. regular, or unexciting". Like vanilla ice cream. It refers to bridges
#. which do not have Pluggable Transports, and only speak the regular,
#. boring Tor protocol. Translate it as you see fit. Have fun with it.
-#: bridgedb/strings.py:88
+#: bridgedb/strings.py:75
#, python-format
msgid ""
"Additionally, BridgeDB has plenty of plain-ol'-vanilla bridges %s without any"
@@ -268,21 +241,21 @@ msgid ""
"\n"
msgstr ""
-#: bridgedb/strings.py:101 bridgedb/test/test_https.py:356
+#: bridgedb/strings.py:87 bridgedb/test/test_https.py:356
msgid "What are bridges?"
msgstr ""
-#: bridgedb/strings.py:102
+#: bridgedb/strings.py:88
#, python-format
msgid "%s Bridges %s are Tor relays that help you circumvent censorship."
msgstr ""
-#: bridgedb/strings.py:107
+#: bridgedb/strings.py:93
msgid "I need an alternative way of getting bridges!"
msgstr ""
#. TRANSLATORS: Please DO NOT translate "get transport obfs4".
-#: bridgedb/strings.py:109
+#: bridgedb/strings.py:95
#, python-format
msgid ""
"Another way to get bridges is to send an email to %s. Leave the email subject"
@@ -294,32 +267,32 @@ msgid ""
"providers: %s or %s."
msgstr ""
-#: bridgedb/strings.py:117
+#: bridgedb/strings.py:103
msgid "My bridges don't work! I need help!"
msgstr ""
#. TRANSLATORS: Please DO NOT translate "Tor Browser".
#. TRANSLATORS: The two '%s' are substituted with "Tor Browser Manual" and
#. "Support Portal", respectively.
-#: bridgedb/strings.py:121
+#: bridgedb/strings.py:107
#, python-format
msgid "If your Tor Browser cannot connect, please take a look at the %s and our %s."
msgstr ""
-#: bridgedb/strings.py:125
+#: bridgedb/strings.py:111
msgid "Here are your bridge lines:"
msgstr ""
-#: bridgedb/strings.py:126
+#: bridgedb/strings.py:112
msgid "Get Bridges!"
msgstr ""
-#: bridgedb/strings.py:130
+#: bridgedb/strings.py:116
msgid "Bridge distribution mechanisms"
msgstr ""
#. TRANSLATORS: Please DO NOT translate "BridgeDB", "HTTPS", and "Moat".
-#: bridgedb/strings.py:132
+#: bridgedb/strings.py:118
#, python-format
msgid ""
"BridgeDB implements four mechanisms to distribute bridges: \"HTTPS\", "
@@ -333,7 +306,7 @@ msgid ""
"mechanisms is."
msgstr ""
-#: bridgedb/strings.py:138
+#: bridgedb/strings.py:124
#, python-format
msgid ""
"The \"HTTPS\" distribution mechanism hands out bridges over this website. To"
@@ -343,7 +316,7 @@ msgid ""
"solve the subsequent CAPTCHA."
msgstr ""
-#: bridgedb/strings.py:142
+#: bridgedb/strings.py:128
#, python-format
msgid ""
"The \"Moat\" distribution mechanism is part of Tor Browser, allowing users to"
@@ -356,7 +329,7 @@ msgid ""
"bridges."
msgstr ""
-#: bridgedb/strings.py:148
+#: bridgedb/strings.py:134
#, python-format
msgid ""
"Users can request bridges from the \"Email\" distribution mechanism by "
@@ -366,11 +339,11 @@ msgid ""
"email body."
msgstr ""
-#: bridgedb/strings.py:152
+#: bridgedb/strings.py:138
msgid "Reserved"
msgstr ""
-#: bridgedb/strings.py:153
+#: bridgedb/strings.py:139
#, python-format
msgid ""
"BridgeDB maintains a small number of bridges that are not distributed\n"
@@ -384,11 +357,11 @@ msgid ""
"called \"Unallocated\" in %sbridge pool assignment%s files."
msgstr ""
-#: bridgedb/strings.py:160
+#: bridgedb/strings.py:146
msgid "None"
msgstr ""
-#: bridgedb/strings.py:161
+#: bridgedb/strings.py:147
msgid ""
"Bridges whose distribution mechanism is \"None\" are not distributed by "
"BridgeDB.\n"
@@ -399,33 +372,33 @@ msgid ""
"it will then change to the bridge's actual distribution mechanism.\n"
msgstr ""
-#: bridgedb/strings.py:171
+#: bridgedb/strings.py:157
msgid "Please select options for bridge type:"
msgstr ""
-#: bridgedb/strings.py:172
+#: bridgedb/strings.py:158
msgid "Do you need IPv6 addresses?"
msgstr ""
-#: bridgedb/strings.py:173
+#: bridgedb/strings.py:159
#, python-format
msgid "Do you need a %s?"
msgstr ""
-#: bridgedb/strings.py:177
+#: bridgedb/strings.py:163
msgid "Your browser is not displaying images properly."
msgstr ""
-#: bridgedb/strings.py:178
+#: bridgedb/strings.py:164
msgid "Enter the characters from the image above..."
msgstr ""
-#: bridgedb/strings.py:182
+#: bridgedb/strings.py:168
msgid "How to start using your bridges"
msgstr ""
#. TRANSLATORS: Please DO NOT translate "Tor Browser".
-#: bridgedb/strings.py:184
+#: bridgedb/strings.py:170
#, python-format
msgid ""
" First, you need to %sdownload Tor Browser%s. Our Tor Browser User\n"
@@ -434,29 +407,29 @@ msgid ""
" are using Android, %sclick here%s."
msgstr ""
-#: bridgedb/strings.py:192
-msgid "Displays this message."
+#: bridgedb/strings.py:175
+msgid ""
+"Add these bridges to your Tor Browser by opening your browser\n"
+"preferences, clicking on \"Tor\", and then adding them to the \"Provide a\n"
+"bridge\" field."
msgstr ""
-#. TRANSLATORS: Please try to make it clear that "vanilla" here refers to the
-#. same non-Pluggable Transport bridges described above as being
-#. "plain-ol'-vanilla" bridges.
-#: bridgedb/strings.py:196
-msgid "Request vanilla bridges."
+#: bridgedb/strings.py:182
+msgid "(Request unobfuscated Tor bridges.)"
msgstr ""
-#: bridgedb/strings.py:197
-msgid "Request IPv6 bridges."
+#: bridgedb/strings.py:183
+msgid "(Request IPv6 bridges.)"
msgstr ""
-#. TRANSLATORS: Please DO NOT translate the word the word "TYPE".
-#: bridgedb/strings.py:199
-msgid "Request a Pluggable Transport by TYPE."
+#. TRANSLATORS: Please DO NOT translate the word "TYPE".
+#: bridgedb/strings.py:185
+msgid "(Request obfuscated bridges. Replace TYPE with 'obfs4'.)"
msgstr ""
#. TRANSLATORS: Please DO NOT translate "BridgeDB".
#. TRANSLATORS: Please DO NOT translate "GnuPG".
-#: bridgedb/strings.py:202
-msgid "Get a copy of BridgeDB's public GnuPG key."
+#: bridgedb/strings.py:189
+msgid "(Get a copy of BridgeDB's public GnuPG key.)"
msgstr ""
diff --git a/bridgedb/metrics.py b/bridgedb/metrics.py
index bb888d9..48713f0 100644
--- a/bridgedb/metrics.py
+++ b/bridgedb/metrics.py
@@ -22,7 +22,6 @@ import datetime
from bridgedb import geo
from bridgedb.distributors.common.http import getClientIP
from bridgedb.distributors.email import request
-from bridgedb.distributors.email.distributor import EmailRequestedHelp
from twisted.mail.smtp import Address
@@ -387,11 +386,7 @@ class EmailMetrics(Metrics):
emailAddr = emailAddrs[0]
# Get the requested transport protocol.
- try:
- br = request.determineBridgeRequestOptions(
- smtpAutoresp.incoming.lines)
- except EmailRequestedHelp:
- return
+ br = request.determineBridgeRequestOptions( smtpAutoresp.incoming.lines)
bridgeType = "vanilla" if not len(br.transports) else br.transports[0]
# Over email, transports are requested by typing them. Typos happen
diff --git a/bridgedb/strings.py b/bridgedb/strings.py
index b6a7f1f..f3ea849 100644
--- a/bridgedb/strings.py
+++ b/bridgedb/strings.py
@@ -38,30 +38,17 @@ def _(text):
return text
-# TRANSLATORS: Please do not translate the word "TYPE".
EMAIL_MISC_TEXT = {
0: _("""\
-[This is an automated message; please do not reply.]"""),
+[This is an automated email.]"""),
1: _("""\
Here are your bridges:"""),
2: _("""\
You have exceeded the rate limit. Please slow down! The minimum time between
emails is %s hours. All further emails during this time period will be ignored."""),
3: _("""\
-COMMANDs: (combine COMMANDs to specify multiple options simultaneously)"""),
- # TRANSLATORS: Please DO NOT translate the word "BridgeDB".
- 4: _("Welcome to BridgeDB!"),
- # TRANSLATORS: Please DO NOT translate the words "transport" or "TYPE".
- 5: _("Currently supported transport TYPEs:"),
- 6: _("Hey, %s!"),
- 7: _("Hello, friend!"),
- 8: _("Public Keys"),
- # TRANSLATORS: This string will end up saying something like:
- # "This email was generated with rainbows, unicorns, and sparkles
- # for alice(a)example.com on Friday, 09 May, 2014 at 18:59:39."
- 9: _("""\
-This email was generated with rainbows, unicorns, and sparkles
-for %s on %s at %s."""),
+If these bridges are not what you need, reply to this email with one of
+the following commands in the message body:"""),
}
WELCOME = {
@@ -90,11 +77,10 @@ Additionally, BridgeDB has plenty of plain-ol'-vanilla bridges %s without any
Pluggable Transports %s which maybe doesn't sound as cool, but they can still
help to circumvent internet censorship in many cases.\n\n"""),
}
-"""These strings should go on the first "Welcome" email sent by the
-:mod:`~bridgedb.EmailServer`, as well as on the ``index.html`` template used
-by the :mod:`~bridgedb.distributors.https.server`. They are used as an introduction to
-explain what Tor bridges are, what bridges do, and why someone might want to
-use bridges.
+"""These strings should go on the ``options.html`` template used by the
+:mod:`~bridgedb.distributors.https.server`. They are used as an
+introduction to explain what Tor bridges are, what bridges do, and why
+someone might want to use bridges.
"""
FAQ = {
@@ -186,22 +172,21 @@ HOWTO_TBB = {
Manual explains how you can add your bridges to Tor Browser. If you are
using Windows, Linux, or OS X, %sclick here%s to learn more. If you
are using Android, %sclick here%s."""),
+ 2: _("""\
+Add these bridges to your Tor Browser by opening your browser
+preferences, clicking on "Tor", and then adding them to the "Provide a
+bridge" field."""),
}
EMAIL_COMMANDS = {
- "get help": _("Displays this message."),
-# TRANSLATORS: Please try to make it clear that "vanilla" here refers to the
-# same non-Pluggable Transport bridges described above as being
-# "plain-ol'-vanilla" bridges.
- "get bridges": _("Request vanilla bridges."),
- "get ipv6": _("Request IPv6 bridges."),
- # TRANSLATORS: Please DO NOT translate the word the word "TYPE".
- "get transport [TYPE]": _("Request a Pluggable Transport by TYPE."),
+ "get bridges": _("(Request unobfuscated Tor bridges.)"),
+ "get ipv6": _("(Request IPv6 bridges.)"),
+ # TRANSLATORS: Please DO NOT translate the word "TYPE".
+ "get transport TYPE": _("(Request obfuscated bridges. Replace TYPE with "
+ "'obfs4'.)"),
# TRANSLATORS: Please DO NOT translate "BridgeDB".
# TRANSLATORS: Please DO NOT translate "GnuPG".
- "get key": _("Get a copy of BridgeDB's public GnuPG key."),
- #"subscribe": _("Subscribe to receive new bridges once per week"),
- #"unsubscribe": _("Cancel a subscription to new bridges"),
+ "get key": _("(Get a copy of BridgeDB's public GnuPG key.)"),
}
#-----------------------------------------------------------------------------
diff --git a/bridgedb/test/test_email_autoresponder.py b/bridgedb/test/test_email_autoresponder.py
index c8e9624..d5023e0 100644
--- a/bridgedb/test/test_email_autoresponder.py
+++ b/bridgedb/test/test_email_autoresponder.py
@@ -70,11 +70,12 @@ class CreateResponseBodyTests(unittest.TestCase):
self.assertSubstring('-----BEGIN PGP PUBLIC KEY BLOCK-----', ret)
def test_createResponseBody_bridges_invalid(self):
- """An invalid request for 'transport obfs3' should get help text."""
+ """An invalid request for 'transport obfs3' should still return
+ bridges."""
lines = self._getIncomingLines("testing@localhost")
lines[4] = "transport obfs3"
ret = autoresponder.createResponseBody(lines, self.ctx, self.toAddress)
- self.assertSubstring("COMMANDs", ret)
+ self.assertSubstring("Here are your bridges:", ret)
def test_createResponseBody_bridges_obfs3(self):
"""A request for 'get transport obfs3' should receive a response."""
diff --git a/bridgedb/test/test_email_request.py b/bridgedb/test/test_email_request.py
index 0c87d36..e0bb642 100644
--- a/bridgedb/test/test_email_request.py
+++ b/bridgedb/test/test_email_request.py
@@ -17,26 +17,25 @@ import ipaddr
from twisted.trial import unittest
+from bridgedb import strings
from bridgedb.distributors.email import request
class DetermineBridgeRequestOptionsTests(unittest.TestCase):
"""Unittests for :func:`b.e.request.determineBridgeRequestOptions`."""
- def test_determineBridgeRequestOptions_get_help(self):
- """Requesting 'get help' should raise EmailRequestedHelp."""
- lines = ['',
- 'get help']
- self.assertRaises(request.EmailRequestedHelp,
- request.determineBridgeRequestOptions, lines)
-
- def test_determineBridgeRequestOptions_get_halp(self):
- """Requesting 'get halp' should raise EmailRequestedHelp."""
+ def test_determineBridgeRequestOptions_multiline_invalid(self):
lines = ['',
- 'get halp']
- self.assertRaises(request.EmailRequestedHelp,
- request.determineBridgeRequestOptions, lines)
-
+ 'help',
+ 'i need bridges',
+ 'give me your gpgs']
+ reqvest = request.determineBridgeRequestOptions(lines)
+ # We consider every request valid...
+ self.assertEqual(reqvest.isValid(), True)
+ self.assertFalse(reqvest.wantsKey())
+ # ...so by default, we return a bridge.
+ self.assertEqual(len(reqvest.transports), 1)
+
def test_determineBridgeRequestOptions_get_key(self):
"""Requesting 'get key' should raise EmailRequestedKey."""
lines = ['',
@@ -45,14 +44,14 @@ class DetermineBridgeRequestOptionsTests(unittest.TestCase):
request.determineBridgeRequestOptions, lines)
def test_determineBridgeRequestOptions_multiline_invalid(self):
- """Requests without a 'get' anywhere should be considered invalid."""
+ """Requests without a 'get' are incorrect but still valid, and should
+ return bridges."""
lines = ['',
'transport obfs3',
'ipv6 vanilla bridges',
'give me your gpgs']
reqvest = request.determineBridgeRequestOptions(lines)
- # It's invalid because it didn't include a 'get' anywhere.
- self.assertEqual(reqvest.isValid(), False)
+ self.assertEqual(reqvest.isValid(), True)
self.assertFalse(reqvest.wantsKey())
# Though they did request IPv6, technically.
self.assertIs(reqvest.ipVersion, 6)
@@ -61,9 +60,8 @@ class DetermineBridgeRequestOptionsTests(unittest.TestCase):
self.assertEqual(reqvest.transports[0], 'obfs3')
def test_determineBridgeRequestOptions_multiline_valid(self):
- """Though requests with a 'get' are considered valid."""
lines = ['',
- 'get transport obfs3',
+ 'transport obfs3',
'vanilla bridges',
'transport scramblesuit unblocked ca']
reqvest = request.determineBridgeRequestOptions(lines)
@@ -73,6 +71,7 @@ class DetermineBridgeRequestOptionsTests(unittest.TestCase):
# Though they didn't request IPv6, so it should default to IPv4.
self.assertIs(reqvest.ipVersion, 4)
# And they requested two transports.
+ print(reqvest.transports)
self.assertEqual(len(reqvest.transports), 2)
self.assertEqual(reqvest.transports[0], 'obfs3')
self.assertEqual(reqvest.transports[1], 'scramblesuit')
@@ -103,13 +102,16 @@ class DetermineBridgeRequestOptionsTests(unittest.TestCase):
self.assertEqual(reqvest.notBlockedIn[0], 'ca')
def test_determineBridgeRequestOptions_get_transport(self):
- """An invalid request for 'transport obfs3' (missing the 'get')."""
+ """An invalid request for 'transprot obfs3' (typo) should return our
+ default bridge."""
+ default_transport = "obfs4"
+ strings._setDefaultTransport(default_transport)
lines = ['',
- 'transport obfs3']
+ 'transprot obfs3']
reqvest = request.determineBridgeRequestOptions(lines)
self.assertEqual(len(reqvest.transports), 1)
- self.assertEqual(reqvest.transports[0], 'obfs3')
- self.assertEqual(reqvest.isValid(), False)
+ self.assertEqual(reqvest.transports[0], default_transport)
+ self.assertEqual(reqvest.isValid(), True)
def test_determineBridgeRequestOptions_get_ipv6(self):
"""An valid request for 'get ipv6'."""
diff --git a/bridgedb/test/test_email_templates.py b/bridgedb/test/test_email_templates.py
index 1d55dd9..4a5979d 100644
--- a/bridgedb/test/test_email_templates.py
+++ b/bridgedb/test/test_email_templates.py
@@ -36,7 +36,7 @@ class EmailTemplatesTests(unittest.TestCase):
self.offlineFingerprint = '7B78437015E63DF47BB1270ACBD97AA24E8E472E'
def shouldIncludeCommands(self, text):
- self.assertSubstring('COMMANDs', text)
+ self.assertSubstring('commands', text)
def shouldIncludeInstructions(self, text):
self.assertSubstring('Tor Browser', text)
@@ -46,10 +46,10 @@ class EmailTemplatesTests(unittest.TestCase):
self.assertSubstring('Here are your bridges:', text)
def shouldIncludeGreeting(self, text):
- self.assertSubstring('Hey, blackhole!', text)
+ self.assertSubstring('This is an automated email', text)
def shouldIncludeAutomationNotice(self, text):
- self.assertSubstring('automated message', text)
+ self.assertSubstring('automated email', text)
def shouldIncludeKey(self, text):
self.assertSubstring('-----BEGIN PGP PUBLIC KEY BLOCK-----', text)
@@ -59,26 +59,9 @@ class EmailTemplatesTests(unittest.TestCase):
self.shouldIncludeCommands(text)
def test_templates_addGreeting(self):
- text = templates.addGreeting(self.t, self.client.local)
+ text = templates.addGreeting(self.t)
self.shouldIncludeGreeting(text)
- def test_templates_addGreeting_noClient(self):
- text = templates.addGreeting(self.t, None)
- self.assertSubstring('Hello, friend!', text)
-
- def test_templates_addGreeting_withWelcome(self):
- text = templates.addGreeting(self.t, self.client.local, welcome=True)
- self.shouldIncludeGreeting(text)
- self.assertSubstring('Welcome to BridgeDB!', text)
-
- def test_templates_addGreeting_trueClient(self):
- text = templates.addGreeting(self.t, True)
- self.assertSubstring('Hey', text)
-
- def test_templates_addGreeting_23Client(self):
- text = templates.addGreeting(self.t, 23)
- self.assertSubstring('Hey', text)
-
def test_templates_addHowto(self):
text = templates.addHowto(self.t)
self.shouldIncludeInstructions(text)
@@ -97,12 +80,6 @@ class EmailTemplatesTests(unittest.TestCase):
text = templates.buildKeyMessage(self.t, self.client)
self.assertSubstring(self.offlineFingerprint, text)
- def test_templates_buildWelcomeText(self):
- text = templates.buildWelcomeText(self.t, self.client)
- self.shouldIncludeGreeting(text)
- self.assertSubstring('Welcome to BridgeDB!', text)
- self.shouldIncludeCommands(text)
-
def test_templates_buildSpamWarning(self):
text = templates.buildSpamWarning(self.t, self.client)
self.shouldIncludeGreeting(text)
1
0
27 May '20
commit bca64964a255cf959489c7049c66e5eb70b5291c
Merge: 7afbe7e 1958bbb
Author: Philipp Winter <phw(a)nymity.ch>
Date: Mon Apr 6 15:30:12 2020 -0700
Merge branch 'defect/30941' into develop
CHANGELOG | 6 ++
bridgedb/distributors/email/autoresponder.py | 10 --
bridgedb/distributors/email/distributor.py | 6 +-
bridgedb/distributors/email/request.py | 20 ++--
bridgedb/distributors/email/templates.py | 126 +++++------------------
bridgedb/i18n/templates/bridgedb.pot | 143 +++++++++++----------------
bridgedb/metrics.py | 7 +-
bridgedb/strings.py | 49 ++++-----
bridgedb/test/test_email_autoresponder.py | 5 +-
bridgedb/test/test_email_request.py | 46 ++++-----
bridgedb/test/test_email_templates.py | 41 +-------
11 files changed, 151 insertions(+), 308 deletions(-)
1
0
[bridgedb/master] Give BridgeDB more time to start before unit test.
by phw@torproject.org 27 May '20
by phw@torproject.org 27 May '20
27 May '20
commit 8105032e2ab876d1c7d31471b828a0690f2bf6f3
Author: Philipp Winter <phw(a)nymity.ch>
Date: Mon Apr 6 09:41:45 2020 -0700
Give BridgeDB more time to start before unit test.
The renaming of test_Bridges.py to test_bridgerings.py means that
test_bridgedb_script.py is now run earlier (because tests are executed
in alphabetic order), which means less time for BridgeDB to start. This
commit adds an extra sleep to a unit test, so we can be reasonably sure
that BridgeDB is already running when unlinking its assignments file.
---
bridgedb/test/test_bridgedb_script.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/bridgedb/test/test_bridgedb_script.py b/bridgedb/test/test_bridgedb_script.py
index 76b4001..b58e016 100644
--- a/bridgedb/test/test_bridgedb_script.py
+++ b/bridgedb/test/test_bridgedb_script.py
@@ -79,6 +79,7 @@ class BridgeDBCliTest(unittest.TestCase):
if not self.pid or not processExists(self.pid):
raise SkipTest("Can't run test: no BridgeDB process running.")
+ self.doSleep()
os.unlink(self.assignmentsFile)
os.kill(self.pid, signal.SIGHUP)
self.doSleep()
1
0
27 May '20
commit 7afbe7e2866c7628bc5e40b15618105843486c80
Merge: 2ccf7ef 8105032
Author: Philipp Winter <phw(a)nymity.ch>
Date: Mon Apr 6 10:24:31 2020 -0700
Merge branch 'defect/29686' into develop
CHANGELOG | 4 ++++
bridgedb/{Bridges.py => bridgerings.py} | 4 ++--
bridgedb/bridges.py | 4 ++--
bridgedb/distributors/email/distributor.py | 8 ++++----
bridgedb/distributors/https/distributor.py | 11 ++++++-----
bridgedb/distributors/moat/distributor.py | 5 +++--
bridgedb/main.py | 18 +++++++++---------
bridgedb/persistent.py | 11 +++++++----
bridgedb/test/deprecated.py | 4 ++--
bridgedb/test/legacy_Tests.py | 12 ++++++------
bridgedb/test/test_Tests.py | 10 +++++-----
bridgedb/test/test_bridgedb_script.py | 2 ++
.../test/{test_Bridges.py => test_bridgerings.py} | 22 +++++++++++-----------
bridgedb/test/test_bridges.py | 12 ++++++------
bridgedb/test/test_https_distributor.py | 4 ++--
bridgedb/test/util.py | 4 ++--
doc/sphinx/ext/traclinks.py | 3 ++-
...idgedb.Bridges.rst => bridgedb.bridgerings.rst} | 6 +++---
doc/sphinx/source/bridgedb.rst | 2 +-
doc/sphinx/source/conf.py | 2 +-
20 files changed, 80 insertions(+), 68 deletions(-)
1
0