diff options
author | W. Trevor King <wking@drexel.edu> | 2009-12-14 07:37:51 -0500 |
---|---|---|
committer | W. Trevor King <wking@drexel.edu> | 2009-12-14 07:37:51 -0500 |
commit | 19fe0817ba7c2cd04caea3adfa82d4490288a548 (patch) | |
tree | 6291cac9b9861f1009d63a419c3e79879f356bc8 /libbe/command/base.py | |
parent | 2f0ceedba5b6619faf476cd1aa67e826e91d5c7c (diff) | |
download | bugseverywhere-19fe0817ba7c2cd04caea3adfa82d4490288a548.tar.gz |
Transitioned comment to Command format
Diffstat (limited to 'libbe/command/base.py')
-rw-r--r-- | libbe/command/base.py | 105 |
1 files changed, 81 insertions, 24 deletions
diff --git a/libbe/command/base.py b/libbe/command/base.py index b27e188..e28cf33 100644 --- a/libbe/command/base.py +++ b/libbe/command/base.py @@ -2,6 +2,7 @@ import codecs import optparse +import os.path import sys import libbe @@ -9,7 +10,6 @@ import libbe.ui.util.user import libbe.util.encoding import libbe.util.plugin - class UserError(Exception): pass @@ -90,34 +90,55 @@ class Option (CommandInput): def __repr__(self): return '<Option %s>' % self.__str__() -class _DummyParser (object): - def __init__(self, options): - self.option_list = options - self.option_groups = [] - for option in self.option_list: # add required methods and attributes - option.dest = option.name - option._short_opts = [] - if option.short_name != None: - option._short_opts.append('-' + option.short_name) - option._long_opts = ['--' + option.name] - option.takes_value = lambda : option.arg != None - if option.takes_value(): - option.metavar = option.arg.metavar - else: - option.metavar = None +class _DummyParser (optparse.OptionParser): + def __init__(self, command): + optparse.OptionParser.__init__(self) + self.remove_option('-h') + self.command = command + self._command_opts = [] + for option in self.command.options: + self._add_option(option) + + def _add_option(self, option): + # from libbe.ui.command_line.CmdOptionParser._add_option + option.validate() + long_opt = '--%s' % option.name + if option.short_name != None: + short_opt = '-%s' % option.short_name + assert '_' not in option.name, \ + 'Non-reconstructable option name %s' % option.name + kwargs = {'dest':option.name.replace('-', '_'), + 'help':option.help} + if option.arg == None or option.arg.type == 'bool': + kwargs['action'] = 'store_true' + kwargs['metavar'] = None + kwargs['default'] = False + else: + kwargs['type'] = option.arg.type + kwargs['action'] = 'store' + kwargs['metavar'] = option.arg.metavar + kwargs['default'] = option.arg.default + if option.short_name != None: + opt = optparse.Option(short_opt, long_opt, **kwargs) + else: + opt = optparse.Option(long_opt, **kwargs) + #option.takes_value = lambda : option.arg != None + opt._option = option + self._command_opts.append(opt) + self.add_option(opt) class OptionFormatter (optparse.IndentedHelpFormatter): - def __init__(self, options): + def __init__(self, command): optparse.IndentedHelpFormatter.__init__(self) - self.options = options + self.command = command def option_help(self): # based on optparse.OptionParser.format_option_help() - parser = _DummyParser(self.options) + parser = _DummyParser(self.command) self.store_option_strings(parser) ret = [] ret.append(self.format_heading('Options')) self.indent() - for option in self.options: + for option in parser._command_opts: ret.append(self.format_option(option)) ret.append('\n') self.dedent() @@ -132,11 +153,11 @@ class Command (object): usage: be command [options] <BLANKLINE> Options: - -h HELP, --help=HELP Print a help message. + -h, --help Print a help message. <BLANKLINE> - --complete=STRING Print a list of possible completions. + --complete Print a list of possible completions. <BLANKLINE> - A detailed help message. + A detailed help message. """ name = 'command' @@ -145,7 +166,9 @@ class Command (object): self.status = None self.result = None self.requires_bugdir = False + self.requires_storage = False self.requires_unconnected_storage = False + self.restrict_file_access = True self.input_encoding = None self.output_encoding = None self.options = [ @@ -250,7 +273,7 @@ class Command (object): return usage def _option_help(self): - o = OptionFormatter(self.options) + o = OptionFormatter(self) return o.option_help().strip('\n') def _long_help(self): @@ -266,3 +289,37 @@ class Command (object): # finish a particular argument return argument.completion_callback(self, argument, fragment) return [] # the particular argument doesn't supply completion info + + def check_restricted_access(self, storage, path): + """ + Check that the file at path is inside bugdir.root. This is + important if you allow other users to execute becommands with + your username (e.g. if you're running be-handle-mail through + your ~/.procmailrc). If this check wasn't made, a user could + e.g. run + be commit -b ~/.ssh/id_rsa "Hack to expose ssh key" + which would expose your ssh key to anyone who could read the + VCS log. + + >>> class DummyStorage (object): pass + >>> s = DummyStorage() + >>> s.repo = os.path.expanduser('~/x/') + >>> c = Command() + >>> try: + ... c.check_restricted_access(s, os.path.expanduser('~/.ssh/id_rsa')) + ... except UserError, e: + ... assert str(e).startswith('file access restricted!'), str(e) + ... print 'we got the expected error' + we got the expected error + >>> c.check_restricted_access(s, os.path.expanduser('~/x')) + >>> c.check_restricted_access(s, os.path.expanduser('~/x/y')) + >>> c.restrict_file_access = False + >>> c.check_restricted_access(s, os.path.expanduser('~/.ssh/id_rsa')) + """ + if self.restrict_file_access == True: + path = os.path.abspath(path) + repo = os.path.abspath(storage.repo).rstrip(os.path.sep) + if path == repo or path.startswith(repo+os.path.sep): + return + raise UserError('file access restricted!\n %s not in %s' + % (path, repo)) |