From 7e2ab36d86998575853150c0a57de5e22518cf66 Mon Sep 17 00:00:00 2001
From: sebres <info@sebres.de>
Date: Tue, 21 Jun 2022 16:55:57 +0200
Subject: [PATCH] move global groups to start of expression (python 3.11
 compat)

[remove change to regex not in 0.11.2]
Signed-off-by: Jeffery To <jeffery.to@gmail.com>
---
 fail2ban/client/fail2banregex.py | 2 +-
 fail2ban/server/datetemplate.py  | 8 ++++++++
 2 files changed, 9 insertions(+), 1 deletion(-)

--- a/fail2ban/server/datetemplate.py
+++ b/fail2ban/server/datetemplate.py
@@ -35,6 +35,7 @@ logSys = getLogger(__name__)
 # check already grouped contains "(", but ignores char "\(" and conditional "(?(id)...)":
 RE_GROUPED = re.compile(r'(?<!(?:\(\?))(?<!\\)\((?!\?)')
 RE_GROUP = ( re.compile(r'^((?:\(\?\w+\))?\^?(?:\(\?\w+\))?)(.*?)(\$?)$'), r"\1(\2)\3" )
+RE_GLOBALFLAGS = re.compile(r'((?:^|(?!<\\))\(\?[a-z]+\))')
 
 RE_EXLINE_NO_BOUNDS = re.compile(r'^\{UNB\}')
 RE_EXLINE_BOUND_BEG = re.compile(r'^\{\^LN-BEG\}')
@@ -110,6 +111,11 @@ class DateTemplate(object):
 		# because it may be very slow in negative case (by long log-lines not matching pattern)
 
 		regex = regex.strip()
+		# cut global flags like (?iu) from RE in order to pre-set it after processing:
+		gf = RE_GLOBALFLAGS.search(regex)
+		if gf:
+			regex = RE_GLOBALFLAGS.sub('', regex, count=1)
+		# check word boundaries needed:
 		boundBegin = wordBegin and not RE_NO_WRD_BOUND_BEG.search(regex)
 		boundEnd = wordEnd and not RE_NO_WRD_BOUND_END.search(regex)
 		# if no group add it now, should always have a group(1):
@@ -135,6 +141,8 @@ class DateTemplate(object):
 			self.flags |= DateTemplate.LINE_END
 		# remove possible special pattern "**" in front and end of regex:
 		regex = RE_DEL_WRD_BOUNDS[0].sub(RE_DEL_WRD_BOUNDS[1], regex)
+		if gf: # restore global flags:
+			regex = gf.group(1) + regex
 		self._regex = regex
 		logSys.log(7, '  constructed regex %s', regex)
 		self._cRegex = None
