From 37de5462beca411b01cff7b354778b64d75ba5a7 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sat, 21 Sep 2013 11:47:24 +1000 Subject: [PATCH] ENH: iso8601 - remove default_timezone set to UTC, isn't valid any more - calculate from local timezone. Enforce T date/time separator in iso8601 regex. Make minutes in timezone optional as per ISO8601. Use consistant regex for ISO8601 --- fail2ban/server/datetemplate.py | 5 +---- fail2ban/server/iso8601.py | 40 ++++++++++++++++++--------------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/fail2ban/server/datetemplate.py b/fail2ban/server/datetemplate.py index 81b307eb..6309e8eb 100644 --- a/fail2ban/server/datetemplate.py +++ b/fail2ban/server/datetemplate.py @@ -300,10 +300,7 @@ class DateISO8601(DateTemplate): def __init__(self): DateTemplate.__init__(self) - date_re = "[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}" \ - ".[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?" \ - "(Z|(([-+])([0-9]{2}):([0-9]{2})))?" - self.setRegex(date_re) + self.setRegex(iso8601.ISO8601_REGEX_RAW) def getDate(self, line): dateMatch = self.matchDate(line) diff --git a/fail2ban/server/iso8601.py b/fail2ban/server/iso8601.py index a42989ea..f40d5e75 100644 --- a/fail2ban/server/iso8601.py +++ b/fail2ban/server/iso8601.py @@ -32,17 +32,17 @@ datetime.datetime(2007, 1, 25, 12, 0, tzinfo=) """ -from datetime import datetime, timedelta, tzinfo +from datetime import datetime, timedelta, tzinfo, time import re __all__ = ["parse_date", "ParseError"] # Adapted from http://delete.me.uk/2005/03/iso8601.html -ISO8601_REGEX = re.compile(r"(?P[0-9]{4})(-(?P[0-9]{1,2})(-(?P[0-9]{1,2})" - r"((?P.)(?P[0-9]{2}):(?P[0-9]{2})(:(?P[0-9]{2})(\.(?P[0-9]+))?)?" - r"(?PZ|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?" -) -TIMEZONE_REGEX = re.compile("(?P[+-])(?P[0-9]{2}).(?P[0-9]{2})") +ISO8601_REGEX_RAW = "(?P[0-9]{4})-(?P[0-9]{1,2})-(?P[0-9]{1,2})" \ + "T(?P[0-9]{2}):(?P[0-9]{2})(:(?P[0-9]{2})(\.(?P[0-9]+))?)?" \ + "(?PZ|(([-+])([0-9]{2}):([0-9]{2})))?" +ISO8601_REGEX = re.compile(ISO8601_REGEX_RAW) +TIMEZONE_REGEX = re.compile("(?P[+-])(?P[0-9]{2}):?(?P[0-9]{2})?") class ParseError(Exception): """Raised when there is a problem parsing a date string""" @@ -67,8 +67,8 @@ class FixedOffset(tzinfo): """Fixed offset in hours and minutes from UTC """ - def __init__(self, offset_hours, offset_minutes, name): - self.__offset = timedelta(hours=offset_hours, minutes=offset_minutes) + def __init__(self, name, offset_hours, offset_minutes, offset_seconds=0): + self.__offset = timedelta(hours=offset_hours, minutes=offset_minutes, seconds=offset_seconds) self.__name = name def utcoffset(self, dt): @@ -83,26 +83,30 @@ class FixedOffset(tzinfo): def __repr__(self): return "" % self.__name -def parse_timezone(tzstring, default_timezone=UTC): +def parse_timezone(tzstring): """Parses ISO 8601 time zone specs into tzinfo offsets """ if tzstring == "Z": - return default_timezone - # This isn't strictly correct, but it's common to encounter dates without - # timezones so I'll assume the default (which defaults to UTC). - # Addresses issue 4. + return UTC + if tzstring is None: - return default_timezone + zone_sec = -time.timezone + return FixedOffset(name=time.tzname[0],hours=(zone_sec / 3600),minutes=(zone_sec % 3600)/60,seconds=zone_sec % 60) + m = TIMEZONE_REGEX.match(tzstring) prefix, hours, minutes = m.groups() - hours, minutes = int(hours), int(minutes) + if minutes is None: + minutes = 0 + else: + minutes = int(minutes) + hours = int(hours) if prefix == "-": hours = -hours minutes = -minutes - return FixedOffset(hours, minutes, tzstring) + return FixedOffset(tzstring, hours, minutes) -def parse_date(datestring, default_timezone=UTC): +def parse_date(datestring): """Parses ISO 8601 dates into datetime objects The timezone is parsed from the date string. However it is quite common to @@ -116,7 +120,7 @@ def parse_date(datestring, default_timezone=UTC): if not m: raise ParseError("Unable to parse date string %r" % datestring) groups = m.groupdict() - tz = parse_timezone(groups["timezone"], default_timezone=default_timezone) + tz = parse_timezone(groups["timezone"]) if groups["fraction"] is None: groups["fraction"] = 0 else: