(Steve Dougherty)
2013-06-07: Add initial WoT support to fn-pull. Add initial WoT support to fn-pull. * Refactor WoT module to allow functions for parsing responses. * WoT not currently supported, but LCWoT is. * See https://bugs.freenetproject.org/view.php?id=5729
diff --git a/infocalypse/__init__.py b/infocalypse/__init__.py
--- a/infocalypse/__init__.py
+++ b/infocalypse/__init__.py
@@ -510,6 +510,43 @@ def infocalypse_pull(ui_, repo, **opts):
params['FMSREAD_HASH'] = opts['hash'][0]
params['FMSREAD_ONLYTRUSTED'] = bool(opts['onlytrusted'])
request_uri = get_uri_from_hash(ui_, repo, params, stored_cfg)
+ elif opts['wot']:
+ import wot
+ truster = stored_cfg.get_wot_identity(
+ stored_cfg.get_dir_insert_uri(repo.root))
+ # TODO: Require repo name, not full path - look it up from the XML.
+
+ # Expecting <id stuff>/reponame.R1/edition
+ wot_id, repo_path = opts['wot'].split('/', 1)
+
+ nickname_prefix = ''
+ key_prefix=''
+ # Could be nick@key, nick, @key
+ split = wot_id.split('@')
+ nickname_prefix = split[0]
+
+ if len(split) == 2:
+ key_prefix = split[1]
+
+ attributes = wot.resolve_identity(ui_,
+ truster=truster,
+ nickname_prefix=nickname_prefix,
+ key_prefix=key_prefix)
+ if attributes is None:
+ return
+
+ # Expecting [freenet:]?USK@key/WebOfTrust/edition
+ request_uri = attributes['RequestURI']
+ # See similar note in fn-create: trim off LCWoT URI prefix.
+ # TODO: Semantically meaningful key classes.
+ prefix = "freenet:"
+ if request_uri.startswith(prefix):
+ request_uri = request_uri[len(prefix):]
+
+ request_uri = request_uri.split('/', 1)[0]
+
+ request_uri = request_uri + '/' + repo_path
+
else:
request_uri = opts['uri']
diff --git a/infocalypse/config.py b/infocalypse/config.py
--- a/infocalypse/config.py
+++ b/infocalypse/config.py
@@ -201,6 +201,13 @@ class Config:
"""
self.wot_identities[normalize(for_usk_or_id)] = wot_identity
+ def get_wot_identity(self, for_usk_or_id):
+ """
+ Return the WoT identity associated with the request USK,
+ or the default if none is set.
+ """
+ return self.wot_identities[normalize(for_usk_or_id)]
+
# Hmmm... really nescessary?
def get_dir_insert_uri(self, repo_dir):
""" Return the insert USK for repo_dir or None. """
diff --git a/infocalypse/wot.py b/infocalypse/wot.py
--- a/infocalypse/wot.py
+++ b/infocalypse/wot.py
@@ -51,10 +51,93 @@ def resolve_local_identity(ui, nickname_
ui.warn("No nicknames start with '{0}'.\n".format(nickname_prefix))
return
+ return read_local_identity(response, id_num)
+
+def resolve_identity(ui, truster, nickname_prefix=None, key_prefix=''):
+ """
+ If using LCWoT, either the nickname prefix should be enough to be
+ unambiguous, or failing that enough of the key.
+ If using WoT, partial search is not supported, and the entire key must be
+ specified.
+
+ Returns a dictionary of the nickname, request URI,
+ and identity that matches the given criteria.
+ In the case of an error prints a message and returns None.
+
+ :param ui: Mercurial ui for error messages.
+ :param truster: Check trust list of this local identity.
+ :param nickname_prefix: Partial (prefix) of nickname. Can be whole.
+ :param key_prefix: Partial (prefix) of key. Can be empty.
+ """
+ # TODO: Support different FCP IP / port.
+ node = fcp.FCPNode()
+
+ # Test for GetIdentitiesByPartialNickname support. currently LCWoT-only.
+ # https://github.com/tmarkus/LessCrappyWebOfTrust/blob/master/src/main/java/plugins/WebOfTrust/fcp/GetIdentitiesByPartialNickname.java
+ params = {'Message': 'GetIdentitiesByPartialNickname',
+ 'Truster': truster,
+ 'PartialNickname': nickname_prefix,
+ 'PartialID': key_prefix,
+ 'MaxIdentities': 1, # Match must be unambiguous.
+ 'Context': 'vcs'}
+ response =\
+ node.fcpPluginMessage(async=False,
+ plugin_name="plugins.WebOfTrust.WebOfTrust",
+ plugin_params=params)[0]
+
+ if response['header'] != 'FCPPluginReply' or\
+ 'Replies.Message' not in response:
+ ui.warn('Unexpected reply. Got {0}\n'.format(response))
+ return
+ elif response['Replies.Message'] == 'Identities':
+ return read_identity(response, 0)
+ elif response['Replies.Message'] == 'Error':
+ # The difficulty here is that the message type is Error for both an
+ # unrecognized message type and ambiguous search terms.
+ # TODO: This seems likely to break - the Description seems intended
+ # for human readers and will probably change.
+ if response['Replies.Description'].startswith('Number of matched'):
+ # Supported version of LCWoT - terms ambiguous.
+ ui.warn("'{0}@{1}' is ambiguous.".format(nickname_prefix,
+ key_prefix))
+ return
+ elif response['Replies.Description'].startswith('Unknown message') or\
+ response['Replies.Description'].startswith('Could not match'):
+ # Not supported; check for exact identity.
+ ui.warn('Searching by partial nickname/key not supported.')
+
+ # Attempt to search failed - check for exact key. Here key_prefix must be
+ # a complete key for the lookup to succeed.
+ params = {'Message': 'GetIdentity',
+ 'Truster': truster,
+ 'Identity': key_prefix}
+ response =\
+ node.fcpPluginMessage(async=False,
+ plugin_name="plugins.WebOfTrust.WebOfTrust",
+ plugin_params=params)[0]
+
+ # There should be only one result.
+ # Depends on https://bugs.freenetproject.org/view.php?id=5729
+ print read_identity(response, 0)
+
+def read_local_identity(message, id_num):
+ """
+ Reads an FCP response from a WoT plugin describing a local identity and
+ returns a dictionary of Nickname, InsertURI, RequestURI, and Identity.
+ """
+ result = read_identity(message, id_num)
+ result['InsertURI'] = message['Replies.InsertURI{0}'.format(id_num)]
+ return result
+
+def read_identity(message, id_num):
+ """
+ Reads an FCP response from a WoT plugin describing an identity and
+ returns a dictionary of Nickname, RequestURI, and Identity.
+ """
# Return properties for the selected identity. (by number)
result = {}
- for item in [ 'Nickname', 'InsertURI','RequestURI', 'Identity' ]:
- result[item] = response['Replies.{0}{1}'.format(item, id_num)]
+ for item in [ 'Nickname', 'RequestURI', 'Identity' ]:
+ result[item] = message['Replies.{0}{1}'.format(item, id_num)]
# LCWoT also puts these things as properties, which would be nicer to
# depend on and would allow just returning all properties for the identity.