Example #1
0
 def registerEvent(self, event):
   """
   Notes event and redraws log. If paused it's held in a temporary buffer.
   
   Arguments:
     event - LogEntry for the event that occurred
   """
   
   if not event.type in self.loggedEvents: return
   
   # strips control characters to avoid screwing up the terminal
   event.msg = uiTools.getPrintable(event.msg)
   
   # note event in the log file if we're saving them
   if self.logFile:
     try:
       self.logFile.write(event.getDisplayMessage(True) + "\n")
       self.logFile.flush()
     except IOError, exc:
       log.log(self._config["log.logPanel.logFileWriteFailed"], "Unable to write to log file: %s" % sysTools.getFileErrorMsg(exc))
       self.logFile = None
Example #2
0
    def getDisplayContents(self, strip=False):
        """
    Provides the contents of the configuration file, formatted in a rendering
    frindly fashion:
    - Tabs print as three spaces. Keeping them as tabs is problematic for
      layouts since it's counted as a single character, but occupies several
      cells.
    - Strips control and unprintable characters.
    
    Arguments:
      strip - removes comments and extra whitespace if true
    """

        self.valsLock.acquire()

        if not self.isLoaded(): returnVal = None
        else:
            if self.displayableContents == None:
                # restricts contents to displayable characters
                self.displayableContents = []

                for lineNum in range(len(self.contents)):
                    lineText = self.contents[lineNum]
                    lineText = lineText.replace("\t", "   ")
                    lineText = uiTools.getPrintable(lineText)
                    self.displayableContents.append(lineText)

            if strip:
                if self.strippedContents == None:
                    self.strippedContents = _stripComments(
                        self.displayableContents)

                returnVal = list(self.strippedContents)
            else:
                returnVal = list(self.displayableContents)

        self.valsLock.release()
        return returnVal
Example #3
0
 def getDisplayContents(self, strip = False):
   """
   Provides the contents of the configuration file, formatted in a rendering
   frindly fashion:
   - Tabs print as three spaces. Keeping them as tabs is problematic for
     layouts since it's counted as a single character, but occupies several
     cells.
   - Strips control and unprintable characters.
   
   Arguments:
     strip - removes comments and extra whitespace if true
   """
   
   self.valsLock.acquire()
   
   if not self.isLoaded(): returnVal = None
   else:
     if self.displayableContents == None:
       # restricts contents to displayable characters
       self.displayableContents = []
       
       for lineNum in range(len(self.contents)):
         lineText = self.contents[lineNum]
         lineText = lineText.replace("\t", "   ")
         lineText = uiTools.getPrintable(lineText)
         self.displayableContents.append(lineText)
     
     if strip:
       if self.strippedContents == None:
         self.strippedContents = _stripComments(self.displayableContents)
       
       returnVal = list(self.strippedContents)
     else: returnVal = list(self.displayableContents)
   
   self.valsLock.release()
   return returnVal
Example #4
0
    def registerEvent(self, event):
        """
    Notes event and redraws log. If paused it's held in a temporary buffer.
    
    Arguments:
      event - LogEntry for the event that occurred
    """

        if not event.type in self.loggedEvents: return

        # strips control characters to avoid screwing up the terminal
        event.msg = uiTools.getPrintable(event.msg)

        # note event in the log file if we're saving them
        if self.logFile:
            try:
                self.logFile.write(event.getDisplayMessage(True) + "\n")
                self.logFile.flush()
            except IOError, exc:
                log.log(
                    self._config["log.logPanel.logFileWriteFailed"],
                    "Unable to write to log file: %s" %
                    sysTools.getFileErrorMsg(exc))
                self.logFile = None
Example #5
0
def loadOptionDescriptions(loadPath = None):
  """
  Fetches and parses descriptions for tor's configuration options from its man
  page. This can be a somewhat lengthy call, and raises an IOError if issues
  occure.
  
  If available, this can load the configuration descriptions from a file where
  they were previously persisted to cut down on the load time (latency for this
  is around 200ms).
  
  Arguments:
    loadPath - if set, this attempts to fetch the configuration descriptions
               from the given path instead of the man page
  """
  
  CONFIG_DESCRIPTIONS_LOCK.acquire()
  CONFIG_DESCRIPTIONS.clear()
  
  raisedExc = None
  try:
    if loadPath:
      # Input file is expected to be of the form:
      # <option>
      # <arg description>
      # <description, possibly multiple lines>
      # <PERSIST_ENTRY_DIVIDER>
      inputFile = open(loadPath, "r")
      inputFileContents = inputFile.readlines()
      inputFile.close()
      
      # constructs a reverse mapping for categories
      strToCat = dict([(OPTION_CATEGORY_STR[cat], cat) for cat in OPTION_CATEGORY_STR])
      
      try:
        versionLine = inputFileContents.pop(0).rstrip()
        
        if versionLine.startswith("Tor Version "):
          fileVersion = versionLine[12:]
          torVersion = torTools.getConn().getInfo("version", "")
          if fileVersion != torVersion:
            msg = "wrong version, tor is %s but the file's from %s" % (torVersion, fileVersion)
            raise IOError(msg)
        else:
          raise IOError("unable to parse version")
        
        while inputFileContents:
          # gets category enum, failing if it doesn't exist
          categoryStr = inputFileContents.pop(0).rstrip()
          if categoryStr in strToCat:
            category = strToCat[categoryStr]
          else:
            baseMsg = "invalid category in input file: '%s'"
            raise IOError(baseMsg % categoryStr)
          
          # gets the position in the man page
          indexArg, indexStr = -1, inputFileContents.pop(0).rstrip()
          
          if indexStr.startswith("index: "):
            indexStr = indexStr[7:]
            
            if indexStr.isdigit(): indexArg = int(indexStr)
            else: raise IOError("non-numeric index value: %s" % indexStr)
          else: raise IOError("malformed index argument: %s"% indexStr)
          
          option = inputFileContents.pop(0).rstrip()
          argument = inputFileContents.pop(0).rstrip()
          
          description, loadedLine = "", inputFileContents.pop(0)
          while loadedLine != PERSIST_ENTRY_DIVIDER:
            description += loadedLine
            
            if inputFileContents: loadedLine = inputFileContents.pop(0)
            else: break
          
          CONFIG_DESCRIPTIONS[option.lower()] = ManPageEntry(indexArg, category, argument, description.rstrip())
      except IndexError:
        CONFIG_DESCRIPTIONS.clear()
        raise IOError("input file format is invalid")
    else:
      manCallResults = sysTools.call("man tor")
      
      # Fetches all options available with this tor instance. This isn't
      # vital, and the validOptions are left empty if the call fails.
      conn, validOptions = torTools.getConn(), []
      configOptionQuery = conn.getInfo("config/names").strip().split("\n")
      if configOptionQuery:
        validOptions = [line[:line.find(" ")].lower() for line in configOptionQuery]
      
      optionCount, lastOption, lastArg = 0, None, None
      lastCategory, lastDescription = GENERAL, ""
      for line in manCallResults:
        line = uiTools.getPrintable(line)
        strippedLine = line.strip()
        
        # we have content, but an indent less than an option (ignore line)
        #if strippedLine and not line.startswith(" " * MAN_OPT_INDENT): continue
        
        # line starts with an indent equivilant to a new config option
        isOptIndent = line.startswith(" " * MAN_OPT_INDENT) and line[MAN_OPT_INDENT] != " "
        
        isCategoryLine = not line.startswith(" ") and "OPTIONS" in line
        
        # if this is a category header or a new option, add an entry using the
        # buffered results
        if isOptIndent or isCategoryLine:
          # Filters the line based on if the option is recognized by tor or
          # not. This isn't necessary for arm, so if unable to make the check
          # then we skip filtering (no loss, the map will just have some extra
          # noise).
          strippedDescription = lastDescription.strip()
          if lastOption and (not validOptions or lastOption.lower() in validOptions):
            CONFIG_DESCRIPTIONS[lastOption.lower()] = ManPageEntry(optionCount, lastCategory, lastArg, strippedDescription)
            optionCount += 1
          lastDescription = ""
          
          # parses the option and argument
          line = line.strip()
          divIndex = line.find(" ")
          if divIndex != -1:
            lastOption, lastArg = line[:divIndex], line[divIndex + 1:]
          
          # if this is a category header then switch it
          if isCategoryLine:
            if line.startswith("OPTIONS"): lastCategory = GENERAL
            elif line.startswith("CLIENT"): lastCategory = CLIENT
            elif line.startswith("SERVER"): lastCategory = SERVER
            elif line.startswith("DIRECTORY SERVER"): lastCategory = DIRECTORY
            elif line.startswith("DIRECTORY AUTHORITY SERVER"): lastCategory = AUTHORITY
            elif line.startswith("HIDDEN SERVICE"): lastCategory = HIDDEN_SERVICE
            elif line.startswith("TESTING NETWORK"): lastCategory = TESTING
            else:
              msg = "Unrecognized category in the man page: %s" % line.strip()
              log.log(CONFIG["log.configDescriptions.unrecognizedCategory"], msg)
        else:
          # Appends the text to the running description. Empty lines and lines
          # starting with a specific indentation are used for formatting, for
          # instance the ExitPolicy and TestingTorNetwork entries.
          if lastDescription and lastDescription[-1] != "\n":
            lastDescription += " "
          
          if not strippedLine:
            lastDescription += "\n\n"
          elif line.startswith(" " * MAN_EX_INDENT):
            lastDescription += "    %s\n" % strippedLine
          else: lastDescription += strippedLine
  except IOError, exc:
    raisedExc = exc