Skip to content

Commit f3aa90a

Browse files
author
Simon Coffey
committed
Clarify ISO 8601 duration regexp
The ISO 8601 parsing regexp is moderately complex, and uses numbered backreferences to extract data, which is prone to breakage if new capture groups are introduced (either inadvertently or deliberately). This also means every regexp group we don't want to capture must be anonymised using (?: ...). In modern rubies we could use named capture groups to clarify things; however since these are only supported since ruby 1.9 and ruby-saml supports 1.8.7, that's not an option. However, we can still use /x to introduce whitespace and source code comments, which this commit does, splitting each meaningful capture group onto its own annotated line. Doing this, it also became clear that some of the groups weren't necessary, e.g. the two groups surrounding each part of the ( YMDHMS format | week format) disjunction, so I've reduced the nesting somewhat, too.
1 parent c9f81b9 commit f3aa90a

File tree

1 file changed

+17
-3
lines changed

1 file changed

+17
-3
lines changed

lib/onelogin/ruby-saml/utils.rb

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,21 @@ class Utils
1515

1616
DSIG = "http://www.w3.org/2000/09/xmldsig#"
1717
XENC = "http://www.w3.org/2001/04/xmlenc#"
18-
DURATION_FORMAT = %r(^(-?)P(?:(?:(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?)|(?:(\d+)W))$)
18+
DURATION_FORMAT = %r(^
19+
(-?)P # 1: Duration sign
20+
(?:
21+
(?:(\d+)Y)? # 2: Years
22+
(?:(\d+)M)? # 3: Months
23+
(?:(\d+)D)? # 4: Days
24+
(?:T
25+
(?:(\d+)H)? # 5: Hours
26+
(?:(\d+)M)? # 6: Minutes
27+
(?:(\d+)S)? # 7: Seconds and optional milliseconds
28+
)?
29+
|
30+
(\d+)W # 8: Weeks
31+
)
32+
$)x
1933

2034
# Checks if the x509 cert provided is expired
2135
#
@@ -37,10 +51,10 @@ def self.is_cert_expired(cert)
3751
# current time.
3852
#
3953
# @return [Integer] The new timestamp, after the duration is applied.
40-
#
54+
#
4155
def self.parse_duration(duration, timestamp=Time.now.utc)
4256
matches = duration.match(DURATION_FORMAT)
43-
57+
4458
if matches.nil?
4559
raise Exception.new("Invalid ISO 8601 duration")
4660
end

0 commit comments

Comments
 (0)