commit 5eb2155266cf4d50af23a9c0cd06d5ab05db9553 Author: Damian Johnson atagar@torproject.org Date: Tue Jun 21 20:14:09 2011 -0700
Relay setup wizard role selection
This provides the first prompt of the relay setup wizard which has options for the general role Tor will have. Options include: - Internal Realy - Exit Relay - Bridge - Client - Cancel
Selection is currenty a no-op. Next thing to do are the sub-dialogs these options go to... --- README | 1 + src/cli/__init__.py | 2 +- src/cli/controller.py | 7 +++- src/cli/menu/actions.py | 2 + src/cli/menu/menu.py | 1 + src/cli/wizard.py | 98 +++++++++++++++++++++++++++++++++++++++++++++++ src/settings.cfg | 15 +++++++ src/util/uiTools.py | 11 +++++ 8 files changed, 135 insertions(+), 2 deletions(-)
diff --git a/README b/README index 44fabf1..835b02b 100644 --- a/README +++ b/README @@ -187,6 +187,7 @@ Layout: headerPanel.py - top of all pages, providing general information descriptorPopup.py - displays connection descriptor data popups.py - toolkit providing display popups + wizard.py - provides the relay setup wizard
logPanel.py - (page 1) displays tor, arm, and torctl events configPanel.py - (page 3) editor panel for the tor configuration diff --git a/src/cli/__init__.py b/src/cli/__init__.py index 1564f68..435883d 100644 --- a/src/cli/__init__.py +++ b/src/cli/__init__.py @@ -2,5 +2,5 @@ Panels, popups, and handlers comprising the arm user interface. """
-__all__ = ["configPanel", "controller", "descriptorPopup", "headerPanel", "logPanel", "popups", "torrcPanel"] +__all__ = ["configPanel", "controller", "descriptorPopup", "headerPanel", "logPanel", "popups", "torrcPanel", "wizard"]
diff --git a/src/cli/controller.py b/src/cli/controller.py index e20e023..e771a26 100644 --- a/src/cli/controller.py +++ b/src/cli/controller.py @@ -8,6 +8,7 @@ import curses import threading
import cli.menu.menu +import cli.wizard import cli.popups import cli.headerPanel import cli.logPanel @@ -455,6 +456,7 @@ def startTorMonitor(startTime):
cli.graphing.graphPanel.loadConfig(config) cli.connections.connEntry.loadConfig(config) + cli.wizard.loadConfig(config)
# attempts to fetch the tor pid, warning if unsuccessful (this is needed for # checking its resource usage, among other things) @@ -536,7 +538,8 @@ def drawTorMonitor(stdscr, startTime): # main draw loop overrideKey = None # uses this rather than waiting on user input isUnresponsive = False # flag for heartbeat responsiveness check - + if not torTools.getConn().isAlive(): overrideKey = ord('w') # shows wizard + while not control.isDone(): displayPanels = control.getDisplayPanels() isUnresponsive = heartbeatCheck(isUnresponsive) @@ -593,6 +596,8 @@ def drawTorMonitor(stdscr, startTime): log.log(log.ERR, "Error detected when reloading tor: %s" % sysTools.getFileErrorMsg(exc)) elif key == ord('h') or key == ord('H'): overrideKey = cli.popups.showHelpPopup() + elif key == ord('w') or key == ord('W'): + cli.wizard.showWizard() else: for panelImpl in displayPanels: isKeystrokeConsumed = panelImpl.handleKey(key) diff --git a/src/cli/menu/actions.py b/src/cli/menu/actions.py index c571bd8..3c90b10 100644 --- a/src/cli/menu/actions.py +++ b/src/cli/menu/actions.py @@ -5,6 +5,7 @@ Generates the menu for arm, binding options with their related actions. import functools
import cli.popups +import cli.wizard import cli.controller import cli.menu.item import cli.graphing.graphPanel @@ -53,6 +54,7 @@ def makeActionsMenu(): actionsMenu = cli.menu.item.Submenu("Actions") actionsMenu.add(cli.menu.item.MenuItem("Close Menu", None)) actionsMenu.add(cli.menu.item.MenuItem("New Identity", headerPanel.sendNewnym)) + actionsMenu.add(cli.menu.item.MenuItem("Setup Wizard", cli.wizard.showWizard))
if control.isPaused(): label, arg = "Unpause", False else: label, arg = "Pause", True diff --git a/src/cli/menu/menu.py b/src/cli/menu/menu.py index 1dbbbd0..8302551 100644 --- a/src/cli/menu/menu.py +++ b/src/cli/menu/menu.py @@ -109,6 +109,7 @@ def showMenu():
popup.win.refresh()
+ curses.cbreak() key = control.getScreen().getch() cursor.handleKey(key)
diff --git a/src/cli/wizard.py b/src/cli/wizard.py new file mode 100644 index 0000000..2b7cdf7 --- /dev/null +++ b/src/cli/wizard.py @@ -0,0 +1,98 @@ +""" +Provides user prompts for setting up a new relay. This autogenerates a torrc +that's used by arm to start its tor instance. +""" + +import curses + +import cli.popups +import cli.controller + +from util import enum, uiTools + +# basic configuration types we can run as +RunType = enum.Enum("RELAY", "EXIT", "BRIDGE", "CLIENT") + +# other options provided in the prompts +CANCEL, BACK = "Cancel", "Back" + +CONFIG = {"wizard.role.message": "", + "wizard.role.option.label": {}, + "wizard.role.option.description": {}} + +def loadConfig(config): + config.update(CONFIG) + +def showWizard(): + myRole = promptRunType() + +def promptRunType(): + """ + Provides a prompt for selecting the general role we'd like Tor to run with. + This returns a RunType enumeration for the selection, or None if the dialog + was canceled. + """ + + popup, _, _ = cli.popups.init(23, 58) + if not popup: return + control = cli.controller.getController() + key, selection = 0, 0 + + # constructs (enum, label, [description lines]) tuples for our options + options = [] + + for runType in RunType.values() + [CANCEL]: + label = CONFIG["wizard.role.option.label"].get(runType, "") + descRemainder = CONFIG["wizard.role.option.description"].get(runType, "") + descLines = [] + + while descRemainder: + descLine, descRemainder = uiTools.cropStr(descRemainder, 54, None, endType = None, getRemainder = True) + descLines.append(descLine.strip()) + + options.append((runType, label, descLines)) + + try: + popup.win.box() + curses.cbreak() + format = uiTools.getColor("green") + y, msgRemainder = 1, CONFIG["wizard.role.message"] + + # provides the welcoming message + while msgRemainder: + msg, msgRemainder = uiTools.cropStr(msgRemainder, 54, None, endType = None, getRemainder = True) + popup.addstr(y, 2, msg.strip(), format | curses.A_BOLD) + y += 1 + + while not uiTools.isSelectionKey(key): + offset = 0 + + for i in range(len(options)): + _, label, lines = options[i] + optionFormat = format | curses.A_STANDOUT if i == selection else format + + # Curses has a weird bug where there's a one-pixel alignment + # difference between bold and regular text, so it looks better + # to render the whitespace here as not being bold. + + offset += 1 + popup.addstr(y + offset, 2, label, optionFormat | curses.A_BOLD) + popup.addstr(y + offset, 2 + len(label), " " * (54 - len(label)), optionFormat) + offset += 1 + + for line in lines: + popup.addstr(y + offset, 2, uiTools.padStr(line, 54), optionFormat) + offset += 1 + + popup.win.refresh() + key = control.getScreen().getch() + + if key == curses.KEY_UP: selection = max(0, selection - 1) + elif key == curses.KEY_DOWN: selection = min(len(options) - 1, selection + 1) + elif key == 27: selection, key = -1, curses.KEY_ENTER # esc - cancel + finally: + cli.popups.finalize() + + selectedOption = options[selection][0] + return None if selectedOption == CANCEL else selectedOption + diff --git a/src/settings.cfg b/src/settings.cfg index bced9a4..2ad2784 100644 --- a/src/settings.cfg +++ b/src/settings.cfg @@ -340,6 +340,21 @@ msg.ARM_DEBUG GETINFO traffic/written msg.ARM_DEBUG GETCONF msg.ARM_DEBUG Unable to query process resource usage from ps
+# descriptions used in the relay setup wizard +wizard.role.message Welcome to the Tor network! This will step you through the configuration process for being a part of it. To start with, what role would you like to have? + +wizard.role.option.label Relay => Internal Relay +wizard.role.option.label Exit => Exit Relay +wizard.role.option.label Bridge => Bridge +wizard.role.option.label Client => Client +wizard.role.option.label Cancel => Cancel + +wizard.role.option.description Relay => Provides interconnections with other Tor relays. This is a safe and easy of making the network better. +wizard.role.option.description Exit => Connects between Tor an the outside Internet. This is a vital role, but can lead to abuse complaints. +wizard.role.option.description Bridge => Non-public relay specifically for helping censored users. +wizard.role.option.description Client => Use the network without contributing to it. +wizard.role.option.description Cancel => Close without starting Tor. + # some config options are fetched via special values torrc.map HiddenServiceDir => HiddenServiceOptions torrc.map HiddenServicePort => HiddenServiceOptions diff --git a/src/util/uiTools.py b/src/util/uiTools.py index 40a3087..52885de 100644 --- a/src/util/uiTools.py +++ b/src/util/uiTools.py @@ -282,6 +282,17 @@ def cropStr(msg, size, minWordLen = 4, minCrop = 0, endType = Ending.ELLIPSE, ge if getRemainder: return (returnMsg, remainder) else: return returnMsg
+def padStr(msg, size): + """ + Provides the string padded with whitespace to the given length. + + Arguments: + msg - string to be padded + size - length to be padded to + """ + + return ("%%-%is" % size) % msg + def camelCase(label, divider = "_", joiner = " "): """ Converts the given string to camel case, ie:
tor-commits@lists.torproject.org