From e2e2206159610fabffdc2f2d112fa93abc4940bf Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Sat, 14 Feb 2015 17:48:38 -0800 Subject: [PATCH] use completing-input for wormhole code read, not sys.argv --- bin/receive_text.py | 5 +-- bin/send_text.py | 6 ++-- src/wormhole/codes.py | 68 ++++++++++++++++++++++++++++++++++++++-- src/wormhole/wordlist.py | 11 +++++-- 4 files changed, 78 insertions(+), 12 deletions(-) diff --git a/bin/receive_text.py b/bin/receive_text.py index a374602..0e5d9b9 100644 --- a/bin/receive_text.py +++ b/bin/receive_text.py @@ -1,12 +1,13 @@ from __future__ import print_function -import time, sys, json +import time, json from wormhole.transcribe import Receiver +from wormhole.codes import input_code_with_completion APPID = "lothar.com/wormhole/text-xfer" # we're receiving +code = input_code_with_completion("Enter receive-text wormhole code: ", []) start = time.time() -code = sys.argv[1] data = json.dumps({"message": "ok"}).encode("utf-8") r = Receiver(APPID, data, code) them_bytes = r.get_data() diff --git a/bin/send_text.py b/bin/send_text.py index 034c051..2d99d8d 100644 --- a/bin/send_text.py +++ b/bin/send_text.py @@ -10,10 +10,8 @@ data = json.dumps({"message": message, }).encode("utf-8") i = Initiator(APPID, data) code = i.get_code() -print("Wormhole code is '%s'" % code) -print("On the other computer, please run:") -print("") -print(" wormhole-receive-text %s" % code) +print("On the other computer, please run: receive_text") +print("Wormhole code is: %s" % code) print("") them_bytes = i.get_data() them_d = json.loads(them_bytes.decode("utf-8")) diff --git a/src/wormhole/codes.py b/src/wormhole/codes.py index d6420d6..c2b5baa 100644 --- a/src/wormhole/codes.py +++ b/src/wormhole/codes.py @@ -1,11 +1,73 @@ +from __future__ import print_function import os -from .wordlist import byte_to_even_word, byte_to_odd_word +from .wordlist import (byte_to_even_word, byte_to_odd_word, + even_words_lowercase, odd_words_lowercase) def make_code(channel_id): - even_word = byte_to_even_word[os.urandom(1)] odd_word = byte_to_odd_word[os.urandom(1)] - return "%d-%s-%s" % (channel_id, even_word, odd_word) + even_word = byte_to_even_word[os.urandom(1)] + return "%d-%s-%s" % (channel_id, odd_word.lower(), even_word.lower()) def extract_channel_id(code): channel_id = int(code.split("-")[0]) return channel_id + +import readline +#import sys + +class CodeInputter: + def __init__(self, channel_ids): + self.channel_ids = channel_ids + self.last_text = None # memoize for a speedup + self.last_matches = None + + def wrap_completer(self, text, state): + try: + return self.completer(text, state) + except Exception as e: + # completer exceptions are normally silently discarded, which + # makes debugging challenging + print("completer exception: %s" % e) + raise e + + def completer(self, text, state): + #print("completer:", text, state, file=sys.stderr) + pieces = text.split("-") + last = pieces[-1].lower() + if text == self.last_text: + matches = self.last_matches + #print(" old matches", len(matches), file=sys.stderr) + else: + if len(pieces) < 2: + matches = [str(channel_id) for channel_id in self.channel_ids + if str(channel_id).startswith(last)] + else: + if len(pieces) % 2 == 0: + words = odd_words_lowercase + else: + words = even_words_lowercase + so_far = "-".join(pieces[:-1]) + "-" + matches = sorted([so_far+word for word in words + if word.startswith(last)]) + self.last_text = text + self.last_matches = matches + #print(" new matches:", matches, file=sys.stderr) + if state >= len(matches): + return None + match = matches[state] + if len(pieces) < 3: + match += "-" + return match + + +def input_code_with_completion(prompt, channel_ids): + c = CodeInputter(channel_ids) + readline.parse_and_bind("tab: complete") + readline.set_completer(c.wrap_completer) + readline.set_completer_delims("") + code = raw_input(prompt) + return code + +if __name__ == "__main__": + code = input_code_with_completion("Enter wormhole code: ", []) + print("code is:", code) diff --git a/src/wormhole/wordlist.py b/src/wormhole/wordlist.py index 5fb2fe2..049d126 100644 --- a/src/wormhole/wordlist.py +++ b/src/wormhole/wordlist.py @@ -146,8 +146,13 @@ byte_to_even_word = dict([(unhexlify(k), both_words[0]) byte_to_odd_word = dict([(unhexlify(k), both_words[1]) for k,both_words in raw_words.items()]) -lowercase_word_to_byte_and_evenodd = l = {} +even_words_lowercase, odd_words_lowercase = set(), set() +even_words_lowercase_to_byte, odd_words_lowercase_to_byte = dict(), dict() for k,both_words in raw_words.items(): even_word, odd_word = both_words - l[even_word.lower()] = (unhexlify(k), 0) - l[odd_word.lower()] = (unhexlify(k), 1) + + even_words_lowercase.add(even_word.lower()) + even_words_lowercase_to_byte[even_word.lower()] = unhexlify(k) + + odd_words_lowercase.add(odd_word.lower()) + odd_words_lowercase_to_byte[odd_word.lower()] = unhexlify(k)