cherry-pick newer version of extractOptions, in order to avoid large discrepancy between 0.10 and 0.9 config-parsers:

allow to use dual parameter lists (coming through substitutions), e. g.: `name[p1=0, p2="..."][p3='...']`;
simplified explanation: `][` treats as `,` in new version.
cherry-picked from 0.10.
pull/1908/head
sebres 2018-01-10 10:55:19 +01:00
parent 82f8bd8639
commit 3d9a112c8f
2 changed files with 33 additions and 23 deletions

View File

@ -27,14 +27,13 @@ __license__ = "GPL"
import glob import glob
import json import json
import os.path import os.path
import re
from .configreader import ConfigReaderUnshared, ConfigReader from .configreader import ConfigReaderUnshared, ConfigReader
from .filterreader import FilterReader from .filterreader import FilterReader
from .actionreader import ActionReader from .actionreader import ActionReader
from ..version import version from ..version import version
from ..helpers import getLogger from ..helpers import getLogger
from ..helpers import splitwords from ..helpers import extractOptions, splitwords
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = getLogger(__name__) logSys = getLogger(__name__)
@ -42,10 +41,6 @@ logSys = getLogger(__name__)
class JailReader(ConfigReader): class JailReader(ConfigReader):
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)
self.__name = name self.__name = name
@ -121,7 +116,7 @@ class JailReader(ConfigReader):
if self.isEnabled(): if self.isEnabled():
# Read filter # Read filter
if self.__opts["filter"]: if self.__opts["filter"]:
filterName, filterOpt = JailReader.extractOptions( filterName, filterOpt = extractOptions(
self.__opts["filter"]) self.__opts["filter"])
self.__filter = FilterReader( self.__filter = FilterReader(
filterName, self.__name, filterOpt, share_config=self.share_config, basedir=self.getBaseDir()) filterName, self.__name, filterOpt, share_config=self.share_config, basedir=self.getBaseDir())
@ -150,7 +145,7 @@ class JailReader(ConfigReader):
try: try:
if not act: # skip empty actions if not act: # skip empty actions
continue continue
actName, actOpt = JailReader.extractOptions(act) actName, actOpt = extractOptions(act)
if actName.endswith(".py"): if actName.endswith(".py"):
self.__actions.append([ self.__actions.append([
"set", "set",
@ -244,18 +239,4 @@ class JailReader(ConfigReader):
stream.insert(0, ["add", self.__name, backend]) stream.insert(0, ["add", self.__name, backend])
return stream return stream
@staticmethod JailReader.extractOptions = staticmethod(extractOptions)
def extractOptions(option):
match = JailReader.optionCRE.match(option)
if not match:
# TODO proper error handling
return None, None
option_name, optstr = match.groups()
option_opts = dict()
if optstr:
for optmatch in JailReader.optionExtractRE.finditer(optstr):
opt = optmatch.group(1)
value = [
val for val in optmatch.group(2,3,4) if val is not None][0]
option_opts[opt.strip()] = value.strip()
return option_name, option_opts

View File

@ -137,3 +137,32 @@ def splitwords(s):
if not s: if not s:
return [] return []
return filter(bool, map(str.strip, re.split('[ ,\n]+', s))) return filter(bool, map(str.strip, re.split('[ ,\n]+', s)))
#
# Following function used for parse options from parameter (e.g. `name[p1=0, p2="..."][p3='...']`).
#
# regex, to extract list of options:
OPTION_CRE = re.compile(r"^([^\[]+)(?:\[(.*)\])?\s*$", re.DOTALL)
# regex, to iterate over single option in option list, syntax:
# `action = act[p1="...", p2='...', p3=...]`, where the p3=... not contains `,` or ']'
# since v0.10 separator extended with `]\s*[` for support of multiple option groups, syntax
# `action = act[p1=...][p2=...]`
OPTION_EXTRACT_CRE = re.compile(
r'([\w\-_\.]+)=(?:"([^"]*)"|\'([^\']*)\'|([^,\]]*))(?:,|\]\s*\[|$)', re.DOTALL)
def extractOptions(option):
match = OPTION_CRE.match(option)
if not match:
# TODO proper error handling
return None, None
option_name, optstr = match.groups()
option_opts = dict()
if optstr:
for optmatch in OPTION_EXTRACT_CRE.finditer(optstr):
opt = optmatch.group(1)
value = [
val for val in optmatch.group(2,3,4) if val is not None][0]
option_opts[opt.strip()] = value.strip()
return option_name, option_opts