def _general_help(): lines = [] for line in msg('help.general').splitlines(): div = line.find(' - ') if div != -1: cmd, description = line[:div], line[div:] lines.append(format(cmd, *BOLD_OUTPUT) + format(description, *STANDARD_OUTPUT)) else: lines.append(format(line, *BOLD_OUTPUT)) return '\n'.join(lines)
def run_command(self, command, config): """ Runs the given command. Requests starting with a '/' are special commands to the interpreter, and anything else is sent to the control port. :param stem.control.Controller controller: tor control connection :param str command: command to be processed :returns: **list** out output lines, each line being a list of (msg, format) tuples :raises: **stem.SocketClosed** if the control connection has been severed """ if not self._controller.is_alive(): raise stem.SocketClosed() # Commands fall into three categories: # # * Interpretor commands. These start with a '/'. # # * Controller commands stem knows how to handle. We use our Controller's # methods for these to take advantage of caching and present nicer # output. # # * Other tor commands. We pass these directly on to the control port. cmd, arg = command.strip(), '' if ' ' in cmd: cmd, arg = cmd.split(' ', 1) output = '' if cmd.startswith('/'): cmd = cmd.lower() if cmd == '/quit': raise stem.SocketClosed() elif cmd == '/events': output = self.do_events(arg) elif cmd == '/info': output = self.do_info(arg) elif cmd == '/python': output = self.do_python(arg) elif cmd == '/help': output = self.do_help(arg) else: output = format("'%s' isn't a recognized command" % command, *ERROR_OUTPUT) else: cmd = cmd.upper() # makes commands uppercase to match the spec if cmd.replace('+', '') in ('LOADCONF', 'POSTDESCRIPTOR'): # provides a notice that multi-line controller input isn't yet implemented output = format(msg('msg.multiline_unimplemented_notice'), *ERROR_OUTPUT) elif cmd == 'QUIT': self._controller.msg(command) raise stem.SocketClosed() else: is_tor_command = cmd in config.get('help.usage', {}) and cmd.lower() != 'events' if self._run_python_commands and not is_tor_command: self.is_multiline_context = code.InteractiveConsole.push(self, command) return else: try: output = format(self._controller.msg(command).raw_content().strip(), *STANDARD_OUTPUT) except stem.ControllerError as exc: if isinstance(exc, stem.SocketClosed): raise exc else: output = format(str(exc), *ERROR_OUTPUT) output += '\n' # give ourselves an extra line before the next prompt return output
def _response(controller, arg, config): if not arg: return _general_help() usage_info = config.get('help.usage', {}) if arg not in usage_info: return format("No help information available for '%s'..." % arg, *ERROR_OUTPUT) output = format(usage_info[arg] + '\n', *BOLD_OUTPUT) description = config.get('help.description.%s' % arg.lower(), '') for line in description.splitlines(): output += format(' ' + line, *STANDARD_OUTPUT) + '\n' output += '\n' if arg == 'GETINFO': results = controller.get_info('info/names', None) if results: for line in results.splitlines(): if ' -- ' in line: opt, summary = line.split(' -- ', 1) output += format('%-33s' % opt, *BOLD_OUTPUT) output += format(' - %s' % summary, * STANDARD_OUTPUT) + '\n' elif arg == 'GETCONF': results = controller.get_info('config/names', None) if results: options = [opt.split(' ', 1)[0] for opt in results.splitlines()] for i in range(0, len(options), 2): line = '' for entry in options[i:i + 2]: line += '%-42s' % entry output += format(line.rstrip(), *STANDARD_OUTPUT) + '\n' elif arg == 'SIGNAL': signal_options = config.get('help.signal.options', {}) for signal, summary in signal_options.items(): output += format('%-15s' % signal, *BOLD_OUTPUT) output += format(' - %s' % summary, *STANDARD_OUTPUT) + '\n' elif arg == 'SETEVENTS': results = controller.get_info('events/names', None) if results: entries = results.split() # displays four columns of 20 characters for i in range(0, len(entries), 4): line = '' for entry in entries[i:i + 4]: line += '%-20s' % entry output += format(line.rstrip(), *STANDARD_OUTPUT) + '\n' elif arg == 'USEFEATURE': results = controller.get_info('features/names', None) if results: output += format(results, *STANDARD_OUTPUT) + '\n' elif arg in ('LOADCONF', 'POSTDESCRIPTOR'): # gives a warning that this option isn't yet implemented output += format(msg('msg.multiline_unimplemented_notice'), * ERROR_OUTPUT) + '\n' return output.rstrip()
def _response(controller, arg, config): if not arg: return _general_help() usage_info = config.get('help.usage', {}) if arg not in usage_info: return format("No help information available for '%s'..." % arg, *ERROR_OUTPUT) output = format(usage_info[arg] + '\n', *BOLD_OUTPUT) description = config.get('help.description.%s' % arg.lower(), '') for line in description.splitlines(): output += format(' ' + line, *STANDARD_OUTPUT) + '\n' output += '\n' if arg == 'GETINFO': results = controller.get_info('info/names', None) if results: for line in results.splitlines(): if ' -- ' in line: opt, summary = line.split(' -- ', 1) output += format('%-33s' % opt, *BOLD_OUTPUT) output += format(' - %s' % summary, *STANDARD_OUTPUT) + '\n' elif arg == 'GETCONF': results = controller.get_info('config/names', None) if results: options = [opt.split(' ', 1)[0] for opt in results.splitlines()] for i in range(0, len(options), 2): line = '' for entry in options[i:i + 2]: line += '%-42s' % entry output += format(line.rstrip(), *STANDARD_OUTPUT) + '\n' elif arg == 'SIGNAL': signal_options = config.get('help.signal.options', {}) for signal, summary in signal_options.items(): output += format('%-15s' % signal, *BOLD_OUTPUT) output += format(' - %s' % summary, *STANDARD_OUTPUT) + '\n' elif arg == 'SETEVENTS': results = controller.get_info('events/names', None) if results: entries = results.split() # displays four columns of 20 characters for i in range(0, len(entries), 4): line = '' for entry in entries[i:i + 4]: line += '%-20s' % entry output += format(line.rstrip(), *STANDARD_OUTPUT) + '\n' elif arg == 'USEFEATURE': results = controller.get_info('features/names', None) if results: output += format(results, *STANDARD_OUTPUT) + '\n' elif arg in ('LOADCONF', 'POSTDESCRIPTOR'): # gives a warning that this option isn't yet implemented output += format(msg('msg.multiline_unimplemented_notice'), *ERROR_OUTPUT) + '\n' return output.rstrip()