Skip to content

Commit

Permalink
Initial update to 'time' 0.3.
Browse files Browse the repository at this point in the history
  • Loading branch information
CraftSpider authored and SergioBenitez committed Aug 18, 2021
1 parent 0d10202 commit 0a7453c
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 37 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ signed = ["hmac", "sha2", "base64", "rand", "subtle"]
key-expansion = ["sha2", "hkdf"]

[dependencies]
time = { version = "0.2.11", default-features = false, features = ["std"] }
time = { version = "0.3", default-features = false, features = ["std", "parsing", "formatting", "macros"] }
percent-encoding = { version = "2.0", optional = true }

# dependencies for secure (private/signed) functionality
Expand Down
2 changes: 1 addition & 1 deletion src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl<'c> CookieBuilder<'c> {
///
/// # fn main() {
/// let c = Cookie::build("foo", "bar")
/// .expires(OffsetDateTime::now())
/// .expires(OffsetDateTime::now_utc())
/// .finish();
///
/// assert!(c.expires().is_some());
Expand Down
10 changes: 5 additions & 5 deletions src/expiration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use time::OffsetDateTime;
/// let expires = Expiration::from(None);
/// assert_eq!(expires, Expiration::Session);
///
/// let now = OffsetDateTime::now();
/// let now = OffsetDateTime::now_utc();
/// let expires = Expiration::from(now);
/// assert_eq!(expires, Expiration::DateTime(now));
///
Expand Down Expand Up @@ -46,7 +46,7 @@ impl Expiration {
/// let expires = Expiration::from(None);
/// assert!(!expires.is_datetime());
///
/// let expires = Expiration::from(OffsetDateTime::now());
/// let expires = Expiration::from(OffsetDateTime::now_utc());
/// assert!(expires.is_datetime());
/// ```
pub fn is_datetime(&self) -> bool {
Expand All @@ -67,7 +67,7 @@ impl Expiration {
/// let expires = Expiration::from(None);
/// assert!(expires.is_session());
///
/// let expires = Expiration::from(OffsetDateTime::now());
/// let expires = Expiration::from(OffsetDateTime::now_utc());
/// assert!(!expires.is_session());
/// ```
pub fn is_session(&self) -> bool {
Expand All @@ -88,7 +88,7 @@ impl Expiration {
/// let expires = Expiration::from(None);
/// assert!(expires.datetime().is_none());
///
/// let now = OffsetDateTime::now();
/// let now = OffsetDateTime::now_utc();
/// let expires = Expiration::from(now);
/// assert_eq!(expires.datetime(), Some(now));
/// ```
Expand All @@ -108,7 +108,7 @@ impl Expiration {
/// use cookie::Expiration;
/// use time::{OffsetDateTime, Duration};
///
/// let now = OffsetDateTime::now();
/// let now = OffsetDateTime::now_utc();
/// let one_week = Duration::weeks(1);
///
/// let expires = Expiration::from(now);
Expand Down
18 changes: 12 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -816,7 +816,7 @@ impl<'c> Cookie<'c> {
/// let mut c = Cookie::new("name", "value");
/// assert_eq!(c.expires(), None);
///
/// let mut now = OffsetDateTime::now();
/// let mut now = OffsetDateTime::now_utc();
/// now += Duration::weeks(52);
///
/// c.set_expires(now);
Expand All @@ -826,7 +826,7 @@ impl<'c> Cookie<'c> {
/// assert_eq!(c.expires(), Some(Expiration::Session));
/// ```
pub fn set_expires<T: Into<Expiration>>(&mut self, time: T) {
use time::{date, time, offset};
use time::macros::{date, time, offset};
static MAX_DATETIME: OffsetDateTime = date!(9999-12-31)
.with_time(time!(23:59:59.999_999))
.assume_utc()
Expand Down Expand Up @@ -905,7 +905,7 @@ impl<'c> Cookie<'c> {
///
/// c.make_removal();
/// assert_eq!(c.value(), "");
/// assert_eq!(c.max_age(), Some(Duration::zero()));
/// assert_eq!(c.max_age(), Some(Duration::ZERO));
/// # }
/// ```
pub fn make_removal(&mut self) {
Expand Down Expand Up @@ -945,7 +945,9 @@ impl<'c> Cookie<'c> {

if let Some(time) = self.expires_datetime() {
let time = time.to_offset(UtcOffset::UTC);
write!(f, "; Expires={}", time.format("%a, %d %b %Y %H:%M:%S GMT"))?;
write!(f, "; Expires={}", time.format(&time::macros::format_description!(
"[weekday repr:short], [day] [month repr:short] [year] [hour]:[minute]:[second] GMT"
)).unwrap())?;
}

Ok(())
Expand Down Expand Up @@ -1293,6 +1295,7 @@ mod tests {
use crate::{Cookie, SameSite};
use crate::parse::parse_gmt_date;
use crate::{time::Duration, OffsetDateTime};
use crate::{time::macros::format_description};

#[test]
fn format() {
Expand Down Expand Up @@ -1320,7 +1323,10 @@ mod tests {
assert_eq!(&cookie.to_string(), "foo=bar; Domain=www.rust-lang.org");

let time_str = "Wed, 21 Oct 2015 07:28:00 GMT";
let expires = parse_gmt_date(time_str, "%a, %d %b %Y %H:%M:%S GMT").unwrap();
let expires = parse_gmt_date(
time_str,
&format_description!("[weekday repr:short], [day] [month repr:short] [year] [hour]:[minute]:[second] GMT")
).unwrap();
let cookie = Cookie::build("foo", "bar")
.expires(expires).finish();
assert_eq!(&cookie.to_string(),
Expand Down Expand Up @@ -1353,7 +1359,7 @@ mod tests {
#[test]
#[ignore]
fn format_date_wraps() {
let expires = OffsetDateTime::unix_epoch() + Duration::max_value();
let expires = OffsetDateTime::UNIX_EPOCH + Duration::MAX;
let cookie = Cookie::build("foo", "bar")
.expires(expires).finish();
assert_eq!(&cookie.to_string(),
Expand Down
78 changes: 54 additions & 24 deletions src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ use std::borrow::Cow;
use std::error::Error;
use std::str::Utf8Error;
use std::fmt;
use std::convert::From;
use std::convert::{From, TryFrom};

#[allow(unused_imports, deprecated)]
use std::ascii::AsciiExt;

#[cfg(feature = "percent-encode")]
use percent_encoding::percent_decode;
use time::{Duration, OffsetDateTime, PrimitiveDateTime, UtcOffset, Date};
use time::{Duration, OffsetDateTime, PrimitiveDateTime, UtcOffset};
use time::error::Parse;
use time::parsing::Parsed;
use time::macros::format_description;

use crate::{Cookie, SameSite, CookieStr};

Expand Down Expand Up @@ -184,7 +187,7 @@ fn parse_inner<'c>(s: &str, decode: bool) -> Result<Cookie<'c>, ParseError> {
// From RFC 6265 5.2.2: neg values indicate that the earliest
// expiration should be used, so set the max age to 0 seconds.
if is_negative {
Some(Duration::zero())
Some(Duration::ZERO)
} else {
Some(v.parse::<i64>()
.map(Duration::seconds)
Expand Down Expand Up @@ -222,10 +225,19 @@ fn parse_inner<'c>(s: &str, decode: bool) -> Result<Cookie<'c>, ParseError> {
// Try strptime with three date formats according to
// http://tools.ietf.org/html/rfc2616#section-3.3.1. Try
// additional ones as encountered in the real world.
let tm = parse_gmt_date(v, "%a, %d %b %Y %H:%M:%S GMT")
.or_else(|_| parse_gmt_date(v, "%A, %d-%b-%y %H:%M:%S GMT"))
.or_else(|_| parse_gmt_date(v, "%a, %d-%b-%Y %H:%M:%S GMT"))
.or_else(|_| parse_gmt_date(v, "%a %b %d %H:%M:%S %Y"));
let tm = parse_gmt_date(
v,
&format_description!("[weekday repr:short], [day] [month repr:short] [year] [hour]:[minute]:[second] GMT")
).or_else(|_| parse_gmt_date(
v,
&format_description!("[weekday repr:short], [day]-[month repr:short]-[year repr:last_two] [hour]:[minute]:[second] GMT")
)).or_else(|_| parse_gmt_date(
v,
&format_description!("[weekday repr:short], [day]-[month repr:short]-[year] [hour]:[minute]:[second] GMT")
)).or_else(|_| parse_gmt_date(
v,
&format_description!("[weekday repr:short] [month repr:short] [day] [hour]:[minute]:[second] [year]")
));

if let Ok(time) = tm {
cookie.expires = Some(time.into())
Expand All @@ -252,27 +264,39 @@ pub(crate) fn parse_cookie<'c, S>(cow: S, decode: bool) -> Result<Cookie<'c>, Pa
Ok(cookie)
}

pub(crate) fn parse_gmt_date(s: &str, format: &str) -> Result<OffsetDateTime, time::ParseError> {
PrimitiveDateTime::parse(s, format)
.map(|t| t.assume_utc().to_offset(UtcOffset::UTC))
// Handle malformed "abbreviated" dates like Chromium. See cookie#162.
.map(|date| {
let offset = match date.year() {
0..=68 => 2000,
69..=99 => 1900,
_ => return date,
};

let new_date = Date::try_from_ymd(date.year() + offset, date.month(), date.day());
PrimitiveDateTime::new(new_date.expect("date from date"), date.time()).assume_utc()
pub(crate) fn parse_gmt_date<T>(s: &str, format: &T) -> Result<OffsetDateTime, time::error::Parse>
where
T: time::parsing::Parsable,
{
format.parse(s.as_bytes())
.map(|mut parsed| {
// Handle malformed "abbreviated" dates like Chromium. See cookie#162.
parsed.year_last_two()
.map(|y| {
let y = y as i32;
let offset = match y {
0..=68 => 2000,
69..=99 => 1900,
_ => 0,
};

parsed.set_year(y + offset)
});

parsed
})
.and_then(|parsed| <PrimitiveDateTime as TryFrom<Parsed>>::try_from(parsed)
.map_err(|err| Parse::TryFromParsed(err))
)
.map(|t| t.assume_utc().to_offset(UtcOffset::UTC))
}

#[cfg(test)]
mod tests {
use crate::{Cookie, SameSite};
use super::parse_gmt_date;
use ::time::Duration;
use ::time::macros::format_description;

macro_rules! assert_eq_parse {
($string:expr, $expected:expr) => (
Expand Down Expand Up @@ -389,7 +413,7 @@ mod tests {
assert_ne_parse!(" foo=bar ;HttpOnly; secure", unexpected);
assert_ne_parse!(" foo=bar ;HttpOnly; secure", unexpected);

expected.set_max_age(Duration::zero());
expected.set_max_age(Duration::ZERO);
assert_eq_parse!(" foo=bar ;HttpOnly; Secure; Max-Age=0", expected);
assert_eq_parse!(" foo=bar ;HttpOnly; Secure; Max-Age = 0 ", expected);
assert_eq_parse!(" foo=bar ;HttpOnly; Secure; Max-Age=-1", expected);
Expand Down Expand Up @@ -444,13 +468,19 @@ mod tests {
Domain=FOO.COM", unexpected);

let time_str = "Wed, 21 Oct 2015 07:28:00 GMT";
let expires = parse_gmt_date(time_str, "%a, %d %b %Y %H:%M:%S GMT").unwrap();
let expires = parse_gmt_date(
time_str,
&format_description!("[weekday repr:short], [day] [month repr:short] [year] [hour]:[minute]:[second] GMT")
).unwrap();
expected.set_expires(expires);
assert_eq_parse!(" foo=bar ;HttpOnly; Secure; Max-Age=4; Path=/foo; \
Domain=foo.com; Expires=Wed, 21 Oct 2015 07:28:00 GMT", expected);

unexpected.set_domain("foo.com");
let bad_expires = parse_gmt_date(time_str, "%a, %d %b %Y %H:%S:%M GMT").unwrap();
let bad_expires = parse_gmt_date(
time_str,
&format_description!("[weekday repr:short], [day] [month repr:short] [year] [hour]:[minute]:[minute] GMT")
).unwrap();
expected.set_expires(bad_expires);
assert_ne_parse!(" foo=bar ;HttpOnly; Secure; Max-Age=4; Path=/foo; \
Domain=foo.com; Expires=Wed, 21 Oct 2015 07:28:00 GMT", unexpected);
Expand Down Expand Up @@ -518,7 +548,7 @@ mod tests {

#[test]
fn do_not_panic_on_large_max_ages() {
let max_seconds = Duration::max_value().whole_seconds();
let max_seconds = Duration::MAX.whole_seconds();
let expected = Cookie::build("foo", "bar")
.max_age(Duration::seconds(max_seconds))
.finish();
Expand Down

0 comments on commit 0a7453c

Please sign in to comment.