RF+BF+ENH: Rewrite extract options, and now allow "=" char in options

pull/224/head
Steven Hiscocks 2013-05-10 17:24:23 +01:00
parent 970291867b
commit 33a7763cfc
2 changed files with 15 additions and 46 deletions

View File

@ -36,6 +36,8 @@ logSys = logging.getLogger(__name__)
class JailReader(ConfigReader): class JailReader(ConfigReader):
optionCRE = re.compile("^((?:\w|-|_|\.)+)(?:\[(.*)\])?$") optionCRE = re.compile("^((?:\w|-|_|\.)+)(?:\[(.*)\])?$")
optionExtractRE = re.compile(
r'([\w\-_\.]+)=(?:"([^"]*)"|\'([^\']*)\'|([^,]*))(?:,|$)')
def __init__(self, name, force_enable=False, **kwargs): def __init__(self, name, force_enable=False, **kwargs):
ConfigReader.__init__(self, **kwargs) ConfigReader.__init__(self, **kwargs)
@ -155,46 +157,13 @@ class JailReader(ConfigReader):
#@staticmethod #@staticmethod
def extractOptions(option): def extractOptions(option):
m = JailReader.optionCRE.match(option) option_name, optstr = JailReader.optionCRE.match(option).groups()
d = dict() option_opts = dict()
mgroups = m.groups() if optstr:
if len(mgroups) == 2: for optmatch in JailReader.optionExtractRE.finditer(optstr):
option_name, option_opts = mgroups opt = optmatch.group(1)
elif len(mgroups) == 1: value = [
option_name, option_opts = mgroups[0], None val for val in optmatch.group(2,3,4) if val is not None][0]
else: option_opts[opt.strip()] = value.strip()
raise ValueError("While reading option %s we should have got up to " return option_name, option_opts
"2 groups. Got: %r" % (option, mgroups))
if not option_opts is None:
# Huge bad hack :( This method really sucks. TODO Reimplement it.
options = ""
escapeChar = None
allowComma = False
for c in option_opts:
if c in ('"', "'") and not allowComma:
# Start
escapeChar = c
allowComma = True
elif c == escapeChar:
# End
escapeChar = None
allowComma = False
else:
if c == ',' and allowComma:
options += "<COMMA>"
else:
options += c
# Split using ,
optionsSplit = options.split(',')
# Replace the tag <COMMA> with ,
optionsSplit = [n.replace("<COMMA>", ',') for n in optionsSplit]
for param in optionsSplit:
p = param.split('=')
try:
d[p[0].strip()] = p[1].strip()
except IndexError:
logSys.error("Invalid argument %s in '%s'" % (p, option_opts))
return [option_name, d]
extractOptions = staticmethod(extractOptions) extractOptions = staticmethod(extractOptions)

View File

@ -147,19 +147,19 @@ class JailReaderTest(unittest.TestCase):
def testSplitOption(self): def testSplitOption(self):
# Simple example # Simple example
option = "mail-whois[name=SSH]" option = "mail-whois[name=SSH]"
expected = ['mail-whois', {'name': 'SSH'}] expected = ('mail-whois', {'name': 'SSH'})
result = JailReader.extractOptions(option) result = JailReader.extractOptions(option)
self.assertEqual(expected, result) self.assertEqual(expected, result)
# Empty option # Empty option
option = "abc[]" option = "abc[]"
expected = ['abc', {}] expected = ('abc', {})
result = JailReader.extractOptions(option) result = JailReader.extractOptions(option)
self.assertEqual(expected, result) self.assertEqual(expected, result)
# More complex examples # More complex examples
option = 'option[opt01=abc,opt02="123",opt03="with=okay?",opt04="andwith,okay...",opt05="how about spaces",opt06="single\'in\'double",opt07=\'double"in"single\', opt08= leave some space, opt09=one for luck, opt10=, opt11=]' option = 'option[opt01=abc,opt02="123",opt03="with=okay?",opt04="andwith,okay...",opt05="how about spaces",opt06="single\'in\'double",opt07=\'double"in"single\', opt08= leave some space, opt09=one for luck, opt10=, opt11=]'
expected = ['option', { expected = ('option', {
'opt01': "abc", 'opt01': "abc",
'opt02': "123", 'opt02': "123",
'opt03': "with=okay?", 'opt03': "with=okay?",
@ -171,7 +171,7 @@ class JailReaderTest(unittest.TestCase):
'opt09': "one for luck", 'opt09': "one for luck",
'opt10': "", 'opt10': "",
'opt11': "", 'opt11': "",
}] })
result = JailReader.extractOptions(option) result = JailReader.extractOptions(option)
self.assertEqual(expected, result) self.assertEqual(expected, result)