diff --git a/av98.py b/av98.py index fd5cfdb..7ba1059 100755 --- a/av98.py +++ b/av98.py @@ -297,6 +297,12 @@ class GeminiClient(cmd.Cmd): self.cache = {} self.cache_timestamps = {} + def _input(self, s): + try: + return input(s) + except UnicodeDecodeError: + return "" + def _connect_to_tofu_db(self): db_path = os.path.join(self.config_dir, "tofu.db") @@ -386,7 +392,7 @@ you'll be able to transparently follow links to Gopherspace!""") if self.active_cert_domains and gi.host not in self.active_cert_domains: if self.active_is_transient: print("Permanently delete currently active transient certificate?") - resp = input("Y/N? ") + resp = self.input("Y/N? ") if resp.strip().lower() in ("y", "yes"): print("Destroying certificate.") self._deactivate_client_cert() @@ -395,7 +401,7 @@ you'll be able to transparently follow links to Gopherspace!""") raise UserAbortException() else: print("PRIVACY ALERT: Deactivate client cert before connecting to a new domain?") - resp = input("Y/N? ") + resp = self.input("Y/N? ") if resp.strip().lower() in ("n", "no"): print("Keeping certificate active for {}".format(gi.host)) else: @@ -405,7 +411,7 @@ you'll be able to transparently follow links to Gopherspace!""") # Suggest reactivating previous certs if not self.client_certs["active"] and gi.host in self.client_certs: print("PRIVACY ALERT: Reactivate previously used client cert for {}?".format(gi.host)) - resp = input("Y/N? ") + resp = self.input("Y/N? ") if resp.strip().lower() in ("y", "yes"): self._activate_client_cert(*self.client_certs[gi.host]) else: @@ -444,7 +450,7 @@ you'll be able to transparently follow links to Gopherspace!""") if status == "11": user_input = getpass.getpass("> ") else: - user_input = input("> ") + user_input = self.input("> ") return self._fetch_over_network(gi.query(user_input)) # Redirects @@ -458,13 +464,13 @@ you'll be able to transparently follow links to Gopherspace!""") raise RuntimeError("Refusing to follow more than %d consecutive redirects!" % _MAX_REDIRECTS) # Never follow cross-domain redirects without asking elif new_gi.host != gi.host: - follow = input("Follow cross-domain redirect to %s? (y/n) " % new_gi.url) + follow = self.input("Follow cross-domain redirect to %s? (y/n) " % new_gi.url) # Never follow cross-protocol redirects without asking elif new_gi.scheme != gi.scheme: - follow = input("Follow cross-protocol redirect to %s? (y/n) " % new_gi.url) + follow = self.input("Follow cross-protocol redirect to %s? (y/n) " % new_gi.url) # Don't follow *any* redirect without asking if auto-follow is off elif not self.options["auto_follow_redirects"]: - follow = input("Follow redirect to %s? (y/n) " % new_gi.url) + follow = self.input("Follow redirect to %s? (y/n) " % new_gi.url) # Otherwise, follow away else: follow = "yes" @@ -729,7 +735,7 @@ you'll be able to transparently follow links to Gopherspace!""") print("3. Generate a new persistent certificate.") print("4. Load a previously generated persistent.") print("5. Load certificate from an external file.") - choice = input("> ").strip() + choice = self.input("> ").strip() if choice == "2": self._generate_transient_cert_cert() elif choice == "3": @@ -841,7 +847,7 @@ you'll be able to transparently follow links to Gopherspace!""") print("****************************************") print("Attempt to verify the new certificate fingerprint out-of-band:") print(fingerprint) - choice = input("Accept this new certificate? Y/N ").strip().lower() + choice = self.input("Accept this new certificate? Y/N ").strip().lower() if choice in ("y", "yes"): self.db_cur.execute("""INSERT INTO cert_cache VALUES (?, ?, ?, ?, ?, ?)""", @@ -982,7 +988,7 @@ you'll be able to transparently follow links to Gopherspace!""") format. """ print("Loading client certificate file, in PEM format (blank line to cancel)") - certfile = input("Certfile path: ").strip() + certfile = self.input("Certfile path: ").strip() if not certfile: print("Aborting.") return @@ -991,7 +997,7 @@ you'll be able to transparently follow links to Gopherspace!""") print("Certificate file {} does not exist.".format(certfile)) return print("Loading private key file, in PEM format (blank line to cancel)") - keyfile = input("Keyfile path: ").strip() + keyfile = self.input("Keyfile path: ").strip() if not keyfile: print("Aborting.") return @@ -1020,7 +1026,7 @@ you'll be able to transparently follow links to Gopherspace!""") certdir = os.path.join(self.config_dir, "client_certs") print("What do you want to name this new certificate?") print("Answering `mycert` will create `{0}/mycert.crt` and `{0}/mycert.key`".format(certdir)) - name = input("> ") + name = self.input("> ") if not name.strip(): print("Aborting.") return @@ -1056,7 +1062,7 @@ you'll be able to transparently follow links to Gopherspace!""") for n, cert in enumerate(certs): certdir[str(n+1)] = (cert, os.path.splitext(cert)[0] + ".key") print("{}. {}".format(n+1, os.path.splitext(os.path.basename(cert))[0])) - choice = input("> ").strip() + choice = self.input("> ").strip() if choice in certdir: certfile, keyfile = certdir[choice] self._activate_client_cert(certfile, keyfile) @@ -1171,7 +1177,7 @@ you'll be able to transparently follow links to Gopherspace!""") print("3. Load previously generated certificate.") print("4. Load externally created client certificate from file.") print("Enter blank line to exit certificate manager.") - choice = input("> ").strip() + choice = self.input("> ").strip() if choice == "1": print("Deactivating client certificate.") self._deactivate_client_cert()