@@ -277,6 +277,27 @@ def validate_include_target_data(
277277 return unexpected_target_data_message
278278
279279
280+ def _accepted_date_formats () -> Set [str ]:
281+ """
282+ Return all known accepted date formats.
283+
284+ We expect that more formats than this will be accepted.
285+ These are the accepted ones we know of at the time of writing.
286+ """
287+ known_accepted_formats = {
288+ '%a, %b %d %H:%M:%S %Y' ,
289+ '%a %b %d %H:%M:%S %Y' ,
290+ '%a, %d %b %Y %H:%M:%S' ,
291+ '%a %d %b %Y %H:%M:%S' ,
292+ }
293+
294+ known_accepted_formats = known_accepted_formats .union (
295+ set (date_format + ' GMT' for date_format in known_accepted_formats )
296+ )
297+
298+ return known_accepted_formats
299+
300+
280301@wrapt .decorator
281302def validate_date_format (
282303 wrapped : Callable [..., str ],
@@ -298,35 +319,22 @@ def validate_date_format(
298319 An `UNAUTHORIZED` response if the date is in the wrong format.
299320 """
300321 request , context = args
301-
302- # We expect that more formats than this will be accepted.
303- # These are the accepted ones we know of at the time of writing.
304- known_accepted_formats = {
305- '%a, %b %d %H:%M:%S %Y' ,
306- '%a %b %d %H:%M:%S %Y' ,
307- '%a, %d %b %Y %H:%M:%S' ,
308- '%a %d %b %Y %H:%M:%S' ,
309- }
310-
311- formats_with_timezones = set (item + ' GMT' for item in known_accepted_formats )
312-
313- formats = known_accepted_formats .union (formats_with_timezones )
314- import pdb ; pdb .set_trace ()
315-
316- try :
317- datetime .datetime .strptime (
318- request .headers ['Date' ],
319- '%a, %d %b %Y %H:%M:%S GMT' ,
320- )
321- except ValueError :
322- context .status_code = codes .UNAUTHORIZED
323- context .headers ['WWW-Authenticate' ] = 'VWS'
324- text = 'Malformed date header.'
325- content_type = 'text/plain; charset=ISO-8859-1'
326- context .headers ['Content-Type' ] = content_type
327- return text
328-
329- return wrapped (* args , ** kwargs )
322+ date_header = request .headers ['Date' ]
323+
324+ for date_format in _accepted_date_formats ():
325+ try :
326+ datetime .datetime .strptime (date_header , date_format )
327+ except ValueError :
328+ pass
329+ else :
330+ return wrapped (* args , ** kwargs )
331+
332+ context .status_code = codes .UNAUTHORIZED
333+ context .headers ['WWW-Authenticate' ] = 'VWS'
334+ text = 'Malformed date header.'
335+ content_type = 'text/plain; charset=ISO-8859-1'
336+ context .headers ['Content-Type' ] = content_type
337+ return text
330338
331339
332340@wrapt .decorator
@@ -350,15 +358,19 @@ def validate_date(
350358 A `FORBIDDEN` response if the date is out of range.
351359 """
352360 request , context = args
361+ date_header = request .headers ['Date' ]
353362
354- date_from_header = datetime .datetime .strptime (
355- request .headers ['Date' ],
356- '%a, %d %b %Y %H:%M:%S GMT' ,
357- )
363+ for date_format in _accepted_date_formats ():
364+ try :
365+ date = datetime .datetime .strptime (date_header , date_format )
366+ except ValueError :
367+ pass
368+ else :
369+ break
358370
359371 gmt = pytz .timezone ('GMT' )
360372 now = datetime .datetime .now (tz = gmt )
361- date_from_header = date_from_header .replace (tzinfo = gmt )
373+ date_from_header = date .replace (tzinfo = gmt )
362374 time_difference = now - date_from_header
363375
364376 maximum_time_difference = datetime .timedelta (minutes = 65 )
0 commit comments