BF: Tags not fully recursively substituted

Note: recursive check ignored for "matches", as tags would be escaped,
and hence shouldn't match "<%s>" as "<ip>" would become "\<ip\>". This
therefore maintains advantage of delayed call for {ip,jail,}matches.

Fixes gh-713
pull/715/merge^2
Steven Hiscocks 2014-05-03 14:28:13 +01:00
parent b486014b35
commit b3266ba44d
2 changed files with 19 additions and 5 deletions

View File

@ -371,8 +371,11 @@ class CommandAction(ActionBase):
within the values recursively replaced.
"""
t = re.compile(r'<([^ >]+)>')
for tag, value in tags.iteritems():
value = str(value)
for tag in tags.iterkeys():
if tag.endswith('matches'):
# Escapped so wont match
continue
value = str(tags[tag])
m = t.search(value)
done = []
#logSys.log(5, 'TAG: %s, value: %s' % (tag, value))
@ -383,6 +386,9 @@ class CommandAction(ActionBase):
# recursive definitions are bad
#logSys.log(5, 'recursion fail tag: %s value: %s' % (tag, value) )
return False
elif found_tag.endswith('matches'):
# Escapped so wont match
continue
else:
if tags.has_key(found_tag):
value = value.replace('<%s>' % found_tag , tags[found_tag])
@ -441,6 +447,7 @@ class CommandAction(ActionBase):
`query` string with tags replaced.
"""
string = query
aInfo = cls.substituteRecursiveTags(aInfo)
for tag in aInfo:
if "<%s>" % tag in query:
value = str(aInfo[tag]) # assure string

View File

@ -100,17 +100,24 @@ class CommandActionTest(LogCaptureTestCase):
{'ipjailmatches': "some >char< should \< be[ escap}ed&\n"}),
"some \\>char\\< should \\\\\\< be\\[ escap\\}ed\\&\n")
# Recursive
aInfo["ABC"] = "<xyz>"
self.assertEqual(
self.__action.replaceTag("Text <xyz> text <ABC> ABC", aInfo),
"Text 890 text 890 ABC")
# Callable
self.assertEqual(
self.__action.replaceTag("09 <callme> 11",
CallingMap(callme=lambda: str(10))),
self.__action.replaceTag("09 <matches> 11",
CallingMap(matches=lambda: str(10))),
"09 10 11")
# As tag not present, therefore callable should not be called
# Will raise ValueError if it is
self.assertEqual(
self.__action.replaceTag("abc",
CallingMap(callme=lambda: int("a"))), "abc")
CallingMap(matches=lambda: int("a"))), "abc")
def testExecuteActionBan(self):
self.__action.actionstart = "touch /tmp/fail2ban.test"