[tor-commits] [arm/release] Dropping deprecated conn panel from the codebase

atagar at torproject.org atagar at torproject.org
Sun Jul 17 06:08:16 UTC 2011


commit 8dc1fcaa32e2aef8dfd5b018709844b4c582f388
Author: Damian Johnson <atagar at torproject.org>
Date:   Tue Apr 26 09:50:14 2011 -0700

    Dropping deprecated conn panel from the codebase
    
    Now that we have feature parity between the new and old connection panels we
    can drop the old version. This change removes it, and all the confusing
    controller hacks in place to allow us to have either or both panels be visible.
---
 armrc.sample                     |    6 -
 src/interface/connPanel.py       |  997 --------------------------------------
 src/interface/controller.py      |  421 ++---------------
 src/interface/descriptorPopup.py |   20 +-
 4 files changed, 48 insertions(+), 1396 deletions(-)

diff --git a/armrc.sample b/armrc.sample
index 4cda197..58fe5c2 100644
--- a/armrc.sample
+++ b/armrc.sample
@@ -157,10 +157,6 @@ features.graph.bw.accounting.isTimeLong false
 
 # Parameters for connection display
 # ---------------------------------
-# oldPanel
-#   includes the old connection panel in the interface
-# newPanel
-#   includes the new connection panel in the interface
 # listingType
 #   the primary category of information shown by default, options including:
 #   0 -> IP Address / Port              1 -> Hostname
@@ -187,8 +183,6 @@ features.graph.bw.accounting.isTimeLong false
 # showColumn.*
 #   toggles the visability of the connection table columns
 
-features.connection.oldPanel false
-features.connection.newPanel true
 features.connection.listingType 0
 features.connection.order 0, 2, 1
 features.connection.refreshRate 5
diff --git a/src/interface/connPanel.py b/src/interface/connPanel.py
deleted file mode 100644
index e4d4be6..0000000
--- a/src/interface/connPanel.py
+++ /dev/null
@@ -1,997 +0,0 @@
-#!/usr/bin/env python
-# connPanel.py -- Lists network connections used by tor.
-# Released under the GPL v3 (http://www.gnu.org/licenses/gpl.html)
-
-import time
-import socket
-import curses
-from threading import RLock
-from TorCtl import TorCtl
-
-from util import log, connections, hostnames, panel, torTools, uiTools
-
-# Scrubs private data from any connection that might belong to client or exit
-# traffic. This is a little overly conservative, hiding anything that isn't
-# identified as a relay and meets the following criteria:
-# - Connection is inbound and relay's either a bridge (BridgeRelay is set) or 
-#   guard (making it a probable client connection)
-# - Outbound connection permitted by the exit policy (probable exit connection)
-# 
-# Note that relay etiquette says these are bad things to look at (ie, DON'T 
-# CHANGE THIS UNLESS YOU HAVE A DAMN GOOD REASON!)
-SCRUB_PRIVATE_DATA = True
-
-# directory servers (IP, port) for tor version 0.2.1.24
-# this comes from the dirservers array in src/or/config.c
-DIR_SERVERS = [("86.59.21.38", "80"),         # tor26
-               ("128.31.0.39", "9031"),       # moria1
-               ("216.224.124.114", "9030"),   # ides
-               ("80.190.246.100", "8180"),    # gabelmoo
-               ("194.109.206.212", "80"),     # dizum
-               ("193.23.244.244", "80"),      # dannenberg
-               ("208.83.223.34", "443"),      # urras
-               ("82.94.251.203", "80")]       # Tonga
-
-# enums for listing types
-LIST_IP, LIST_HOSTNAME, LIST_FINGERPRINT, LIST_NICKNAME = range(4)
-LIST_LABEL = {LIST_IP: "IP Address", LIST_HOSTNAME: "Hostname", LIST_FINGERPRINT: "Fingerprint", LIST_NICKNAME: "Nickname"}
-
-# attributes for connection types
-TYPE_COLORS = {"inbound": "green", "outbound": "blue", "client": "cyan", "directory": "magenta", "control": "red", "family": "magenta", "localhost": "yellow"}
-TYPE_WEIGHTS = {"inbound": 0, "outbound": 1, "client": 2, "directory": 3, "control": 4, "family": 5, "localhost": 6} # defines ordering
-
-# enums for indexes of ConnPanel 'connections' fields
-CONN_TYPE, CONN_L_IP, CONN_L_PORT, CONN_F_IP, CONN_F_PORT, CONN_COUNTRY, CONN_TIME, CONN_PRIVATE = range(8)
-
-# labels associated to 'connectionCount' 
-CONN_COUNT_LABELS = ["inbound", "outbound", "client", "directory", "control"]
-
-# enums for sorting types (note: ordering corresponds to SORT_TYPES for easy lookup)
-# TODO: add ORD_BANDWIDTH -> (ORD_BANDWIDTH, "Bandwidth", lambda x, y: ???)
-ORD_TYPE, ORD_FOREIGN_LISTING, ORD_SRC_LISTING, ORD_DST_LISTING, ORD_COUNTRY, ORD_FOREIGN_PORT, ORD_SRC_PORT, ORD_DST_PORT, ORD_TIME = range(9)
-SORT_TYPES = [(ORD_TYPE, "Connection Type",
-                lambda x, y: TYPE_WEIGHTS[x[CONN_TYPE]] - TYPE_WEIGHTS[y[CONN_TYPE]]),
-              (ORD_FOREIGN_LISTING, "Listing (Foreign)", None),
-              (ORD_SRC_LISTING, "Listing (Source)", None),
-              (ORD_DST_LISTING, "Listing (Dest.)", None),
-              (ORD_COUNTRY, "Country Code",
-                lambda x, y: cmp(x[CONN_COUNTRY], y[CONN_COUNTRY])),
-              (ORD_FOREIGN_PORT, "Port (Foreign)",
-                lambda x, y: int(x[CONN_F_PORT]) - int(y[CONN_F_PORT])),
-              (ORD_SRC_PORT, "Port (Source)",
-                lambda x, y: int(x[CONN_F_PORT] if x[CONN_TYPE] == "inbound" else x[CONN_L_PORT]) - int(y[CONN_F_PORT] if y[CONN_TYPE] == "inbound" else y[CONN_L_PORT])),
-              (ORD_DST_PORT, "Port (Dest.)",
-                lambda x, y: int(x[CONN_L_PORT] if x[CONN_TYPE] == "inbound" else x[CONN_F_PORT]) - int(y[CONN_L_PORT] if y[CONN_TYPE] == "inbound" else y[CONN_F_PORT])),
-              (ORD_TIME, "Connection Time",
-                lambda x, y: cmp(-x[CONN_TIME], -y[CONN_TIME]))]
-
-# provides bi-directional mapping of sorts with their associated labels
-def getSortLabel(sortType, withColor = False):
-  """
-  Provides label associated with a type of sorting. Throws ValueEror if no such
-  sort exists. If adding color formatting this wraps with the following mappings:
-  Connection Type     red
-  Listing *           blue
-  Port *              green
-  Bandwidth           cyan
-  Country Code        yellow
-  """
-  
-  for (type, label, func) in SORT_TYPES:
-    if sortType == type:
-      color = None
-      
-      if withColor:
-        if label == "Connection Type": color = "red"
-        elif label.startswith("Listing"): color = "blue"
-        elif label.startswith("Port"): color = "green"
-        elif label == "Bandwidth": color = "cyan"
-        elif label == "Country Code": color = "yellow"
-        elif label == "Connection Time": color = "magenta"
-      
-      #if color: return "<%s>%s</%s>" % (color, label, color)
-      if color: return (label, color)
-      else: return label
-  
-  raise ValueError(sortType)
-
-def getSortType(sortLabel):
-  """
-  Provides sort type associated with a given label. Throws ValueEror if label
-  isn't recognized.
-  """
-  
-  for (type, label, func) in SORT_TYPES:
-    if sortLabel == label: return type
-  raise ValueError(sortLabel)
-
-def ipAddressIsPrivate(ipAddr):
-  """
-  Provides true if the IP address belongs on the local network or belongs to
-  loopback, false otherwise. These include:
-  Private ranges: 10.*, 172.16.* - 172.31.*, 192.168.*
-  Loopback: 127.*
-  
-  Arguments:
-    ipAddr - IP address to be checked
-  """
-  
-  # TODO: being lazy right now and just declaring all of 172.* as private
-  return ipAddr.startswith("10.") or ipAddr.startswith("192.168.") or ipAddr.startswith("172.") or ipAddr.startswith("127.")
-
-class ConnPanel(TorCtl.PostEventListener, panel.Panel):
-  """
-  Lists tor related connection data.
-  """
-  
-  def __init__(self, stdscr, conn, isDisabled):
-    TorCtl.PostEventListener.__init__(self)
-    panel.Panel.__init__(self, stdscr, "conn", 0)
-    self.scroll = 0
-    self.conn = conn                  # tor connection for querrying country codes
-    self.listingType = LIST_IP        # information used in listing entries
-    self.allowDNS = False             # permits hostname resolutions if true
-    self.showLabel = True             # shows top label if true, hides otherwise
-    self.showingDetails = False       # augments display to accomidate details window if true
-    self.lastUpdate = -1              # time last stats was retrived
-    self.localhostEntry = None        # special connection - tuple with (entry for this node, fingerprint)
-    self.sortOrdering = [ORD_TYPE, ORD_FOREIGN_LISTING, ORD_FOREIGN_PORT]
-    self.fingerprintLookupCache = {}                              # cache of (ip, port) -> fingerprint
-    self.nicknameLookupCache = {}                                 # cache of (ip, port) -> nickname
-    self.fingerprintMappings = _getFingerprintMappings(self.conn) # mappings of ip -> [(port, fingerprint, nickname), ...]
-    self.providedGeoipWarning = False
-    self.orconnStatusCache = []           # cache for 'orconn-status' calls
-    self.orconnStatusCacheValid = False   # indicates if cache has been invalidated
-    self.clientConnectionCache = None     # listing of nicknames for our client connections
-    self.clientConnectionLock = RLock()   # lock for clientConnectionCache
-    self.isDisabled = isDisabled          # prevent panel from updating entirely
-    self.lastConnResults = None           # used to check if connection results have changed
-    
-    self.isCursorEnabled = True
-    self.cursorSelection = None
-    self.cursorLoc = 0              # fallback cursor location if selection disappears
-    
-    # parameters used for pausing
-    self.isPaused = False
-    self.pauseTime = 0              # time when paused
-    self.connectionsBuffer = []     # location where connections are stored while paused
-    self.connectionCountBuffer = []
-    self.familyResolutionsBuffer = {}
-    
-    # mapping of ip/port to fingerprint of family entries, used in hack to short circuit (ip / port) -> fingerprint lookups
-    self.familyResolutions = {}
-    
-    # mapping of family entries to fingerprints
-    self.familyFingerprints = {}
-    
-    self.address = ""
-    self.nickname = ""
-    self.listenPort = "0"           # port used to identify inbound/outbound connections (from ORListenAddress if defined, otherwise ORPort)
-    self.orPort = "0"
-    self.dirPort = "0"
-    self.controlPort = "0"
-    self.socksPort = "0"
-    self.family = []                # fingerpints of family entries
-    self.isBridge = False           # true if BridgeRelay is set
-    self.exitPolicy = ""
-    self.exitRejectPrivate = True   # true if ExitPolicyRejectPrivate is 0
-    
-    self.resetOptions()
-    
-    # connection results are tuples of the form:
-    # (type, local IP, local port, foreign IP, foreign port, country code)
-    self.connections = []
-    self.connectionsLock = RLock()    # limits modifications of connections
-    
-    # count of total inbound, outbound, client, directory, and control connections
-    self.connectionCount = [0] * 5
-    
-    self.reset()
-  
-  def resetOptions(self):
-    self.familyResolutions = {}
-    self.familyFingerprints = {}
-    
-    try:
-      self.address = "" # fetched when needed if unset
-      self.nickname = self.conn.get_option("Nickname")[0][1]
-      if self.nickname == None: self.nickname = "Unnamed"
-      
-      self.orPort = self.conn.get_option("ORPort")[0][1]
-      self.dirPort = self.conn.get_option("DirPort")[0][1]
-      self.controlPort = self.conn.get_option("ControlPort")[0][1]
-      
-      # uses ports to identify type of connections (ORListenAddress port overwrites ORPort if set)
-      listenAddr = self.conn.get_option("ORListenAddress")[0][1]
-      if listenAddr and ":" in listenAddr:
-        self.listenPort = listenAddr[listenAddr.find(":") + 1:]
-      else: self.listenPort = self.orPort
-      
-      self.socksPort = torTools.getConn().getOption("SocksPort", "0")
-      
-      # entry is None if not set, otherwise of the format "$<fingerprint>,$<fingerprint>"
-      familyEntry = self.conn.get_option("MyFamily")[0][1]
-      if familyEntry: self.family = familyEntry.split(",")
-      else: self.family = []
-      
-      self.isBridge = self.conn.get_option("BridgeRelay")[0][1] == "1"
-      
-      policyEntries = torTools.getConn().getOption("ExitPolicy", multiple=True)
-      if not policyEntries: policyEntries = [] # if ExitPolicy is undefined, policyEntries is None
-      self.exitPolicy = ",".join(policyEntries)
-      self.exitPolicy = self.exitPolicy.replace("\\t", " ").replace("\"", "")
-      
-      if self.exitPolicy: self.exitPolicy += "," + self.conn.get_info("exit-policy/default")["exit-policy/default"]
-      else: self.exitPolicy = self.conn.get_info("exit-policy/default")["exit-policy/default"]
-      
-      self.exitRejectPrivate = self.conn.get_option("ExitPolicyRejectPrivate")[0][1] == "1"
-      
-      self._resolveFamilyEntries()
-    except (socket.error, TorCtl.ErrorReply, TorCtl.TorCtlClosed):
-      self.nickname = ""
-      self.listenPort = None
-      self.orPort = "0"
-      self.dirPort = "0"
-      self.controlPort = "0"
-      self.socksPort = "0"
-      self.family = []
-      self.isBridge = False
-      self.exitPolicy = ""
-      self.exitRejectPrivate = True
-  
-  # change in client circuits
-  def circ_status_event(self, event):
-    self.clientConnectionLock.acquire()
-    self.clientConnectionCache = None
-    self.clientConnectionLock.release()
-  
-  # when consensus changes update fingerprint mappings
-  # TODO: should also be taking NS events into account
-  def new_consensus_event(self, event):
-    self.orconnStatusCacheValid = False
-    self.fingerprintLookupCache.clear()
-    self.nicknameLookupCache.clear()
-    self.fingerprintMappings = _getFingerprintMappings(self.conn, event.nslist)
-    if self.listingType != LIST_HOSTNAME: self.sortConnections()
-  
-  def new_desc_event(self, event):
-    self.orconnStatusCacheValid = False
-    self._resolveFamilyEntries()
-    
-    for fingerprint in event.idlist:
-      # clears entries with this fingerprint from the cache
-      if fingerprint in self.fingerprintLookupCache.values():
-        invalidEntries = set(k for k, v in self.fingerprintLookupCache.iteritems() if v == fingerprint)
-        for k in invalidEntries:
-          # nicknameLookupCache keys are a subset of fingerprintLookupCache
-          del self.fingerprintLookupCache[k]
-          if k in self.nicknameLookupCache.keys(): del self.nicknameLookupCache[k]
-      
-      # gets consensus data for the new description
-      try: nsData = self.conn.get_network_status("id/%s" % fingerprint)
-      except (socket.error, TorCtl.ErrorReply, TorCtl.TorCtlClosed): return
-      
-      if len(nsData) > 1:
-        # multiple records for fingerprint (shouldn't happen)
-        log.log(log.WARN, "Multiple consensus entries for fingerprint: %s" % fingerprint)
-        return
-      nsEntry = nsData[0]
-      
-      # updates fingerprintMappings with new data
-      if nsEntry.ip in self.fingerprintMappings.keys():
-        # if entry already exists with the same orport, remove it
-        orportMatch = None
-        for entryPort, entryFingerprint, entryNickname in self.fingerprintMappings[nsEntry.ip]:
-          if entryPort == nsEntry.orport:
-            orportMatch = (entryPort, entryFingerprint, entryNickname)
-            break
-        
-        if orportMatch: self.fingerprintMappings[nsEntry.ip].remove(orportMatch)
-        
-        # add new entry
-        self.fingerprintMappings[nsEntry.ip].append((nsEntry.orport, nsEntry.idhex, nsEntry.nickname))
-      else:
-        self.fingerprintMappings[nsEntry.ip] = [(nsEntry.orport, nsEntry.idhex, nsEntry.nickname)]
-    if self.listingType != LIST_HOSTNAME: self.sortConnections()
-  
-  def reset(self):
-    """
-    Reloads connection results.
-    """
-    
-    if self.isDisabled: return
-    
-    # inaccessable during startup so might need to be refetched
-    try:
-      if not self.address: self.address = self.conn.get_info("address")["address"]
-    except (socket.error, TorCtl.ErrorReply, TorCtl.TorCtlClosed): pass
-    
-    self.connectionsLock.acquire()
-    self.clientConnectionLock.acquire()
-    
-    # temporary variables for connections and count
-    connectionsTmp = []
-    connectionCountTmp = [0] * 5
-    familyResolutionsTmp = {}
-    
-    # used (with isBridge) to determine if inbound connections should be scrubbed
-    isGuard = False
-    try:
-      myFingerprint = self.conn.get_info("fingerprint")
-      nsCall = self.conn.get_network_status("id/%s" % myFingerprint)
-      if nsCall: isGuard = "Guard" in nsCall[0].flags
-      else: raise TorCtl.ErrorReply # network consensus couldn't be fetched
-    except (socket.error, TorCtl.ErrorReply, TorCtl.TorCtlClosed): pass
-    
-    try:
-      if self.clientConnectionCache == None:
-        # client connection cache was invalidated
-        self.clientConnectionCache = _getClientConnections(self.conn)
-      
-      connTimes = {} # mapping of ip/port to connection time
-      for entry in (self.connections if not self.isPaused else self.connectionsBuffer):
-        connTimes[(entry[CONN_F_IP], entry[CONN_F_PORT])] = entry[CONN_TIME]
-      
-      results = connections.getResolver("tor").getConnections()
-      if results == self.lastConnResults: return # contents haven't changed
-      
-      for lIp, lPort, fIp, fPort in results:
-        fingerprint = self.getFingerprint(fIp, fPort)
-        
-        isPrivate = False
-        if lPort in (self.listenPort, self.dirPort):
-          type = "inbound"
-          connectionCountTmp[0] += 1
-          if SCRUB_PRIVATE_DATA and fIp not in self.fingerprintMappings.keys(): isPrivate = isGuard or self.isBridge
-        elif lPort == self.socksPort:
-          type = "client"
-          connectionCountTmp[2] += 1
-        elif lPort == self.controlPort:
-          type = "control"
-          connectionCountTmp[4] += 1
-        else:
-          nickname = self.getNickname(fIp, fPort)
-          
-          isClient = False
-          for clientName in self.clientConnectionCache:
-            if nickname == clientName or (len(clientName) > 1 and clientName[0] == "$" and fingerprint == clientName[1:]):
-              isClient = True
-              break
-          
-          if isClient:
-            type = "client"
-            connectionCountTmp[2] += 1
-          elif (fIp, fPort) in DIR_SERVERS:
-            type = "directory"
-            connectionCountTmp[3] += 1
-          else:
-            type = "outbound"
-            connectionCountTmp[1] += 1
-            if SCRUB_PRIVATE_DATA and fIp not in self.fingerprintMappings.keys(): isPrivate = isExitAllowed(fIp, fPort, self.exitPolicy, self.exitRejectPrivate)
-        
-        # replace nat address with external version if available and the
-        # external address isn't a private IP
-        isPrivateIp = ipAddressIsPrivate(fIp)
-        if self.address and type != "control" and not isPrivateIp: lIp = self.address
-        
-        if isPrivateIp:
-          countryCode = "??"
-        else:
-          try:
-            countryCodeQuery = "ip-to-country/%s" % fIp
-            countryCode = self.conn.get_info(countryCodeQuery)[countryCodeQuery]
-          except (socket.error, TorCtl.ErrorReply, TorCtl.TorCtlClosed):
-            countryCode = "??"
-            if not self.providedGeoipWarning:
-              log.log(log.WARN, "Tor geoip database is unavailable.")
-              self.providedGeoipWarning = True
-        
-        if (fIp, fPort) in connTimes: connTime = connTimes[(fIp, fPort)]
-        else: connTime = time.time()
-        
-        connectionsTmp.append((type, lIp, lPort, fIp, fPort, countryCode, connTime, isPrivate))
-      
-      # appends localhost connection to allow user to look up their own consensus entry
-      selfFingerprint = None
-      try:
-        selfFingerprint = self.conn.get_info("fingerprint")["fingerprint"]
-      except (socket.error, TorCtl.ErrorReply, TorCtl.TorCtlClosed): pass
-      
-      if self.address and selfFingerprint:
-        try:
-          countryCodeQuery = "ip-to-country/%s" % self.address
-          selfCountryCode = self.conn.get_info(countryCodeQuery)[countryCodeQuery]
-        except (socket.error, TorCtl.ErrorReply, TorCtl.TorCtlClosed):
-          selfCountryCode = "??"
-        
-        if (self.address, self.orPort) in connTimes: connTime = connTimes[(self.address, self.orPort)]
-        else: connTime = time.time()
-        
-        self.localhostEntry = (("localhost", self.address, self.orPort, self.address, self.orPort, selfCountryCode, connTime, False), selfFingerprint)
-        connectionsTmp.append(self.localhostEntry[0])
-      else:
-        self.localhostEntry = None
-      
-      # appends family connections
-      tmpCounter = 0 # used for unique port of unresolved family entries (funky hack)
-      for familyEntry in self.family:
-        # TODO: turns out that "ns/name/<OR nickname>" accpets fingerprint
-        # identifiers, so all this nickname -> fingerprint work is unnecessary,
-        # but used for fingerprint lookup performance in draw... this could be
-        # improved (might be completely unnecessary due to the fingerprint
-        # lookup cache)
-        fingerprint = None
-        if familyEntry in self.familyFingerprints:
-          fingerprint = self.familyFingerprints[familyEntry]
-        
-        try:
-          if fingerprint: nsCall = self.conn.get_network_status("id/%s" % fingerprint)
-          else: nsCall = self.conn.get_network_status("name/%s" % familyEntry)
-          if nsCall: familyAddress, familyPort = nsCall[0].ip, nsCall[0].orport
-          else: raise TorCtl.ErrorReply # network consensus couldn't be fetched
-          
-          countryCodeQuery = "ip-to-country/%s" % familyAddress
-          familyCountryCode = self.conn.get_info(countryCodeQuery)[countryCodeQuery]
-          
-          if (familyAddress, familyPort) in connTimes: connTime = connTimes[(familyAddress, familyPort)]
-          else: connTime = time.time()
-          
-          if fingerprint: familyResolutionsTmp[(familyAddress, familyPort)] = fingerprint
-          connectionsTmp.append(("family", familyAddress, familyPort, familyAddress, familyPort, familyCountryCode, connTime, False))
-        except (socket.error, TorCtl.ErrorReply):
-          # use dummy entry for sorting - the draw function notes that entries are unknown
-          portIdentifier = str(65536 + tmpCounter)
-          if fingerprint: familyResolutionsTmp[("256.255.255.255", portIdentifier)] = fingerprint
-          connectionsTmp.append(("family", "256.255.255.255", portIdentifier, "256.255.255.255", portIdentifier, "??", time.time(), False))
-          tmpCounter += 1
-        except TorCtl.TorCtlClosed:
-          pass # connections aren't shown when control port is unavailable
-      
-      self.lastUpdate = time.time()
-      
-      # assigns results
-      if self.isPaused:
-        self.connectionsBuffer = connectionsTmp
-        self.connectionCountBuffer = connectionCountTmp
-        self.familyResolutionsBuffer = familyResolutionsTmp
-      else:
-        self.connections = connectionsTmp
-        self.connectionCount = connectionCountTmp
-        self.familyResolutions = familyResolutionsTmp
-        
-        # hostnames are sorted at draw - otherwise now's a good time
-        if self.listingType != LIST_HOSTNAME: self.sortConnections()
-      self.lastConnResults = results
-    finally:
-      self.connectionsLock.release()
-      self.clientConnectionLock.release()
-  
-  def handleKey(self, key):
-    # cursor or scroll movement
-    
-    #if key in (curses.KEY_UP, curses.KEY_DOWN, curses.KEY_PPAGE, curses.KEY_NPAGE):
-    if uiTools.isScrollKey(key):
-      pageHeight = self.getPreferredSize()[0] - 1
-      if self.showingDetails: pageHeight -= 8
-      
-      self.connectionsLock.acquire()
-      try:
-        # determines location parameter to use
-        if self.isCursorEnabled:
-          try: currentLoc = self.connections.index(self.cursorSelection)
-          except ValueError: currentLoc = self.cursorLoc # fall back to nearby entry
-        else: currentLoc = self.scroll
-        
-        # location offset
-        if key == curses.KEY_UP: shift = -1
-        elif key == curses.KEY_DOWN: shift = 1
-        elif key == curses.KEY_PPAGE: shift = -pageHeight + 1 if self.isCursorEnabled else -pageHeight
-        elif key == curses.KEY_NPAGE: shift = pageHeight - 1 if self.isCursorEnabled else pageHeight
-        elif key == curses.KEY_HOME: shift = -currentLoc
-        elif key == curses.KEY_END: shift = len(self.connections) # always below the lower bound
-        newLoc = currentLoc + shift
-        
-        # restricts to valid bounds
-        maxLoc = len(self.connections) - 1 if self.isCursorEnabled else len(self.connections) - pageHeight
-        newLoc = max(0, min(newLoc, maxLoc))
-        
-        # applies to proper parameter
-        if self.isCursorEnabled and self.connections:
-          self.cursorSelection, self.cursorLoc = self.connections[newLoc], newLoc
-        else: self.scroll = newLoc
-      finally:
-        self.connectionsLock.release()
-    elif key == ord('r') or key == ord('R'):
-      self.allowDNS = not self.allowDNS
-      if not self.allowDNS: hostnames.setPaused(True)
-      elif self.listingType == LIST_HOSTNAME: hostnames.setPaused(False)
-    else: return # skip following redraw
-    self.redraw(True)
-  
-  def draw(self, width, height):
-    self.connectionsLock.acquire()
-    try:
-      # hostnames frequently get updated so frequent sorting needed
-      if self.listingType == LIST_HOSTNAME: self.sortConnections()
-      
-      if self.showLabel:
-        # notes the number of connections for each type if above zero
-        countLabel = ""
-        for i in range(len(self.connectionCount)):
-          if self.connectionCount[i] > 0: countLabel += "%i %s, " % (self.connectionCount[i], CONN_COUNT_LABELS[i])
-        if countLabel: countLabel = " (%s)" % countLabel[:-2] # strips ending ", " and encases in parentheses
-        self.addstr(0, 0, "Connections%s:" % countLabel, curses.A_STANDOUT)
-      
-      if self.connections:
-        listingHeight = height - 1
-        currentTime = time.time() if not self.isPaused else self.pauseTime
-        
-        if self.showingDetails:
-          listingHeight -= 8
-          isScrollBarVisible = len(self.connections) > height - 9
-          if width > 80: self.win.hline(8, 80, curses.ACS_HLINE, width - 81)
-        else:
-          isScrollBarVisible = len(self.connections) > height - 1
-        xOffset = 3 if isScrollBarVisible else 0 # content offset for scroll bar
-        
-        # ensure cursor location and scroll top are within bounds
-        self.cursorLoc = max(min(self.cursorLoc, len(self.connections) - 1), 0)
-        self.scroll = max(min(self.scroll, len(self.connections) - listingHeight), 0)
-        
-        if self.isCursorEnabled:
-          # update cursorLoc with selection (or vice versa if selection not found)
-          if self.cursorSelection not in self.connections:
-            self.cursorSelection = self.connections[self.cursorLoc]
-          else: self.cursorLoc = self.connections.index(self.cursorSelection)
-          
-          # shift scroll if necessary for cursor to be visible
-          if self.cursorLoc < self.scroll: self.scroll = self.cursorLoc
-          elif self.cursorLoc - listingHeight + 1 > self.scroll: self.scroll = self.cursorLoc - listingHeight + 1
-        
-        lineNum = (-1 * self.scroll) + 1
-        for entry in self.connections:
-          if lineNum >= 1:
-            type = entry[CONN_TYPE]
-            isPrivate = entry[CONN_PRIVATE]
-            color = TYPE_COLORS[type]
-            
-            # adjustments to measurements for 'xOffset' are to account for scroll bar
-            if self.listingType == LIST_IP:
-              # base data requires 73 characters
-              src = "%s:%s" % (entry[CONN_L_IP], entry[CONN_L_PORT])
-              dst = "%s:%s" % (entry[CONN_F_IP], entry[CONN_F_PORT])
-              if not ipAddressIsPrivate(entry[CONN_F_IP]):
-                dst += " (%s)" % entry[CONN_COUNTRY]
-              
-              if isPrivate: dst = "<scrubbed>"
-              
-              src, dst = "%-21s" % src, "%-26s" % dst
-              
-              etc = ""
-              if width > 115 + xOffset:
-                # show fingerprint (column width: 42 characters)
-                etc += "%-40s  " % self.getFingerprint(entry[CONN_F_IP], entry[CONN_F_PORT])
-                
-              if width > 127 + xOffset:
-                # show nickname (column width: remainder)
-                nickname = self.getNickname(entry[CONN_F_IP], entry[CONN_F_PORT])
-                nicknameSpace = width - 118 - xOffset
-                
-                # truncates if too long
-                if len(nickname) > nicknameSpace: nickname = "%s..." % nickname[:nicknameSpace - 3]
-                
-                etc += ("%%-%is  " % nicknameSpace) % nickname
-            elif self.listingType == LIST_HOSTNAME:
-              # base data requires 80 characters
-              src = "localhost:%-5s" % entry[CONN_L_PORT]
-              
-              # space available for foreign hostname (stretched to claim any free space)
-              foreignHostnameSpace = width - 42 - xOffset
-              
-              etc = ""
-              if width > 102 + xOffset:
-                # shows ip/locale (column width: 22 characters)
-                foreignHostnameSpace -= 22
-                
-                if isPrivate: ipEntry = "<scrubbed>"
-                else:
-                  ipEntry = "%s:%s" % (entry[CONN_F_IP], entry[CONN_F_PORT])
-                  if ipAddressIsPrivate(entry[CONN_F_IP]):
-                    ipEntry += " (%s)" % entry[CONN_COUNTRY]
-                
-                etc += "%-20s  " % ipEntry
-              if width > 134 + xOffset:
-                # show fingerprint (column width: 42 characters)
-                foreignHostnameSpace -= 42
-                etc += "%-40s  " % self.getFingerprint(entry[CONN_F_IP], entry[CONN_F_PORT])
-              
-              if width > 151 + xOffset:
-                # show nickname (column width: min 17 characters, uses half of the remainder)
-                nickname = self.getNickname(entry[CONN_F_IP], entry[CONN_F_PORT])
-                nicknameSpace = 15 + (width - xOffset - 151) / 2
-                foreignHostnameSpace -= (nicknameSpace + 2)
-                
-                if len(nickname) > nicknameSpace: nickname = "%s..." % nickname[:nicknameSpace - 3]
-                etc += ("%%-%is  " % nicknameSpace) % nickname
-              
-              if isPrivate: dst = "<scrubbed>"
-              else:
-                try: hostname = hostnames.resolve(entry[CONN_F_IP])
-                except ValueError: hostname = None
-                
-                # truncates long hostnames
-                portDigits = len(str(entry[CONN_F_PORT]))
-                if hostname and (len(hostname) + portDigits) > foreignHostnameSpace - 1:
-                  hostname = hostname[:(foreignHostnameSpace - portDigits - 4)] + "..."
-                
-                dst = "%s:%s" % (hostname if hostname else entry[CONN_F_IP], entry[CONN_F_PORT])
-              
-              dst = ("%%-%is" % foreignHostnameSpace) % dst
-            elif self.listingType == LIST_FINGERPRINT:
-              # base data requires 75 characters
-              src = "localhost"
-              if entry[CONN_TYPE] == "control": dst = "localhost"
-              else: dst = self.getFingerprint(entry[CONN_F_IP], entry[CONN_F_PORT])
-              dst = "%-40s" % dst
-              
-              etc = ""
-              if width > 92 + xOffset:
-                # show nickname (column width: min 17 characters, uses remainder if extra room's available)
-                nickname = self.getNickname(entry[CONN_F_IP], entry[CONN_F_PORT])
-                nicknameSpace = width - 78 - xOffset if width < 126 else width - 106 - xOffset
-                if len(nickname) > nicknameSpace: nickname = "%s..." % nickname[:nicknameSpace - 3]
-                etc += ("%%-%is  " % nicknameSpace) % nickname
-              
-              if width > 125 + xOffset:
-                # shows ip/port/locale (column width: 28 characters)
-                if isPrivate: ipEntry = "<scrubbed>"
-                else:
-                  ipEntry = "%s:%s" % (entry[CONN_F_IP], entry[CONN_F_PORT])
-                  if ipAddressIsPrivate(entry[CONN_F_IP]):
-                    ipEntry += " (%s)" % entry[CONN_COUNTRY]
-                
-                etc += "%-26s  " % ipEntry
-            else:
-              # base data uses whatever extra room's available (using minimun of 50 characters)
-              src = self.nickname
-              if entry[CONN_TYPE] == "control": dst = self.nickname
-              else: dst = self.getNickname(entry[CONN_F_IP], entry[CONN_F_PORT])
-              
-              # space available for foreign nickname
-              foreignNicknameSpace = width - len(self.nickname) - 27 - xOffset
-              
-              etc = ""
-              if width > 92 + xOffset:
-                # show fingerprint (column width: 42 characters)
-                foreignNicknameSpace -= 42
-                etc += "%-40s  " % self.getFingerprint(entry[CONN_F_IP], entry[CONN_F_PORT])
-              
-              if width > 120 + xOffset:
-                # shows ip/port/locale (column width: 28 characters)
-                foreignNicknameSpace -= 28
-                
-                if isPrivate: ipEntry = "<scrubbed>"
-                else:
-                  ipEntry = "%s:%s" % (entry[CONN_F_IP], entry[CONN_F_PORT])
-                  if ipAddressIsPrivate(entry[CONN_F_IP]):
-                    ipEntry += " (%s)" % entry[CONN_COUNTRY]
-                
-                etc += "%-26s  " % ipEntry
-              
-              dst = ("%%-%is" % foreignNicknameSpace) % dst
-            
-            timeLabel = uiTools.getTimeLabel(currentTime - entry[CONN_TIME], 1)
-            if type == "inbound": src, dst = dst, src
-            elif type == "family" and int(entry[CONN_L_PORT]) > 65535:
-              # this belongs to an unresolved family entry - replaces invalid data with "UNKNOWN"
-              timeLabel = "---"
-              
-              if self.listingType == LIST_IP:
-                src = "%-21s" % "UNKNOWN"
-                dst = "%-26s" % "UNKNOWN"
-              elif self.listingType == LIST_HOSTNAME:
-                src = "%-15s" % "UNKNOWN"
-                dst = ("%%-%is" % len(dst)) % "UNKNOWN"
-                if len(etc) > 0: etc = etc.replace("256.255.255.255 (??)", "UNKNOWN" + " " * 13)
-              else:
-                ipStart = etc.find("256")
-                if ipStart > -1: etc = etc[:ipStart] + ("%%-%is" % len(etc[ipStart:])) % "UNKNOWN"
-            
-            padding = width - (len(src) + len(dst) + len(etc) + 27) - xOffset # padding needed to fill full line
-            lineEntry = "<%s>%s  -->  %s  %s%s%5s (<b>%s</b>)%s</%s>" % (color, src, dst, etc, " " * padding, timeLabel, type.upper(), " " * (9 - len(type)), color)
-            
-            if self.isCursorEnabled and entry == self.cursorSelection:
-              lineEntry = "<h>%s</h>" % lineEntry
-            
-            yOffset = 0 if not self.showingDetails else 8
-            self.addfstr(lineNum + yOffset, xOffset, lineEntry)
-          lineNum += 1
-        
-        if isScrollBarVisible:
-          topY = 9 if self.showingDetails else 1
-          bottomEntry = self.scroll + height - 9 if self.showingDetails else self.scroll + height - 1
-          self.addScrollBar(self.scroll, bottomEntry, len(self.connections), topY)
-    finally:
-      self.connectionsLock.release()
-  
-  def getFingerprint(self, ipAddr, port):
-    """
-    Makes an effort to match connection to fingerprint - if there's multiple
-    potential matches or the IP address isn't found in the discriptor then
-    returns "UNKNOWN".
-    """
-    
-    # checks to see if this matches the localhost entry
-    if self.localhostEntry and ipAddr == self.localhostEntry[0][CONN_L_IP] and port == self.localhostEntry[0][CONN_L_PORT]:
-      return self.localhostEntry[1]
-    
-    # checks if this belongs to a family entry
-    if (ipAddr, port) in self.familyResolutions.keys():
-      return self.familyResolutions[(ipAddr, port)]
-    
-    port = int(port)
-    if (ipAddr, port) in self.fingerprintLookupCache:
-      return self.fingerprintLookupCache[(ipAddr, port)]
-    else:
-      match = None
-      
-      # orconn-status provides a listing of Tor's current connections - used to
-      # eliminated ambiguity for outbound connections
-      if not self.orconnStatusCacheValid:
-        self.orconnStatusCache, isOdd = [], True
-        self.orconnStatusCacheValid = True
-        try:
-          for entry in self.conn.get_info("orconn-status")["orconn-status"].split():
-            if isOdd: self.orconnStatusCache.append(entry)
-            isOdd = not isOdd
-        except (socket.error, TorCtl.ErrorReply, TorCtl.TorCtlClosed): self.orconnStatusCache = None
-      
-      if ipAddr in self.fingerprintMappings.keys():
-        potentialMatches = self.fingerprintMappings[ipAddr]
-        
-        if len(potentialMatches) == 1: match = potentialMatches[0][1]
-        else:
-          # multiple potential matches - look for exact match with port
-          for (entryPort, entryFingerprint, entryNickname) in potentialMatches:
-            if entryPort == port:
-              match = entryFingerprint
-              break
-        
-        if not match:
-          # still haven't found it - use trick from Mike's ConsensusTracker,
-          # excluding possiblities that have...
-          # ... lost their Running flag
-          # ... list a bandwidth of 0
-          # ... have 'opt hibernating' set
-          operativeMatches = list(potentialMatches)
-          for entryPort, entryFingerprint, entryNickname in potentialMatches:
-            # gets router description to see if 'down' is set
-            toRemove = False
-            try:
-              nsCall = self.conn.get_network_status("id/%s" % entryFingerprint)
-              if not nsCall: raise TorCtl.ErrorReply() # network consensus couldn't be fetched
-              else: nsEntry = nsCall[0]
-              
-              descLookupCmd = "desc/id/%s" % entryFingerprint
-              descEntry = TorCtl.Router.build_from_desc(self.conn.get_info(descLookupCmd)[descLookupCmd].split("\n"), nsEntry)
-              toRemove = descEntry.down
-            except (socket.error, TorCtl.ErrorReply, TorCtl.TorCtlClosed): pass # ns or desc lookup fails... also weird
-            
-            # eliminates connections not reported by orconn-status -
-            # this has *very* little impact since few ips have multiple relays
-            if self.orconnStatusCache and not toRemove: toRemove = entryNickname not in self.orconnStatusCache
-            
-            if toRemove: operativeMatches.remove((entryPort, entryFingerprint, entryNickname))
-          
-          if len(operativeMatches) == 1: match = operativeMatches[0][1]
-      
-      if not match: match = "UNKNOWN"
-      
-      self.fingerprintLookupCache[(ipAddr, port)] = match
-      return match
-  
-  def getNickname(self, ipAddr, port):
-    """
-    Attempts to provide the nickname for an ip/port combination, "UNKNOWN"
-    if this can't be determined.
-    """
-    
-    if (ipAddr, port) in self.nicknameLookupCache:
-      return self.nicknameLookupCache[(ipAddr, port)]
-    else:
-      match = self.getFingerprint(ipAddr, port)
-      
-      try:
-        if match != "UNKNOWN":
-          nsCall = self.conn.get_network_status("id/%s" % match)
-          if nsCall: match = nsCall[0].nickname
-          else: raise TorCtl.ErrorReply # network consensus couldn't be fetched
-      except (socket.error, TorCtl.ErrorReply, TorCtl.TorCtlClosed): return "UNKNOWN" # don't cache result
-      
-      self.nicknameLookupCache[(ipAddr, port)] = match
-      return match
-  
-  def setPaused(self, isPause):
-    """
-    If true, prevents connection listing from being updated.
-    """
-    
-    if isPause == self.isPaused: return
-    
-    self.isPaused = isPause
-    if isPause:
-      self.pauseTime = time.time()
-      self.connectionsBuffer = list(self.connections)
-      self.connectionCountBuffer = list(self.connectionCount)
-      self.familyResolutionsBuffer = dict(self.familyResolutions)
-    else:
-      self.connections = list(self.connectionsBuffer)
-      self.connectionCount = list(self.connectionCountBuffer)
-      self.familyResolutions = dict(self.familyResolutionsBuffer)
-      
-      # pause buffer connections may be unsorted
-      if self.listingType != LIST_HOSTNAME: self.sortConnections()
-  
-  def sortConnections(self):
-    """
-    Sorts connections according to currently set ordering. This takes into
-    account secondary and tertiary sub-keys in case of ties.
-    """
-    
-    # Current implementation is very inefficient, but since connection lists
-    # are decently small (count get up to arounk 1k) this shouldn't be a big
-    # whoop. Suggestions for improvements are welcome!
-    
-    sorts = []
-    
-    # wrapper function for using current listed data (for 'LISTING' sorts)
-    if self.listingType == LIST_IP:
-      listingWrapper = lambda ip, port: _ipToInt(ip)
-    elif self.listingType == LIST_HOSTNAME:
-      # alphanumeric hostnames followed by unresolved IP addresses
-      listingWrapper = lambda ip, port: _getHostname(ip).upper() if _getHostname(ip) else "zzzzz%099i" % _ipToInt(ip)
-    elif self.listingType == LIST_FINGERPRINT:
-      # alphanumeric fingerprints followed by UNKNOWN entries
-      listingWrapper = lambda ip, port: self.getFingerprint(ip, port) if self.getFingerprint(ip, port) != "UNKNOWN" else "zzzzz%099i" % _ipToInt(ip)
-    elif self.listingType == LIST_NICKNAME:
-      # alphanumeric nicknames followed by Unnamed then UNKNOWN entries
-      listingWrapper = lambda ip, port: self.getNickname(ip, port) if self.getNickname(ip, port) not in ("UNKNOWN", "Unnamed") else "zzzzz%i%099i" % (0 if self.getNickname(ip, port) == "Unnamed" else 1, _ipToInt(ip))
-    
-    for entry in self.sortOrdering:
-      if entry == ORD_FOREIGN_LISTING:
-        sorts.append(lambda x, y: cmp(listingWrapper(x[CONN_F_IP], x[CONN_F_PORT]), listingWrapper(y[CONN_F_IP], y[CONN_F_PORT])))
-      elif entry == ORD_SRC_LISTING:
-        sorts.append(lambda x, y: cmp(listingWrapper(x[CONN_F_IP] if x[CONN_TYPE] == "inbound" else x[CONN_L_IP], x[CONN_F_PORT]), listingWrapper(y[CONN_F_IP] if y[CONN_TYPE] == "inbound" else y[CONN_L_IP], y[CONN_F_PORT])))
-      elif entry == ORD_DST_LISTING:
-        sorts.append(lambda x, y: cmp(listingWrapper(x[CONN_L_IP] if x[CONN_TYPE] == "inbound" else x[CONN_F_IP], x[CONN_F_PORT]), listingWrapper(y[CONN_L_IP] if y[CONN_TYPE] == "inbound" else y[CONN_F_IP], y[CONN_F_PORT])))
-      else: sorts.append(SORT_TYPES[entry][2])
-    
-    self.connectionsLock.acquire()
-    try: self.connections.sort(lambda x, y: _multisort(x, y, sorts))
-    finally: self.connectionsLock.release()
-
-  def _resolveFamilyEntries(self):
-    """
-    Populates mappings of the torrc family entries to their fingerprints.
-    """
-    
-    self.familyFingerprints = {}
-    
-    for familyEntry in self.family:
-      if not familyEntry: continue
-      
-      if familyEntry[0] == "$":
-        # relay identified by fingerprint
-        self.familyFingerprints[familyEntry] = familyEntry[1:]
-      else:
-        # relay identified by nickname
-        descEntry = torTools.getConn().getInfo("desc/name/%s" % familyEntry)
-        
-        if descEntry:
-          fingerprintStart = descEntry.find("opt fingerprint") + 16
-          fingerprintEnd = descEntry.find("\n", fingerprintStart)
-          fingerprint = descEntry[fingerprintStart:fingerprintEnd].replace(" ", "")
-          
-          self.familyFingerprints[familyEntry] = fingerprint
-
-# recursively checks primary, secondary, and tertiary sorting parameter in ties
-def _multisort(conn1, conn2, sorts):
-  comp = sorts[0](conn1, conn2)
-  if comp or len(sorts) == 1: return comp
-  else: return _multisort(conn1, conn2, sorts[1:])
-
-def _getHostname(ipAddr):
-  try: return hostnames.resolve(ipAddr)
-  except ValueError: return None
-
-# provides comparison int for sorting IP addresses
-def _ipToInt(ipAddr):
-  total = 0
-  for comp in ipAddr.split("."):
-    total *= 255
-    total += int(comp)
-  return total
-
-# uses consensus data to map IP addresses to port / fingerprint combinations
-def _getFingerprintMappings(conn, nsList = None):
-  ipToFingerprint = {}
-  
-  if not nsList:
-    try: nsList = conn.get_network_status()
-    except (socket.error, TorCtl.TorCtlClosed, TorCtl.ErrorReply): nsList = []
-    except TypeError: nsList = [] # TODO: temporary workaround for a TorCtl bug, remove when fixed
-  
-  for entry in nsList:
-    if entry.ip in ipToFingerprint.keys(): ipToFingerprint[entry.ip].append((entry.orport, entry.idhex, entry.nickname))
-    else: ipToFingerprint[entry.ip] = [(entry.orport, entry.idhex, entry.nickname)]
-  
-  return ipToFingerprint
-
-# provides client relays we're currently attached to (first hops in circuits)
-# this consists of the nicknames and ${fingerprint} if unnamed
-def _getClientConnections(conn):
-  clients = []
-  
-  try:
-    for line in conn.get_info("circuit-status")["circuit-status"].split("\n"):
-      components = line.split()
-      if len(components) > 3: clients += [components[2].split(",")[0]]
-  except (socket.error, TorCtl.ErrorReply, TorCtl.TorCtlClosed): pass
-  
-  return clients
-
-def isExitAllowed(ip, port, exitPolicy, isPrivateRejected):
-  """
-  Determines if a given connection is a permissable exit with the given 
-  policy or not (True if it's allowed to be an exit connection, False 
-  otherwise).
-  
-  NOTE: this is a little tricky and liable to need some tweaks
-  """
-  
-  # might not be set when first starting up
-  if not exitPolicy: return True
-  
-  # TODO: move into a utility and craft some unit tests (this is very error 
-  # prone...)
-  
-  # TODO: currently doesn't consider ExitPolicyRejectPrivate (which prevents 
-  # connections to private networks and local ip)
-  for entry in exitPolicy.split(","):
-    entry = entry.strip()
-    
-    isAccept = entry.startswith("accept")
-    entry = entry[7:] # strips off "accept " or "reject "
-    
-    # parses ip address (with mask if provided) and port
-    if ":" in entry:
-      entryIP = entry[:entry.find(":")]
-      entryPort = entry[entry.find(":") + 1:]
-    else:
-      entryIP = entry
-      entryPort = "*"
-    
-    #raise AssertionError(str(exitPolicy) + " - " + entryIP + ":" + entryPort)
-    isIPMatch = entryIP == ip or entryIP[0] == "*"
-    
-    if not "-" in entryPort:
-      # single port
-      isPortMatch = entryPort == str(port) or entryPort[0] == "*"
-    else:
-      # port range
-      minPort = int(entryPort[:entryPort.find("-")])
-      maxPort = int(entryPort[entryPort.find("-") + 1:])
-      isPortMatch = port >= minPort and port <= maxPort
-    
-    # TODO: Currently being lazy and considering subnet masks or 'private' 
-    # keyword to be equivilant to wildcard if it would reject, and none 
-    # if it would accept (ie, being conservative with acceptance). Would be 
-    # nice to fix at some point.
-    if not isAccept: isIPMatch |= "/" in entryIP or entryIP == "private"
-    
-    if isIPMatch and isPortMatch: return isAccept
-  
-  # we shouldn't ever fall through due to default exit policy
-  log.log(log.WARN, "Exit policy left connection uncategorized: %s:%i" % (ip, port))
-  return False
-
diff --git a/src/interface/controller.py b/src/interface/controller.py
index b88152f..5060188 100644
--- a/src/interface/controller.py
+++ b/src/interface/controller.py
@@ -18,7 +18,6 @@ from TorCtl import TorCtl
 import headerPanel
 import graphing.graphPanel
 import logPanel
-import connPanel
 import configPanel
 import torrcPanel
 import descriptorPopup
@@ -43,17 +42,14 @@ PAGE_S = ["header", "control", "popup"] # sticky (ie, always available) page
 PAGES = [
   ["graph", "log"],
   ["conn"],
-  ["conn2"],
   ["config"],
   ["torrc"]]
 
-PAUSEABLE = ["header", "graph", "log", "conn", "conn2"]
+PAUSEABLE = ["header", "graph", "log", "conn"]
 
 CONFIG = {"log.torrc.readFailed": log.WARN,
           "features.graph.type": 1,
           "features.config.prepopulateEditValues": True,
-          "features.connection.oldPanel": False,
-          "features.connection.newPanel": True,
           "queries.refreshRate.rate": 5,
           "log.torEventTypeUnrecognized": log.NOTICE,
           "features.graph.bw.prepopulate": True,
@@ -119,11 +115,7 @@ class ControlPanel(panel.Panel):
         currentPage = self.page
         pageCount = len(PAGES)
         
-        if not CONFIG["features.connection.newPanel"]:
-          if currentPage >= 3: currentPage -= 1
-          pageCount -= 1
-        
-        if self.isBlindMode or not CONFIG["features.connection.oldPanel"]:
+        if self.isBlindMode:
           if currentPage >= 2: currentPage -= 1
           pageCount -= 1
         
@@ -562,17 +554,7 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode):
   # before being positioned - the following is a quick hack til rewritten
   panels["log"].setPaused(True)
   
-  if CONFIG["features.connection.oldPanel"]:
-    panels["conn"] = connPanel.ConnPanel(stdscr, conn, isBlindMode)
-  else:
-    panels["conn"] = panel.Panel(stdscr, "blank", 0, 0, 0)
-    PAUSEABLE.remove("conn")
-  
-  if CONFIG["features.connection.newPanel"]:
-    panels["conn2"] = interface.connections.connPanel.ConnectionPanel(stdscr, config)
-  else:
-    panels["conn2"] = panel.Panel(stdscr, "blank", 0, 0, 0)
-    PAUSEABLE.remove("conn2")
+  panels["conn"] = interface.connections.connPanel.ConnectionPanel(stdscr, config)
   
   panels["control"] = ControlPanel(stdscr, isBlindMode)
   panels["config"] = configPanel.ConfigPanel(stdscr, configPanel.State.TOR, config)
@@ -599,8 +581,6 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode):
   conn.add_event_listener(panels["graph"].stats["bandwidth"])
   conn.add_event_listener(panels["graph"].stats["system resources"])
   if not isBlindMode: conn.add_event_listener(panels["graph"].stats["connections"])
-  if CONFIG["features.connection.oldPanel"]:
-    conn.add_event_listener(panels["conn"])
   conn.add_event_listener(sighupTracker)
   
   # prepopulates bandwidth values from state file
@@ -627,8 +607,7 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode):
   # tells revised panels to run as daemons
   panels["header"].start()
   panels["log"].start()
-  if CONFIG["features.connection.newPanel"]:
-    panels["conn2"].start()
+  panels["conn"].start()
   
   # warns if tor isn't updating descriptors
   #try:
@@ -687,8 +666,6 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode):
         #panels["header"]._updateParams(True)
         
         # other panels that use torrc data
-        if CONFIG["features.connection.oldPanel"]:
-          panels["conn"].resetOptions()
         #if not isBlindMode: panels["graph"].stats["connections"].resetOptions(conn)
         #panels["graph"].stats["bandwidth"].resetOptions()
         
@@ -749,9 +726,6 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode):
           isUnresponsive = False
           log.log(log.NOTICE, "Relay resumed")
       
-      if CONFIG["features.connection.oldPanel"]:
-        panels["conn"].reset()
-      
       # TODO: part two of hack to prevent premature drawing by log panel
       if page == 0 and not isPaused: panels["log"].setPaused(False)
       
@@ -844,11 +818,11 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode):
         
         # stops panel daemons
         panels["header"].stop()
-        if CONFIG["features.connection.newPanel"]: panels["conn2"].stop()
+        panels["conn"].stop()
         panels["log"].stop()
         
         panels["header"].join()
-        if CONFIG["features.connection.newPanel"]: panels["conn2"].join()
+        panels["conn"].join()
         panels["log"].join()
         
         # joins on utility daemon threads - this might take a moment since
@@ -871,15 +845,10 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode):
       if key == curses.KEY_LEFT: page = (page - 1) % len(PAGES)
       else: page = (page + 1) % len(PAGES)
       
-      # skip connections listings if it's disabled
-      while True:
-        if page == 1 and (isBlindMode or not CONFIG["features.connection.oldPanel"]):
-          if key == curses.KEY_LEFT: page = (page - 1) % len(PAGES)
-          else: page = (page + 1) % len(PAGES)
-        elif page == 2 and (isBlindMode or not CONFIG["features.connection.newPanel"]):
-          if key == curses.KEY_LEFT: page = (page - 1) % len(PAGES)
-          else: page = (page + 1) % len(PAGES)
-        else: break
+      # skip connections listing if it's disabled
+      if page == 1 and isBlindMode:
+        if key == curses.KEY_LEFT: page = (page - 1) % len(PAGES)
+        else: page = (page + 1) % len(PAGES)
       
       # pauses panels that aren't visible to prevent events from accumilating
       # (otherwise they'll wait on the curses lock which might get demanding)
@@ -977,37 +946,11 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode):
           popup.addfstr(1, 41, "<b>down arrow</b>: scroll down a line")
           popup.addfstr(2, 2, "<b>page up</b>: scroll up a page")
           popup.addfstr(2, 41, "<b>page down</b>: scroll down a page")
-          popup.addfstr(3, 2, "<b>enter</b>: connection details")
-          popup.addfstr(3, 41, "<b>d</b>: raw consensus descriptor")
-          
-          listingType = connPanel.LIST_LABEL[panels["conn"].listingType].lower()
-          popup.addfstr(4, 2, "<b>l</b>: listed identity (<b>%s</b>)" % listingType)
-          
-          resolverUtil = connections.getResolver("tor").overwriteResolver
-          if resolverUtil == None: resolverUtil = "auto"
-          popup.addfstr(4, 41, "<b>u</b>: resolving utility (<b>%s</b>)" % resolverUtil)
-          
-          if CONFIG["features.connection.oldPanel"]:
-            allowDnsLabel = "allow" if panels["conn"].allowDNS else "disallow"
-          else: allowDnsLabel = "disallow"
-          popup.addfstr(5, 2, "<b>r</b>: permit DNS resolution (<b>%s</b>)" % allowDnsLabel)
-          
-          popup.addfstr(5, 41, "<b>s</b>: sort ordering")
-          popup.addfstr(6, 2, "<b>c</b>: client circuits")
-          
-          #popup.addfstr(5, 41, "c: toggle cursor (<b>%s</b>)" % ("on" if panels["conn"].isCursorEnabled else "off"))
-          
-          pageOverrideKeys = (ord('d'), ord('l'), ord('s'), ord('c'))
-        elif page == 2:
-          popup.addfstr(1, 2, "<b>up arrow</b>: scroll up a line")
-          popup.addfstr(1, 41, "<b>down arrow</b>: scroll down a line")
-          popup.addfstr(2, 2, "<b>page up</b>: scroll up a page")
-          popup.addfstr(2, 41, "<b>page down</b>: scroll down a page")
           
           popup.addfstr(3, 2, "<b>enter</b>: edit configuration option")
           popup.addfstr(3, 41, "<b>d</b>: raw consensus descriptor")
           
-          listingType = panels["conn2"]._listingType.lower()
+          listingType = panels["conn"]._listingType.lower()
           popup.addfstr(4, 2, "<b>l</b>: listed identity (<b>%s</b>)" % listingType)
           
           popup.addfstr(4, 41, "<b>s</b>: sort ordering")
@@ -1017,7 +960,7 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode):
           popup.addfstr(5, 2, "<b>u</b>: resolving utility (<b>%s</b>)" % resolverUtil)
           
           pageOverrideKeys = (ord('d'), ord('l'), ord('s'), ord('u'))
-        elif page == 3:
+        elif page == 2:
           popup.addfstr(1, 2, "<b>up arrow</b>: scroll up a line")
           popup.addfstr(1, 41, "<b>down arrow</b>: scroll down a line")
           popup.addfstr(2, 2, "<b>page up</b>: scroll up a page")
@@ -1031,7 +974,7 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode):
           
           popup.addfstr(4, 2, "<b>r</b>: reload torrc")
           popup.addfstr(4, 41, "<b>x</b>: reset tor (issue sighup)")
-        elif page == 4:
+        elif page == 3:
           popup.addfstr(1, 2, "<b>up arrow</b>: scroll up a line")
           popup.addfstr(1, 41, "<b>down arrow</b>: scroll down a line")
           popup.addfstr(2, 2, "<b>page up</b>: scroll up a page")
@@ -1292,220 +1235,7 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode):
         setPauseState(panels, isPaused, page)
       finally:
         panel.CURSES_LOCK.release()
-    elif CONFIG["features.connection.oldPanel"] and key == 27 and panels["conn"].listingType == connPanel.LIST_HOSTNAME and panels["control"].resolvingCounter != -1:
-      # canceling hostname resolution (esc on any page)
-      panels["conn"].listingType = connPanel.LIST_IP
-      panels["control"].resolvingCounter = -1
-      hostnames.setPaused(True)
-      panels["conn"].sortConnections()
-    elif page == 1 and panels["conn"].isCursorEnabled and uiTools.isSelectionKey(key):
-      # TODO: deprecated when migrated to the new connection panel, thought as
-      # well keep around until there's a counterpart for hostname fetching
-      
-      # provides details on selected connection
-      panel.CURSES_LOCK.acquire()
-      try:
-        setPauseState(panels, isPaused, page, True)
-        popup = panels["popup"]
-        
-        # reconfigures connection panel to accomidate details dialog
-        panels["conn"].showLabel = False
-        panels["conn"].showingDetails = True
-        panels["conn"].redraw(True)
-        
-        hostnames.setPaused(not panels["conn"].allowDNS)
-        relayLookupCache = {} # temporary cache of entry -> (ns data, desc data)
-        
-        curses.cbreak() # wait indefinitely for key presses (no timeout)
-        key = 0
-        
-        while not uiTools.isSelectionKey(key):
-          popup.clear()
-          popup.win.box()
-          popup.addstr(0, 0, "Connection Details:", curses.A_STANDOUT)
-          
-          selection = panels["conn"].cursorSelection
-          if not selection or not panels["conn"].connections: break
-          selectionColor = connPanel.TYPE_COLORS[selection[connPanel.CONN_TYPE]]
-          format = uiTools.getColor(selectionColor) | curses.A_BOLD
-          
-          selectedIp = selection[connPanel.CONN_F_IP]
-          selectedPort = selection[connPanel.CONN_F_PORT]
-          selectedIsPrivate = selection[connPanel.CONN_PRIVATE]
-          
-          addrLabel = "address: %s:%s" % (selectedIp, selectedPort)
-          
-          if selection[connPanel.CONN_TYPE] == "family" and int(selection[connPanel.CONN_L_PORT]) > 65535:
-            # unresolved family entry - unknown ip/port
-            addrLabel = "address: unknown"
-          
-          if selectedIsPrivate: hostname = None
-          else:
-            try: hostname = hostnames.resolve(selectedIp)
-            except ValueError: hostname = "unknown" # hostname couldn't be resolved
-          
-          if hostname == None:
-            if hostnames.isPaused() or selectedIsPrivate: hostname = "DNS resolution disallowed"
-            else:
-              # if hostname is still being resolved refresh panel every half-second until it's completed
-              curses.halfdelay(5)
-              hostname = "resolving..."
-          elif len(hostname) > 73 - len(addrLabel):
-            # hostname too long - truncate
-            hostname = "%s..." % hostname[:70 - len(addrLabel)]
-          
-          if selectedIsPrivate:
-            popup.addstr(1, 2, "address: <scrubbed> (unknown)", format)
-            popup.addstr(2, 2, "locale: ??", format)
-            popup.addstr(3, 2, "No consensus data found", format)
-          else:
-            popup.addstr(1, 2, "%s (%s)" % (addrLabel, hostname), format)
-            
-            locale = selection[connPanel.CONN_COUNTRY]
-            popup.addstr(2, 2, "locale: %s" % locale, format)
-            
-            # provides consensus data for selection (needs fingerprint to get anywhere...)
-            fingerprint = panels["conn"].getFingerprint(selectedIp, selectedPort)
-            
-            if fingerprint == "UNKNOWN":
-              if selectedIp not in panels["conn"].fingerprintMappings.keys():
-                # no consensus entry for this ip address
-                popup.addstr(3, 2, "No consensus data found", format)
-              else:
-                # couldn't resolve due to multiple matches - list them all
-                popup.addstr(3, 2, "Muliple matches, possible fingerprints are:", format)
-                matchings = panels["conn"].fingerprintMappings[selectedIp]
-                
-                line = 4
-                for (matchPort, matchFingerprint, matchNickname) in matchings:
-                  popup.addstr(line, 2, "%i. or port: %-5s fingerprint: %s" % (line - 3, matchPort, matchFingerprint), format)
-                  line += 1
-                  
-                  if line == 7 and len(matchings) > 4:
-                    popup.addstr(8, 2, "... %i more" % len(matchings) - 3, format)
-                    break
-            else:
-              # fingerprint found - retrieve related data
-              lookupErrored = False
-              if selection in relayLookupCache.keys(): nsEntry, descEntry = relayLookupCache[selection]
-              else:
-                try:
-                  nsCall = conn.get_network_status("id/%s" % fingerprint)
-                  if len(nsCall) == 0: raise TorCtl.ErrorReply() # no results provided
-                except (socket.error, TorCtl.ErrorReply, TorCtl.TorCtlClosed):
-                  # ns lookup fails or provides empty results - can happen with
-                  # localhost lookups if relay's having problems (orport not
-                  # reachable) and this will be empty if network consensus
-                  # couldn't be fetched
-                  lookupErrored = True
-                
-                if not lookupErrored and nsCall:
-                  if len(nsCall) > 1:
-                    # multiple records for fingerprint (shouldn't happen)
-                    log.log(log.WARN, "Multiple consensus entries for fingerprint: %s" % fingerprint)
-                  
-                  nsEntry = nsCall[0]
-                  
-                  try:
-                    descLookupCmd = "desc/id/%s" % fingerprint
-                    descEntry = TorCtl.Router.build_from_desc(conn.get_info(descLookupCmd)[descLookupCmd].split("\n"), nsEntry)
-                    relayLookupCache[selection] = (nsEntry, descEntry)
-                  except (socket.error, TorCtl.ErrorReply, TorCtl.TorCtlClosed): lookupErrored = True # desc lookup failed
-              
-              if lookupErrored:
-                popup.addstr(3, 2, "Unable to retrieve consensus data", format)
-              else:
-                popup.addstr(2, 15, "fingerprint: %s" % fingerprint, format)
-                
-                nickname = panels["conn"].getNickname(selectedIp, selectedPort)
-                dirPortLabel = "dirport: %i" % nsEntry.dirport if nsEntry.dirport else ""
-                popup.addstr(3, 2, "nickname: %-25s orport: %-10i %s" % (nickname, nsEntry.orport, dirPortLabel), format)
-                
-                popup.addstr(4, 2, "published: %-24s os: %-14s version: %s" % (descEntry.published, descEntry.os, descEntry.version), format)
-                popup.addstr(5, 2, "flags: %s" % ", ".join(nsEntry.flags), format)
-                
-                exitLine = ", ".join([str(k) for k in descEntry.exitpolicy])
-                if len(exitLine) > 63: exitLine = "%s..." % exitLine[:60]
-                popup.addstr(6, 2, "exit policy: %s" % exitLine, format)
-                
-                if descEntry.contact:
-                  # clears up some common obscuring
-                  contactAddr = descEntry.contact
-                  obscuring = [(" at ", "@"), (" AT ", "@"), ("AT", "@"), (" dot ", "."), (" DOT ", ".")]
-                  for match, replace in obscuring: contactAddr = contactAddr.replace(match, replace)
-                  if len(contactAddr) > 67: contactAddr = "%s..." % contactAddr[:64]
-                  popup.addstr(7, 2, "contact: %s" % contactAddr, format)
-            
-          popup.refresh()
-          key = stdscr.getch()
-          
-          if key == curses.KEY_RIGHT: key = curses.KEY_DOWN
-          elif key == curses.KEY_LEFT: key = curses.KEY_UP
-          
-          if key in (curses.KEY_DOWN, curses.KEY_UP, curses.KEY_PPAGE, curses.KEY_NPAGE):
-            panels["conn"].handleKey(key)
-          elif key in (ord('d'), ord('D')):
-            descriptorPopup.showDescriptorPopup(panels["popup"], stdscr, panels["conn"])
-            panels["conn"].redraw(True)
-        
-        panels["conn"].showLabel = True
-        panels["conn"].showingDetails = False
-        hostnames.setPaused(not panels["conn"].allowDNS and panels["conn"].listingType == connPanel.LIST_HOSTNAME)
-        setPauseState(panels, isPaused, page)
-        curses.halfdelay(REFRESH_RATE * 10) # reset normal pausing behavior
-      finally:
-        panel.CURSES_LOCK.release()
-    elif page == 1 and panels["conn"].isCursorEnabled and key in (ord('d'), ord('D')):
-      # presents popup for raw consensus data
-      panel.CURSES_LOCK.acquire()
-      try:
-        setPauseState(panels, isPaused, page, True)
-        curses.cbreak() # wait indefinitely for key presses (no timeout)
-        panels["conn"].showLabel = False
-        panels["conn"].redraw(True)
-        
-        descriptorPopup.showDescriptorPopup(panels["popup"], stdscr, panels["conn"])
-        
-        setPauseState(panels, isPaused, page)
-        curses.halfdelay(REFRESH_RATE * 10) # reset normal pausing behavior
-        panels["conn"].showLabel = True
-      finally:
-        panel.CURSES_LOCK.release()
-    elif page == 1 and (key == ord('l') or key == ord('L')):
-      # provides menu to pick identification info listed for connections
-      optionTypes = [connPanel.LIST_IP, connPanel.LIST_HOSTNAME, connPanel.LIST_FINGERPRINT, connPanel.LIST_NICKNAME]
-      options = [connPanel.LIST_LABEL[sortType] for sortType in optionTypes]
-      initialSelection = panels["conn"].listingType   # enums correspond to index
-      
-      # hides top label of conn panel and pauses panels
-      panels["conn"].showLabel = False
-      panels["conn"].redraw(True)
-      setPauseState(panels, isPaused, page, True)
-      
-      selection = showMenu(stdscr, panels["popup"], "List By:", options, initialSelection)
-      
-      # reverts changes made for popup
-      panels["conn"].showLabel = True
-      setPauseState(panels, isPaused, page)
-      
-      # applies new setting
-      if selection != -1 and optionTypes[selection] != panels["conn"].listingType:
-        panels["conn"].listingType = optionTypes[selection]
-        
-        if panels["conn"].listingType == connPanel.LIST_HOSTNAME:
-          curses.halfdelay(10) # refreshes display every second until done resolving
-          panels["control"].resolvingCounter = hostnames.getRequestCount() - hostnames.getPendingCount()
-          
-          hostnames.setPaused(not panels["conn"].allowDNS)
-          for connEntry in panels["conn"].connections:
-            try: hostnames.resolve(connEntry[connPanel.CONN_F_IP])
-            except ValueError: pass
-        else:
-          panels["control"].resolvingCounter = -1
-          hostnames.setPaused(True)
-        
-        panels["conn"].sortConnections()
-    elif page in (1, 2) and (key == ord('u') or key == ord('U')):
+    elif page == 1 and (key == ord('u') or key == ord('U')):
       # provides menu to pick identification resolving utility
       options = ["auto"] + connections.Resolver.values()
       
@@ -1514,7 +1244,8 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode):
       else: initialSelection = options.index(currentOverwrite)
       
       # hides top label of conn panel and pauses panels
-      panels["conn"].showLabel = False
+      panelTitle = panels["conn"]._title
+      panels["conn"]._title = ""
       panels["conn"].redraw(True)
       setPauseState(panels, isPaused, page, True)
       
@@ -1522,133 +1253,67 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode):
       selectedOption = options[selection] if selection != "auto" else None
       
       # reverts changes made for popup
-      panels["conn"].showLabel = True
+      panels["conn"]._title = panelTitle
       setPauseState(panels, isPaused, page)
       
       # applies new setting
       if selection != -1 and selectedOption != connections.getResolver("tor").overwriteResolver:
         connections.getResolver("tor").overwriteResolver = selectedOption
-    elif page == 1 and (key == ord('s') or key == ord('S')):
-      # set ordering for connection listing
-      titleLabel = "Connection Ordering:"
-      options = [connPanel.getSortLabel(i) for i in range(9)]
-      oldSelection = [connPanel.getSortLabel(entry) for entry in panels["conn"].sortOrdering]
-      optionColors = dict([connPanel.getSortLabel(i, True) for i in range(9)])
-      results = showSortDialog(stdscr, panels, isPaused, page, titleLabel, options, oldSelection, optionColors)
-      
-      if results:
-        # converts labels back to enums
-        resultEnums = [connPanel.getSortType(entry) for entry in results]
-        panels["conn"].sortOrdering = resultEnums
-        panels["conn"].sortConnections()
-      
-      # TODO: not necessary until the connection panel rewrite
-      #panels["conn"].redraw(True)
-    elif page == 1 and (key == ord('c') or key == ord('C')):
-      # displays popup with client circuits
-      clientCircuits = None
-      try:
-        clientCircuits = conn.get_info("circuit-status")["circuit-status"].split("\n")
-      except (socket.error, TorCtl.ErrorReply, TorCtl.TorCtlClosed): pass
-      
-      maxEntryLength = 0
-      if clientCircuits:
-        for clientEntry in clientCircuits: maxEntryLength = max(len(clientEntry), maxEntryLength)
-      
-      panel.CURSES_LOCK.acquire()
-      try:
-        setPauseState(panels, isPaused, page, True)
-        
-        # makes sure there's room for the longest entry
-        popup = panels["popup"]
-        if clientCircuits and maxEntryLength + 4 > popup.getPreferredSize()[1]:
-          popup.height = max(popup.height, len(clientCircuits) + 3)
-          popup.recreate(stdscr, maxEntryLength + 4)
-        
-        # lists commands
-        popup.clear()
-        popup.win.box()
-        popup.addstr(0, 0, "Client Circuits:", curses.A_STANDOUT)
-        
-        if clientCircuits == None:
-          popup.addstr(1, 2, "Unable to retireve current circuits")
-        elif len(clientCircuits) == 1 and clientCircuits[0] == "":
-          popup.addstr(1, 2, "No active client circuits")
-        else:
-          line = 1
-          for clientEntry in clientCircuits:
-            popup.addstr(line, 2, clientEntry)
-            line += 1
-            
-        popup.addstr(popup.height - 2, 2, "Press any key...")
-        popup.refresh()
-        
-        curses.cbreak()
-        stdscr.getch()
-        curses.halfdelay(REFRESH_RATE * 10)
-        
-        # reverts popup dimensions
-        popup.height = 9
-        popup.recreate(stdscr, 80)
-        
-        setPauseState(panels, isPaused, page)
-      finally:
-        panel.CURSES_LOCK.release()
-    elif page == 2 and key in (ord('d'), ord('D')):
+    elif page == 1 and key in (ord('d'), ord('D')):
       # presents popup for raw consensus data
       panel.CURSES_LOCK.acquire()
       try:
         setPauseState(panels, isPaused, page, True)
         curses.cbreak() # wait indefinitely for key presses (no timeout)
-        panelTitle = panels["conn2"]._title
-        panels["conn2"]._title = ""
-        panels["conn2"].redraw(True)
+        panelTitle = panels["conn"]._title
+        panels["conn"]._title = ""
+        panels["conn"].redraw(True)
         
-        descriptorPopup.showDescriptorPopup(panels["popup"], stdscr, panels["conn2"], True)
+        descriptorPopup.showDescriptorPopup(panels["popup"], stdscr, panels["conn"])
         
-        panels["conn2"]._title = panelTitle
+        panels["conn"]._title = panelTitle
         setPauseState(panels, isPaused, page)
         curses.halfdelay(REFRESH_RATE * 10) # reset normal pausing behavior
       finally:
         panel.CURSES_LOCK.release()
-    elif page == 2 and (key == ord('l') or key == ord('L')):
+    elif page == 1 and (key == ord('l') or key == ord('L')):
       # provides a menu to pick the primary information we list connections by
       options = interface.connections.entries.ListingType.values()
       
       # dropping the HOSTNAME listing type until we support displaying that content
       options.remove(interface.connections.entries.ListingType.HOSTNAME)
       
-      initialSelection = options.index(panels["conn2"]._listingType)
+      initialSelection = options.index(panels["conn"]._listingType)
       
       # hides top label of connection panel and pauses the display
-      panelTitle = panels["conn2"]._title
-      panels["conn2"]._title = ""
-      panels["conn2"].redraw(True)
+      panelTitle = panels["conn"]._title
+      panels["conn"]._title = ""
+      panels["conn"].redraw(True)
       setPauseState(panels, isPaused, page, True)
       
       selection = showMenu(stdscr, panels["popup"], "List By:", options, initialSelection)
       
       # reverts changes made for popup
-      panels["conn2"]._title = panelTitle
+      panels["conn"]._title = panelTitle
       setPauseState(panels, isPaused, page)
       
       # applies new setting
-      if selection != -1 and options[selection] != panels["conn2"]._listingType:
-        panels["conn2"].setListingType(options[selection])
-        panels["conn2"].redraw(True)
-    elif page == 2 and (key == ord('s') or key == ord('S')):
+      if selection != -1 and options[selection] != panels["conn"]._listingType:
+        panels["conn"].setListingType(options[selection])
+        panels["conn"].redraw(True)
+    elif page == 1 and (key == ord('s') or key == ord('S')):
       # set ordering for connection options
       titleLabel = "Connection Ordering:"
       options = interface.connections.entries.SortAttr.values()
-      oldSelection = panels["conn2"]._sortOrdering
+      oldSelection = panels["conn"]._sortOrdering
       optionColors = dict([(attr, interface.connections.entries.SORT_COLORS[attr]) for attr in options])
       results = showSortDialog(stdscr, panels, isPaused, page, titleLabel, options, oldSelection, optionColors)
       
       if results:
-        panels["conn2"].setSortOrder(results)
+        panels["conn"].setSortOrder(results)
       
-      panels["conn2"].redraw(True)
-    elif page == 3 and (key == ord('c') or key == ord('C')) and False:
+      panels["conn"].redraw(True)
+    elif page == 2 and (key == ord('c') or key == ord('C')) and False:
       # TODO: disabled for now (probably gonna be going with separate pages
       # rather than popup menu)
       # provides menu to pick config being displayed
@@ -1671,7 +1336,7 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode):
       if selection != -1: panels["torrc"].setConfigType(selection)
       
       selectiveRefresh(panels, page)
-    elif page == 3 and (key == ord('w') or key == ord('W')):
+    elif page == 2 and (key == ord('w') or key == ord('W')):
       # display a popup for saving the current configuration
       panel.CURSES_LOCK.acquire()
       try:
@@ -1800,7 +1465,7 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode):
         panel.CURSES_LOCK.release()
       
       panels["config"].redraw(True)
-    elif page == 3 and (key == ord('s') or key == ord('S')):
+    elif page == 2 and (key == ord('s') or key == ord('S')):
       # set ordering for config options
       titleLabel = "Config Option Ordering:"
       options = [configPanel.FIELD_ATTR[field][0] for field in configPanel.Field.values()]
@@ -1821,7 +1486,7 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode):
         panels["config"].setSortOrder(resultEnums)
       
       panels["config"].redraw(True)
-    elif page == 3 and uiTools.isSelectionKey(key):
+    elif page == 2 and uiTools.isSelectionKey(key):
       # let the user edit the configuration value, unchanged if left blank
       panel.CURSES_LOCK.acquire()
       try:
@@ -1877,7 +1542,7 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode):
         setPauseState(panels, isPaused, page)
       finally:
         panel.CURSES_LOCK.release()
-    elif page == 4 and key == ord('r') or key == ord('R'):
+    elif page == 3 and key == ord('r') or key == ord('R'):
       # reloads torrc, providing a notice if successful or not
       loadedTorrc = torConfig.getTorrc()
       loadedTorrc.getLock().acquire()
@@ -1907,10 +1572,8 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode):
     elif page == 1:
       panels["conn"].handleKey(key)
     elif page == 2:
-      panels["conn2"].handleKey(key)
-    elif page == 3:
       panels["config"].handleKey(key)
-    elif page == 4:
+    elif page == 3:
       panels["torrc"].handleKey(key)
 
 def startTorMonitor(startTime, loggedEvents, isBlindMode):
diff --git a/src/interface/descriptorPopup.py b/src/interface/descriptorPopup.py
index 7d51ee5..cdc959d 100644
--- a/src/interface/descriptorPopup.py
+++ b/src/interface/descriptorPopup.py
@@ -8,7 +8,6 @@ import curses
 from TorCtl import TorCtl
 
 import controller
-import connPanel
 import connections.connEntry
 from util import panel, torTools, uiTools
 
@@ -69,7 +68,7 @@ class PopupProperties:
     elif key == curses.KEY_PPAGE: self.scroll = max(self.scroll - height, 0)
     elif key == curses.KEY_NPAGE: self.scroll = max(0, min(self.scroll + height, len(self.text) - height))
 
-def showDescriptorPopup(popup, stdscr, connectionPanel, isNewPanel=False):
+def showDescriptorPopup(popup, stdscr, connectionPanel):
   """
   Presents consensus descriptor in popup window with the following controls:
   Up, Down, Page Up, Page Down - scroll descriptor
@@ -83,18 +82,11 @@ def showDescriptorPopup(popup, stdscr, connectionPanel, isNewPanel=False):
   if not panel.CURSES_LOCK.acquire(False): return
   try:
     while isVisible:
-      if isNewPanel:
-        selection = connectionPanel._scroller.getCursorSelection(connectionPanel._entryLines)
-        if not selection: break
-        fingerprint = selection.foreign.getFingerprint()
-        entryColor = connections.connEntry.CATEGORY_COLOR[selection.getType()]
-        properties.reset(fingerprint, entryColor)
-      else:
-        selection = connectionPanel.cursorSelection
-        if not selection or not connectionPanel.connections: break
-        fingerprint = connectionPanel.getFingerprint(selection[connPanel.CONN_F_IP], selection[connPanel.CONN_F_PORT])
-        entryColor = connPanel.TYPE_COLORS[selection[connPanel.CONN_TYPE]]
-        properties.reset(fingerprint, entryColor)
+      selection = connectionPanel._scroller.getCursorSelection(connectionPanel._entryLines)
+      if not selection: break
+      fingerprint = selection.foreign.getFingerprint()
+      entryColor = connections.connEntry.CATEGORY_COLOR[selection.getType()]
+      properties.reset(fingerprint, entryColor)
       
       # constrains popup size to match text
       width, height = 0, 0





More information about the tor-commits mailing list