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
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
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
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
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