mirror of https://github.com/fail2ban/fail2ban
- Refactoring. Reduced number of files.
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/branches/FAIL2BAN-0_8@633 a942ae1a-1317-0410-a47c-b1dcaea8d605_tent/ipv6_via_aInfo
parent
2ce608d640
commit
c07a7a6e7a
|
@ -1,3 +0,0 @@
|
||||||
#Wed Sep 20 22:14:25 GMT 2006
|
|
||||||
eclipse.preferences.version=1
|
|
||||||
encoding//server/datestrptime.py=UTF-8
|
|
|
@ -24,6 +24,7 @@ ver. 0.8.2 (2007/??/??) - stable
|
||||||
account. Thanks to Adrien Clerc
|
account. Thanks to Adrien Clerc
|
||||||
- Moved socket to /var/run/fail2ban.
|
- Moved socket to /var/run/fail2ban.
|
||||||
- Rewrote the communication server.
|
- Rewrote the communication server.
|
||||||
|
- Refactoring. Reduced number of files.
|
||||||
|
|
||||||
ver. 0.8.1 (2007/08/14) - stable
|
ver. 0.8.1 (2007/08/14) - stable
|
||||||
----------
|
----------
|
||||||
|
|
4
MANIFEST
4
MANIFEST
|
@ -23,10 +23,8 @@ server/filter.py
|
||||||
server/filtergamin.py
|
server/filtergamin.py
|
||||||
server/filterpoll.py
|
server/filterpoll.py
|
||||||
server/server.py
|
server/server.py
|
||||||
server/datestrptime.py
|
|
||||||
server/failticket.py
|
server/failticket.py
|
||||||
server/actions.py
|
server/actions.py
|
||||||
server/datetai64n.py
|
|
||||||
server/faildata.py
|
server/faildata.py
|
||||||
server/failmanager.py
|
server/failmanager.py
|
||||||
server/datedetector.py
|
server/datedetector.py
|
||||||
|
@ -37,11 +35,9 @@ server/ticket.py
|
||||||
server/jail.py
|
server/jail.py
|
||||||
server/jails.py
|
server/jails.py
|
||||||
server/__init__.py
|
server/__init__.py
|
||||||
server/dateepoch.py
|
|
||||||
server/banmanager.py
|
server/banmanager.py
|
||||||
server/datetemplate.py
|
server/datetemplate.py
|
||||||
server/mytime.py
|
server/mytime.py
|
||||||
server/regex.py
|
|
||||||
server/failregex.py
|
server/failregex.py
|
||||||
testcases/banmanagertestcase.py
|
testcases/banmanagertestcase.py
|
||||||
testcases/failmanagertestcase.py
|
testcases/failmanagertestcase.py
|
||||||
|
|
|
@ -26,9 +26,9 @@ __license__ = "GPL"
|
||||||
|
|
||||||
import time, logging
|
import time, logging
|
||||||
|
|
||||||
from datestrptime import DateStrptime
|
from datetemplate import DateStrptime
|
||||||
from datetai64n import DateTai64n
|
from datetemplate import DateTai64n
|
||||||
from dateepoch import DateEpoch
|
from datetemplate import DateEpoch
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
|
|
||||||
# Gets the instance of the logger.
|
# Gets the instance of the logger.
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
# This file is part of Fail2Ban.
|
|
||||||
#
|
|
||||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Fail2Ban is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Fail2Ban; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
# Author: Cyril Jaquier
|
|
||||||
#
|
|
||||||
# $Revision$
|
|
||||||
|
|
||||||
__author__ = "Cyril Jaquier"
|
|
||||||
__version__ = "$Revision$"
|
|
||||||
__date__ = "$Date$"
|
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
|
||||||
__license__ = "GPL"
|
|
||||||
|
|
||||||
import time
|
|
||||||
|
|
||||||
from datetemplate import DateTemplate
|
|
||||||
|
|
||||||
class DateEpoch(DateTemplate):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
DateTemplate.__init__(self)
|
|
||||||
# We already know the format for TAI64N
|
|
||||||
self.setRegex("^\d{10}(\.\d{6})?")
|
|
||||||
|
|
||||||
def getDate(self, line):
|
|
||||||
date = None
|
|
||||||
dateMatch = self.matchDate(line)
|
|
||||||
if dateMatch:
|
|
||||||
# extract part of format which represents seconds since epoch
|
|
||||||
date = list(time.localtime(float(dateMatch.group())))
|
|
||||||
return date
|
|
|
@ -1,84 +0,0 @@
|
||||||
# -*- coding: utf8 -*-
|
|
||||||
# This file is part of Fail2Ban.
|
|
||||||
#
|
|
||||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Fail2Ban is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Fail2Ban; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
# Author: Cyril Jaquier
|
|
||||||
#
|
|
||||||
# $Revision$
|
|
||||||
|
|
||||||
__author__ = "Cyril Jaquier"
|
|
||||||
__version__ = "$Revision$"
|
|
||||||
__date__ = "$Date$"
|
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
|
||||||
__license__ = "GPL"
|
|
||||||
|
|
||||||
from mytime import MyTime
|
|
||||||
import time
|
|
||||||
|
|
||||||
from datetemplate import DateTemplate
|
|
||||||
|
|
||||||
##
|
|
||||||
# Use strptime() to parse a date. Our current locale is the 'C'
|
|
||||||
# one because we do not set the locale explicitly. This is POSIX
|
|
||||||
# standard.
|
|
||||||
|
|
||||||
class DateStrptime(DateTemplate):
|
|
||||||
|
|
||||||
TABLE = dict()
|
|
||||||
TABLE["Jan"] = []
|
|
||||||
TABLE["Feb"] = [u"Fév"]
|
|
||||||
TABLE["Mar"] = [u"Mär"]
|
|
||||||
TABLE["Apr"] = ["Avr"]
|
|
||||||
TABLE["May"] = ["Mai"]
|
|
||||||
TABLE["Jun"] = []
|
|
||||||
TABLE["Jul"] = []
|
|
||||||
TABLE["Aug"] = ["Aou"]
|
|
||||||
TABLE["Sep"] = []
|
|
||||||
TABLE["Oct"] = ["Okt"]
|
|
||||||
TABLE["Nov"] = []
|
|
||||||
TABLE["Dec"] = [u"Déc", "Dez"]
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
DateTemplate.__init__(self)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def convertLocale(date):
|
|
||||||
for t in DateStrptime.TABLE:
|
|
||||||
for m in DateStrptime.TABLE[t]:
|
|
||||||
if date.find(m) >= 0:
|
|
||||||
return date.replace(m, t)
|
|
||||||
return date
|
|
||||||
|
|
||||||
def getDate(self, line):
|
|
||||||
date = None
|
|
||||||
dateMatch = self.matchDate(line)
|
|
||||||
if dateMatch:
|
|
||||||
try:
|
|
||||||
# Try first with 'C' locale
|
|
||||||
date = list(time.strptime(dateMatch.group(), self.getPattern()))
|
|
||||||
except ValueError:
|
|
||||||
# Try to convert date string to 'C' locale
|
|
||||||
conv = self.convertLocale(dateMatch.group())
|
|
||||||
date = list(time.strptime(conv, self.getPattern()))
|
|
||||||
if date[0] < 2000:
|
|
||||||
# There is probably no year field in the logs
|
|
||||||
date[0] = MyTime.gmtime()[0]
|
|
||||||
# Bug fix for #1241756
|
|
||||||
# If the date is greater than the current time, we suppose
|
|
||||||
# that the log is not from this year but from the year before
|
|
||||||
if time.mktime(date) > MyTime.time():
|
|
||||||
date[0] -= 1
|
|
||||||
return date
|
|
|
@ -1,46 +0,0 @@
|
||||||
# This file is part of Fail2Ban.
|
|
||||||
#
|
|
||||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Fail2Ban is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Fail2Ban; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
# Author: Cyril Jaquier
|
|
||||||
#
|
|
||||||
# $Revision$
|
|
||||||
|
|
||||||
__author__ = "Cyril Jaquier"
|
|
||||||
__version__ = "$Revision$"
|
|
||||||
__date__ = "$Date$"
|
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
|
||||||
__license__ = "GPL"
|
|
||||||
|
|
||||||
import time
|
|
||||||
|
|
||||||
from datetemplate import DateTemplate
|
|
||||||
|
|
||||||
class DateTai64n(DateTemplate):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
DateTemplate.__init__(self)
|
|
||||||
# We already know the format for TAI64N
|
|
||||||
self.setRegex("@[0-9a-f]{24}")
|
|
||||||
|
|
||||||
def getDate(self, line):
|
|
||||||
date = None
|
|
||||||
dateMatch = self.matchDate(line)
|
|
||||||
if dateMatch:
|
|
||||||
# extract part of format which represents seconds since epoch
|
|
||||||
value = dateMatch.group()
|
|
||||||
seconds_since_epoch = value[2:17]
|
|
||||||
date = list(time.gmtime(int(seconds_since_epoch, 16)))
|
|
||||||
return date
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf8 -*-
|
||||||
# This file is part of Fail2Ban.
|
# This file is part of Fail2Ban.
|
||||||
#
|
#
|
||||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
# Fail2Ban is free software; you can redistribute it and/or modify
|
||||||
|
@ -24,7 +25,9 @@ __date__ = "$Date$"
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||||
__license__ = "GPL"
|
__license__ = "GPL"
|
||||||
|
|
||||||
import re
|
import re, time
|
||||||
|
|
||||||
|
from mytime import MyTime
|
||||||
|
|
||||||
class DateTemplate:
|
class DateTemplate:
|
||||||
|
|
||||||
|
@ -69,3 +72,91 @@ class DateTemplate:
|
||||||
|
|
||||||
def getDate(self, line):
|
def getDate(self, line):
|
||||||
raise Exception("matchDate() is abstract")
|
raise Exception("matchDate() is abstract")
|
||||||
|
|
||||||
|
|
||||||
|
class DateEpoch(DateTemplate):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
DateTemplate.__init__(self)
|
||||||
|
# We already know the format for TAI64N
|
||||||
|
self.setRegex("^\d{10}(\.\d{6})?")
|
||||||
|
|
||||||
|
def getDate(self, line):
|
||||||
|
date = None
|
||||||
|
dateMatch = self.matchDate(line)
|
||||||
|
if dateMatch:
|
||||||
|
# extract part of format which represents seconds since epoch
|
||||||
|
date = list(time.localtime(float(dateMatch.group())))
|
||||||
|
return date
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
# Use strptime() to parse a date. Our current locale is the 'C'
|
||||||
|
# one because we do not set the locale explicitly. This is POSIX
|
||||||
|
# standard.
|
||||||
|
|
||||||
|
class DateStrptime(DateTemplate):
|
||||||
|
|
||||||
|
TABLE = dict()
|
||||||
|
TABLE["Jan"] = []
|
||||||
|
TABLE["Feb"] = [u"Fév"]
|
||||||
|
TABLE["Mar"] = [u"Mär"]
|
||||||
|
TABLE["Apr"] = ["Avr"]
|
||||||
|
TABLE["May"] = ["Mai"]
|
||||||
|
TABLE["Jun"] = []
|
||||||
|
TABLE["Jul"] = []
|
||||||
|
TABLE["Aug"] = ["Aou"]
|
||||||
|
TABLE["Sep"] = []
|
||||||
|
TABLE["Oct"] = ["Okt"]
|
||||||
|
TABLE["Nov"] = []
|
||||||
|
TABLE["Dec"] = [u"Déc", "Dez"]
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
DateTemplate.__init__(self)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def convertLocale(date):
|
||||||
|
for t in DateStrptime.TABLE:
|
||||||
|
for m in DateStrptime.TABLE[t]:
|
||||||
|
if date.find(m) >= 0:
|
||||||
|
return date.replace(m, t)
|
||||||
|
return date
|
||||||
|
|
||||||
|
def getDate(self, line):
|
||||||
|
date = None
|
||||||
|
dateMatch = self.matchDate(line)
|
||||||
|
if dateMatch:
|
||||||
|
try:
|
||||||
|
# Try first with 'C' locale
|
||||||
|
date = list(time.strptime(dateMatch.group(), self.getPattern()))
|
||||||
|
except ValueError:
|
||||||
|
# Try to convert date string to 'C' locale
|
||||||
|
conv = self.convertLocale(dateMatch.group())
|
||||||
|
date = list(time.strptime(conv, self.getPattern()))
|
||||||
|
if date[0] < 2000:
|
||||||
|
# There is probably no year field in the logs
|
||||||
|
date[0] = MyTime.gmtime()[0]
|
||||||
|
# Bug fix for #1241756
|
||||||
|
# If the date is greater than the current time, we suppose
|
||||||
|
# that the log is not from this year but from the year before
|
||||||
|
if time.mktime(date) > MyTime.time():
|
||||||
|
date[0] -= 1
|
||||||
|
return date
|
||||||
|
|
||||||
|
|
||||||
|
class DateTai64n(DateTemplate):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
DateTemplate.__init__(self)
|
||||||
|
# We already know the format for TAI64N
|
||||||
|
self.setRegex("@[0-9a-f]{24}")
|
||||||
|
|
||||||
|
def getDate(self, line):
|
||||||
|
date = None
|
||||||
|
dateMatch = self.matchDate(line)
|
||||||
|
if dateMatch:
|
||||||
|
# extract part of format which represents seconds since epoch
|
||||||
|
value = dateMatch.group()
|
||||||
|
seconds_since_epoch = value[2:17]
|
||||||
|
date = list(time.gmtime(int(seconds_since_epoch, 16)))
|
||||||
|
return date
|
|
@ -24,7 +24,74 @@ __date__ = "$Date$"
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||||
__license__ = "GPL"
|
__license__ = "GPL"
|
||||||
|
|
||||||
from regex import Regex, RegexException
|
import re, sre_constants
|
||||||
|
|
||||||
|
##
|
||||||
|
# Regular expression class.
|
||||||
|
#
|
||||||
|
# This class represents a regular expression with its compiled version.
|
||||||
|
|
||||||
|
class Regex:
|
||||||
|
|
||||||
|
##
|
||||||
|
# Constructor.
|
||||||
|
#
|
||||||
|
# Creates a new object. This method can throw RegexException in order to
|
||||||
|
# avoid construction of invalid object.
|
||||||
|
# @param value the regular expression
|
||||||
|
|
||||||
|
def __init__(self, regex):
|
||||||
|
self._matchCache = None
|
||||||
|
# Perform shortcuts expansions.
|
||||||
|
# Replace "<HOST>" with default regular expression for host.
|
||||||
|
regex = regex.replace("<HOST>", "(?:::f{4,6}:)?(?P<host>\S+)")
|
||||||
|
if regex.lstrip() == '':
|
||||||
|
raise RegexException("Cannot add empty regex")
|
||||||
|
try:
|
||||||
|
self._regexObj = re.compile(regex)
|
||||||
|
self._regex = regex
|
||||||
|
except sre_constants.error:
|
||||||
|
raise RegexException("Unable to compile regular expression '%s'" %
|
||||||
|
regex)
|
||||||
|
|
||||||
|
##
|
||||||
|
# Gets the regular expression.
|
||||||
|
#
|
||||||
|
# The effective regular expression used is returned.
|
||||||
|
# @return the regular expression
|
||||||
|
|
||||||
|
def getRegex(self):
|
||||||
|
return self._regex
|
||||||
|
|
||||||
|
##
|
||||||
|
# Searches the regular expression.
|
||||||
|
#
|
||||||
|
# Sets an internal cache (match object) in order to avoid searching for
|
||||||
|
# the pattern again. This method must be called before calling any other
|
||||||
|
# method of this object.
|
||||||
|
# @param value the line
|
||||||
|
|
||||||
|
def search(self, value):
|
||||||
|
self._matchCache = self._regexObj.search(value)
|
||||||
|
|
||||||
|
##
|
||||||
|
# Checks if the previous call to search() matched.
|
||||||
|
#
|
||||||
|
# @return True if a match was found, False otherwise
|
||||||
|
|
||||||
|
def hasMatched(self):
|
||||||
|
if self._matchCache:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
# Exception dedicated to the class Regex.
|
||||||
|
|
||||||
|
class RegexException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# Regular expression class.
|
# Regular expression class.
|
||||||
|
|
|
@ -29,8 +29,7 @@ from failticket import FailTicket
|
||||||
from jailthread import JailThread
|
from jailthread import JailThread
|
||||||
from datedetector import DateDetector
|
from datedetector import DateDetector
|
||||||
from mytime import MyTime
|
from mytime import MyTime
|
||||||
from regex import Regex, RegexException
|
from failregex import FailRegex, Regex, RegexException
|
||||||
from failregex import FailRegex
|
|
||||||
|
|
||||||
import logging, re
|
import logging, re
|
||||||
|
|
||||||
|
|
|
@ -1,93 +0,0 @@
|
||||||
# This file is part of Fail2Ban.
|
|
||||||
#
|
|
||||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Fail2Ban is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Fail2Ban; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
# Author: Cyril Jaquier
|
|
||||||
#
|
|
||||||
# $Revision$
|
|
||||||
|
|
||||||
__author__ = "Cyril Jaquier"
|
|
||||||
__version__ = "$Revision$"
|
|
||||||
__date__ = "$Date$"
|
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
|
||||||
__license__ = "GPL"
|
|
||||||
|
|
||||||
import re, sre_constants
|
|
||||||
|
|
||||||
##
|
|
||||||
# Regular expression class.
|
|
||||||
#
|
|
||||||
# This class represents a regular expression with its compiled version.
|
|
||||||
|
|
||||||
class Regex:
|
|
||||||
|
|
||||||
##
|
|
||||||
# Constructor.
|
|
||||||
#
|
|
||||||
# Creates a new object. This method can throw RegexException in order to
|
|
||||||
# avoid construction of invalid object.
|
|
||||||
# @param value the regular expression
|
|
||||||
|
|
||||||
def __init__(self, regex):
|
|
||||||
self._matchCache = None
|
|
||||||
# Perform shortcuts expansions.
|
|
||||||
# Replace "<HOST>" with default regular expression for host.
|
|
||||||
regex = regex.replace("<HOST>", "(?:::f{4,6}:)?(?P<host>\S+)")
|
|
||||||
if regex.lstrip() == '':
|
|
||||||
raise RegexException("Cannot add empty regex")
|
|
||||||
try:
|
|
||||||
self._regexObj = re.compile(regex)
|
|
||||||
self._regex = regex
|
|
||||||
except sre_constants.error:
|
|
||||||
raise RegexException("Unable to compile regular expression '%s'" %
|
|
||||||
regex)
|
|
||||||
|
|
||||||
##
|
|
||||||
# Gets the regular expression.
|
|
||||||
#
|
|
||||||
# The effective regular expression used is returned.
|
|
||||||
# @return the regular expression
|
|
||||||
|
|
||||||
def getRegex(self):
|
|
||||||
return self._regex
|
|
||||||
|
|
||||||
##
|
|
||||||
# Searches the regular expression.
|
|
||||||
#
|
|
||||||
# Sets an internal cache (match object) in order to avoid searching for
|
|
||||||
# the pattern again. This method must be called before calling any other
|
|
||||||
# method of this object.
|
|
||||||
# @param value the line
|
|
||||||
|
|
||||||
def search(self, value):
|
|
||||||
self._matchCache = self._regexObj.search(value)
|
|
||||||
|
|
||||||
##
|
|
||||||
# Checks if the previous call to search() matched.
|
|
||||||
#
|
|
||||||
# @return True if a match was found, False otherwise
|
|
||||||
|
|
||||||
def hasMatched(self):
|
|
||||||
if self._matchCache:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
##
|
|
||||||
# Exception dedicated to the class Regex.
|
|
||||||
|
|
||||||
class RegexException(Exception):
|
|
||||||
pass
|
|
Loading…
Reference in New Issue