[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] r23693: {arm} Adding a simple panel for config settings (in arm/trunk: . src/interface)
Author: atagar
Date: 2010-10-27 16:41:20 +0000 (Wed, 27 Oct 2010)
New Revision: 23693
Added:
arm/trunk/src/interface/configStatePanel.py
Modified:
arm/trunk/README
arm/trunk/src/interface/__init__.py
arm/trunk/src/interface/configFilePanel.py
arm/trunk/src/interface/controller.py
Log:
Adding a simple panel for config settings
Modified: arm/trunk/README
===================================================================
--- arm/trunk/README 2010-10-27 12:20:16 UTC (rev 23692)
+++ arm/trunk/README 2010-10-27 16:41:20 UTC (rev 23693)
@@ -126,7 +126,8 @@
connPanel.py - (page 2) displays information on tor connections
descriptorPopup.py - (popup) displays connection descriptor data
- confPanel.py - (page 3) displays torrc and performs validation
+ configFilePanel.py - (page 3) displays torrc/armrc and validation
+ configStatePanel.py - editor panel for the tor and arm config states
util/
__init__.py
Modified: arm/trunk/src/interface/__init__.py
===================================================================
--- arm/trunk/src/interface/__init__.py 2010-10-27 12:20:16 UTC (rev 23692)
+++ arm/trunk/src/interface/__init__.py 2010-10-27 16:41:20 UTC (rev 23693)
@@ -2,5 +2,5 @@
Panels, popups, and handlers comprising the arm user interface.
"""
-__all__ = ["confPanel", "connPanel", "controller", "descriptorPopup", "fileDescriptorPopup", "headerPanel", "logPanel"]
+__all__ = ["configFilePanel", "configStatePanel", "connPanel", "controller", "descriptorPopup", "fileDescriptorPopup", "headerPanel", "logPanel"]
Modified: arm/trunk/src/interface/configFilePanel.py
===================================================================
--- arm/trunk/src/interface/configFilePanel.py 2010-10-27 12:20:16 UTC (rev 23692)
+++ arm/trunk/src/interface/configFilePanel.py 2010-10-27 16:41:20 UTC (rev 23693)
@@ -20,7 +20,7 @@
"""
def __init__(self, stdscr, configType, config=None):
- panel.Panel.__init__(self, stdscr, "conf", 0)
+ panel.Panel.__init__(self, stdscr, "confFile", 0)
self._config = dict(DEFAULT_CONFIG)
if config:
Added: arm/trunk/src/interface/configStatePanel.py
===================================================================
--- arm/trunk/src/interface/configStatePanel.py (rev 0)
+++ arm/trunk/src/interface/configStatePanel.py 2010-10-27 16:41:20 UTC (rev 23693)
@@ -0,0 +1,130 @@
+"""
+Panel presenting the configuration state for tor or arm. Options can be edited
+and the resulting configuration files saved.
+"""
+
+import curses
+import threading
+
+from util import conf, panel, torTools, uiTools
+
+DEFAULT_CONFIG = {"torrc.map": {}}
+
+TOR_STATE, ARM_STATE = range(1, 3) # state to be presented
+
+class ConfigEntry():
+ """
+ Configuration option in the panel.
+ """
+
+ def __init__(self, option, value, type, description = ""):
+ self.option = option
+ self.value = value
+ self.type = type
+ self.description = description
+
+class ConfigStatePanel(panel.Panel):
+ """
+ Renders a listing of the tor or arm configuration state, allowing options to
+ be selected and edited.
+ """
+
+ def __init__(self, stdscr, configType, config=None):
+ panel.Panel.__init__(self, stdscr, "confState", 0)
+
+ self._config = dict(DEFAULT_CONFIG)
+ if config: config.update(self._config)
+
+ self.configType = configType
+ self.confContents = []
+ self.scroll = 0
+ self.valsLock = threading.RLock()
+
+ # TODO: this will need to be able to listen for SETCONF events (arg!)
+
+ if self.configType == TOR_STATE:
+ # for all recognized tor config options, provide their current value
+ conn = torTools.getConn()
+ configOptionQuery = conn.getInfo("config/names", "").strip().split("\n")
+
+ for lineNum in range(len(configOptionQuery)):
+ # lines are of the form "<option> <type>", like:
+ # UseEntryGuards Boolean
+ line = configOptionQuery[lineNum]
+ confOption, confType = line.strip().split(" ", 1)
+
+ confValue = None
+ if confOption in self._config["torrc.map"]:
+ confMappings = conn.getOptionMap(self._config["torrc.map"][confOption], {})
+ if confOption in confMappings: confValue = confMappings[confOption]
+ fetchConfOption = self._config["torrc.map"][confOption]
+ else:
+ confValue = ", ".join(conn.getOption(confOption, [], True))
+
+ # provides nicer values for recognized types
+ if not confValue: confValue = "<none>"
+ elif confType == "Boolean" and confValue in ("0", "1"):
+ confValue = "False" if confValue == "0" else "True"
+ elif confType == "DataSize" and confValue.isdigit():
+ confValue = uiTools.getSizeLabel(int(confValue))
+ elif confType == "TimeInterval" and confValue.isdigit():
+ confValue = uiTools.getTimeLabel(int(confValue), isLong = True)
+
+ self.confContents.append(ConfigEntry(confOption, confValue, confType))
+ elif self.configType == ARM_STATE:
+ # loaded via the conf utility
+ armConf = conf.getConfig("arm")
+ for key in armConf.getKeys():
+ self.confContents.append(ConfigEntry(key, ", ".join(armConf.getValue(key, [], True)), ""))
+ #self.confContents.sort() # TODO: make contents sortable?
+
+ def handleKey(self, key):
+ self.valsLock.acquire()
+ if uiTools.isScrollKey(key):
+ pageHeight = self.getPreferredSize()[0] - 1
+ newScroll = uiTools.getScrollPosition(key, self.scroll, pageHeight, len(self.confContents))
+
+ if self.scroll != newScroll:
+ self.scroll = newScroll
+ self.redraw(True)
+
+ def draw(self, subwindow, width, height):
+ self.valsLock.acquire()
+
+ # draws the top label
+ sourceLabel = "Tor" if self.configType == TOR_STATE else "Arm"
+ self.addstr(0, 0, "%s Config:" % sourceLabel, curses.A_STANDOUT)
+
+ # draws left-hand scroll bar if content's longer than the height
+ scrollOffset = 0
+ if len(self.confContents) > height - 1:
+ scrollOffset = 3
+ self.addScrollBar(self.scroll, self.scroll + height - 1, len(self.confContents), 1)
+
+ # determines the width for the columns
+ optionColWidth, valueColWidth, typeColWidth = 0, 0, 0
+
+ for entry in self.confContents:
+ optionColWidth = max(optionColWidth, len(entry.option))
+ valueColWidth = max(valueColWidth, len(entry.value))
+ typeColWidth = max(typeColWidth, len(entry.type))
+
+ # TODO: make the size dynamic between the value and description
+ optionColWidth = min(25, optionColWidth)
+ valueColWidth = min(25, valueColWidth)
+
+ for lineNum in range(self.scroll, len(self.confContents)):
+ entry = self.confContents[lineNum]
+ drawLine = lineNum + 1 - self.scroll
+
+ optionLabel = uiTools.cropStr(entry.option, optionColWidth)
+ valueLabel = uiTools.cropStr(entry.value, valueColWidth)
+
+ self.addstr(drawLine, scrollOffset, optionLabel, curses.A_BOLD | uiTools.getColor("green"))
+ self.addstr(drawLine, scrollOffset + optionColWidth + 1, valueLabel, curses.A_BOLD | uiTools.getColor("green"))
+ self.addstr(drawLine, scrollOffset + optionColWidth + valueColWidth + 2, entry.type, curses.A_BOLD | uiTools.getColor("green"))
+
+ if drawLine >= height: break
+
+ self.valsLock.release()
+
Modified: arm/trunk/src/interface/controller.py
===================================================================
--- arm/trunk/src/interface/controller.py 2010-10-27 12:20:16 UTC (rev 23692)
+++ arm/trunk/src/interface/controller.py 2010-10-27 16:41:20 UTC (rev 23693)
@@ -18,6 +18,7 @@
import graphing.graphPanel
import logPanel
import connPanel
+import configStatePanel
import configFilePanel
import descriptorPopup
import fileDescriptorPopup
@@ -422,7 +423,8 @@
panels["conn"] = connPanel.ConnPanel(stdscr, conn, isBlindMode)
panels["control"] = ControlPanel(stdscr, isBlindMode)
- panels["torrc"] = configFilePanel.ConfigFilePanel(stdscr, configFilePanel.TORRC, config)
+ panels["torrc"] = configStatePanel.ConfigStatePanel(stdscr, configStatePanel.TOR_STATE, config)
+ #panels["torrc"] = configFilePanel.ConfigFilePanel(stdscr, configFilePanel.TORRC, config)
# provides error if pid coulnd't be determined (hopefully shouldn't happen...)
if not torPid: log.log(log.WARN, "Unable to resolve tor pid, abandoning connection listing")
@@ -527,7 +529,8 @@
if panels["graph"].currentDisplay == "bandwidth":
panels["graph"].setHeight(panels["graph"].stats["bandwidth"].getContentHeight())
- panels["torrc"].loadConfig()
+ # TODO: should redraw the configFilePanel
+ #panels["torrc"].loadConfig()
sighupTracker.isReset = False
# gives panels a chance to take advantage of the maximum bounds
@@ -744,11 +747,12 @@
popup.addfstr(2, 2, "<b>page up</b>: scroll up a page")
popup.addfstr(2, 41, "<b>page down</b>: scroll down a page")
- strippingLabel = "on" if panels["torrc"].stripComments else "off"
- popup.addfstr(3, 2, "<b>s</b>: comment stripping (<b>%s</b>)" % strippingLabel)
+ # TODO: reintroduce options for the configFilePanel
+ #strippingLabel = "on" if panels["torrc"].stripComments else "off"
+ #popup.addfstr(3, 2, "<b>s</b>: comment stripping (<b>%s</b>)" % strippingLabel)
- lineNumLabel = "on" if panels["torrc"].showLineNum else "off"
- popup.addfstr(3, 41, "<b>n</b>: line numbering (<b>%s</b>)" % lineNumLabel)
+ #lineNumLabel = "on" if panels["torrc"].showLineNum else "off"
+ #popup.addfstr(3, 41, "<b>n</b>: line numbering (<b>%s</b>)" % lineNumLabel)
popup.addfstr(4, 2, "<b>r</b>: reload torrc")
popup.addfstr(4, 41, "<b>x</b>: reset tor (issue sighup)")
@@ -1406,7 +1410,7 @@
setPauseState(panels, isPaused, page)
finally:
panel.CURSES_LOCK.release()
- elif page == 2 and key == ord('r') or key == ord('R'):
+ elif page == 2 and False and key == ord('r') or key == ord('R'):
# reloads torrc, providing a notice if successful or not
loadedTorrc = torrc.getTorrc()
loadedTorrc.getLock().acquire()