diff options
author | Patrick Griffis <pgriffis@igalia.com> | 2020-08-28 17:16:15 -0500 |
---|---|---|
committer | Patrick Griffis <pgriffis@igalia.com> | 2020-09-19 15:41:25 -0700 |
commit | 4596b4ec4c14a0e473e3fa0c3f41a0107d846cc8 (patch) | |
tree | b99525eaa9f338a52eeab85df16fd78df5219766 | |
parent | 4217855114d1357eb16c5cf663b2fa09a6e6bd3c (diff) | |
download | libsoup-4596b4ec4c14a0e473e3fa0c3f41a0107d846cc8.tar.gz |
Replace SoupDate with GDateTime
-rw-r--r-- | docs/reference/libsoup-2.4-sections.txt | 22 | ||||
-rw-r--r-- | libsoup/cache/soup-cache.c | 30 | ||||
-rw-r--r-- | libsoup/cookies/soup-cookie-jar-db.c | 2 | ||||
-rw-r--r-- | libsoup/cookies/soup-cookie-jar-text.c | 2 | ||||
-rw-r--r-- | libsoup/cookies/soup-cookie-jar.c | 7 | ||||
-rw-r--r-- | libsoup/cookies/soup-cookie.c | 38 | ||||
-rw-r--r-- | libsoup/cookies/soup-cookie.h | 18 | ||||
-rw-r--r-- | libsoup/hsts/soup-hsts-enforcer-db.c | 8 | ||||
-rw-r--r-- | libsoup/hsts/soup-hsts-policy.c | 25 | ||||
-rw-r--r-- | libsoup/hsts/soup-hsts-policy.h | 4 | ||||
-rw-r--r-- | libsoup/include/soup-installed.h | 2 | ||||
-rw-r--r-- | libsoup/meson.build | 4 | ||||
-rw-r--r-- | libsoup/soup-date-utils-private.h | 30 | ||||
-rw-r--r-- | libsoup/soup-date-utils.c | 329 | ||||
-rw-r--r-- | libsoup/soup-date-utils.h | 38 | ||||
-rw-r--r-- | libsoup/soup-date.c | 911 | ||||
-rw-r--r-- | libsoup/soup-date.h | 88 | ||||
-rw-r--r-- | libsoup/soup-server.c | 8 | ||||
-rw-r--r-- | libsoup/soup-types.h | 1 | ||||
-rw-r--r-- | libsoup/soup.h | 2 | ||||
-rw-r--r-- | tests/cache-test.c | 17 | ||||
-rw-r--r-- | tests/date-test.c | 177 |
22 files changed, 521 insertions, 1242 deletions
diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index 9c8043a8..b258c9ae 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -593,24 +593,9 @@ soup_uri_get_type <SECTION> <FILE>soup-misc</FILE> <TITLE>Soup Miscellaneous Utilities</TITLE> -SoupDate SoupDateFormat -soup_date_new -soup_date_new_from_string -soup_date_new_from_time_t -soup_date_new_from_now -soup_date_to_string -soup_date_to_time_t -soup_date_is_past -soup_date_get_day -soup_date_get_hour -soup_date_get_minute -soup_date_get_month -soup_date_get_offset -soup_date_get_second -soup_date_get_utc -soup_date_get_year -soup_date_free +soup_date_time_new_from_http_string +soup_date_time_to_string <SUBSECTION> soup_headers_parse_request soup_headers_parse_response @@ -637,9 +622,6 @@ soup_add_idle soup_add_io_watch soup_add_timeout <SUBSECTION Private> -soup_date_copy -SOUP_TYPE_DATE -soup_date_get_type soup_char_is_token soup_char_is_uri_gen_delims soup_char_is_uri_percent_encoded diff --git a/libsoup/cache/soup-cache.c b/libsoup/cache/soup-cache.c index 09c71a44..ae79d793 100644 --- a/libsoup/cache/soup-cache.c +++ b/libsoup/cache/soup-cache.c @@ -390,18 +390,18 @@ soup_cache_entry_set_freshness (SoupCacheEntry *entry, SoupMessage *msg, SoupCac expires = soup_message_headers_get_one (entry->headers, "Expires"); date = soup_message_headers_get_one (entry->headers, "Date"); if (expires && date) { - SoupDate *expires_d, *date_d; + GDateTime *expires_d, *date_d; time_t expires_t, date_t; - expires_d = soup_date_new_from_string (expires); + expires_d = soup_date_time_new_from_http_string (expires); if (expires_d) { - date_d = soup_date_new_from_string (date); + date_d = soup_date_time_new_from_http_string (date); - expires_t = soup_date_to_time_t (expires_d); - date_t = soup_date_to_time_t (date_d); + expires_t = g_date_time_to_unix (expires_d); + date_t = g_date_time_to_unix (date_d); - soup_date_free (expires_d); - soup_date_free (date_d); + g_date_time_unref (expires_d); + g_date_time_unref (date_d); if (expires_t && date_t) { entry->freshness_lifetime = (guint32) MAX (expires_t - date_t, 0); @@ -434,17 +434,17 @@ soup_cache_entry_set_freshness (SoupCacheEntry *entry, SoupMessage *msg, SoupCac /* Last-Modified based heuristic */ last_modified = soup_message_headers_get_one (entry->headers, "Last-Modified"); if (last_modified) { - SoupDate *soup_date; + GDateTime *soup_date; time_t now, last_modified_t; - soup_date = soup_date_new_from_string (last_modified); - last_modified_t = soup_date_to_time_t (soup_date); + soup_date = soup_date_time_new_from_http_string (last_modified); + last_modified_t = g_date_time_to_unix (soup_date); now = time (NULL); #define HEURISTIC_FACTOR 0.1 /* From Section 2.3.1.1 */ entry->freshness_lifetime = MAX (0, (now - last_modified_t) * HEURISTIC_FACTOR); - soup_date_free (soup_date); + g_date_time_unref (soup_date); } return; @@ -481,13 +481,13 @@ soup_cache_entry_new (SoupCache *cache, SoupMessage *msg, time_t request_time, t date = soup_message_headers_get_one (entry->headers, "Date"); if (date) { - SoupDate *soup_date; + GDateTime *soup_date; const char *age; time_t date_value, apparent_age, corrected_received_age, response_delay, age_value = 0; - soup_date = soup_date_new_from_string (date); - date_value = soup_date_to_time_t (soup_date); - soup_date_free (soup_date); + soup_date = soup_date_time_new_from_http_string (date); + date_value = g_date_time_to_unix (soup_date); + g_date_time_unref (soup_date); age = soup_message_headers_get_one (entry->headers, "Age"); if (age) diff --git a/libsoup/cookies/soup-cookie-jar-db.c b/libsoup/cookies/soup-cookie-jar-db.c index c6f698d4..7ee9123f 100644 --- a/libsoup/cookies/soup-cookie-jar-db.c +++ b/libsoup/cookies/soup-cookie-jar-db.c @@ -297,7 +297,7 @@ soup_cookie_jar_db_changed (SoupCookieJar *jar, if (new_cookie && new_cookie->expires) { gulong expires; - expires = (gulong)soup_date_to_time_t (new_cookie->expires); + expires = (gulong)g_date_time_to_unix (new_cookie->expires); query = sqlite3_mprintf (QUERY_INSERT, new_cookie->name, new_cookie->value, diff --git a/libsoup/cookies/soup-cookie-jar-text.c b/libsoup/cookies/soup-cookie-jar-text.c index 31c0d891..7a57494d 100644 --- a/libsoup/cookies/soup-cookie-jar-text.c +++ b/libsoup/cookies/soup-cookie-jar-text.c @@ -267,7 +267,7 @@ write_cookie (FILE *out, SoupCookie *cookie) *cookie->domain == '.' ? "TRUE" : "FALSE", cookie->path, cookie->secure ? "TRUE" : "FALSE", - (gulong)soup_date_to_time_t (cookie->expires), + (gulong)g_date_time_to_unix (cookie->expires), cookie->name, cookie->value, same_site_policy_to_string (soup_cookie_get_same_site_policy (cookie))); diff --git a/libsoup/cookies/soup-cookie-jar.c b/libsoup/cookies/soup-cookie-jar.c index f2433384..1cf24f3a 100644 --- a/libsoup/cookies/soup-cookie-jar.c +++ b/libsoup/cookies/soup-cookie-jar.c @@ -12,6 +12,7 @@ #include <string.h> #include "soup-cookie-jar.h" +#include "soup-date-utils-private.h" #include "soup-message-private.h" #include "soup-misc.h" #include "soup.h" @@ -343,7 +344,7 @@ get_cookies (SoupCookieJar *jar, GSList *next = domain_cookies->next; SoupCookie *cookie = domain_cookies->data; - if (cookie->expires && soup_date_is_past (cookie->expires)) { + if (cookie->expires && soup_date_time_is_past (cookie->expires)) { cookies_to_remove = g_slist_append (cookies_to_remove, cookie); new_head = g_slist_delete_link (new_head, domain_cookies); @@ -610,7 +611,7 @@ soup_cookie_jar_add_cookie_full (SoupCookieJar *jar, SoupCookie *cookie, SoupURI * https://tools.ietf.org/html/draft-ietf-httpbis-cookie-alone-01 */ soup_cookie_free (cookie); - } else if (cookie->expires && soup_date_is_past (cookie->expires)) { + } else if (cookie->expires && soup_date_time_is_past (cookie->expires)) { /* The new cookie has an expired date, * this is the way the the server has * of telling us that we have to @@ -635,7 +636,7 @@ soup_cookie_jar_add_cookie_full (SoupCookieJar *jar, SoupCookie *cookie, SoupURI } /* The new cookie is... a new cookie */ - if (cookie->expires && soup_date_is_past (cookie->expires)) { + if (cookie->expires && soup_date_time_is_past (cookie->expires)) { soup_cookie_free (cookie); return; } diff --git a/libsoup/cookies/soup-cookie.c b/libsoup/cookies/soup-cookie.c index 5fa4c251..71540bd8 100644 --- a/libsoup/cookies/soup-cookie.c +++ b/libsoup/cookies/soup-cookie.c @@ -13,6 +13,7 @@ #include <string.h> #include "soup-cookie.h" +#include "soup-date-utils-private.h" #include "soup-misc.h" #include "soup.h" @@ -85,7 +86,7 @@ soup_cookie_copy (SoupCookie *cookie) copy->domain = g_strdup (cookie->domain); copy->path = g_strdup (cookie->path); if (cookie->expires) - copy->expires = soup_date_copy(cookie->expires); + copy->expires = g_date_time_ref (cookie->expires); copy->secure = cookie->secure; copy->http_only = cookie->http_only; soup_cookie_set_same_site_policy (copy, soup_cookie_get_same_site_policy (cookie)); @@ -157,14 +158,14 @@ parse_value (const char **val_p, gboolean copy) return value; } -static SoupDate * +static GDateTime * parse_date (const char **val_p) { char *value; - SoupDate *date; + GDateTime *date; value = parse_value (val_p, TRUE); - date = soup_date_new_from_string (value); + date = soup_date_time_new_from_http_string (value); g_free (value); return date; } @@ -563,7 +564,7 @@ void soup_cookie_set_max_age (SoupCookie *cookie, int max_age) { if (cookie->expires) - soup_date_free (cookie->expires); + g_date_time_unref (cookie->expires); if (max_age == -1) cookie->expires = NULL; @@ -571,9 +572,12 @@ soup_cookie_set_max_age (SoupCookie *cookie, int max_age) /* Use a date way in the past, to protect against * clock skew. */ - cookie->expires = soup_date_new (1970, 1, 1, 0, 0, 0); - } else - cookie->expires = soup_date_new_from_now (max_age); + cookie->expires = g_date_time_new_from_unix_utc (0); + } else { + GDateTime *now = g_date_time_new_now_utc (); + cookie->expires = g_date_time_add_seconds (now, max_age); + g_date_time_unref (now); + } } /** @@ -611,7 +615,7 @@ soup_cookie_set_max_age (SoupCookie *cookie, int max_age) /** * soup_cookie_get_expires: - * @cookie: a #SoupCookie + * @cookie: a #GDateTime * * Gets @cookie's expiration time. * @@ -621,7 +625,7 @@ soup_cookie_set_max_age (SoupCookie *cookie, int max_age) * * Since: 2.32 **/ -SoupDate * +GDateTime * soup_cookie_get_expires (SoupCookie *cookie) { return cookie->expires; @@ -641,13 +645,13 @@ soup_cookie_get_expires (SoupCookie *cookie) * Since: 2.24 **/ void -soup_cookie_set_expires (SoupCookie *cookie, SoupDate *expires) +soup_cookie_set_expires (SoupCookie *cookie, GDateTime *expires) { if (cookie->expires) - soup_date_free (cookie->expires); + g_date_time_unref (cookie->expires); if (expires) - cookie->expires = soup_date_copy (expires); + cookie->expires = g_date_time_ref (expires); else cookie->expires = NULL; } @@ -745,8 +749,8 @@ serialize_cookie (SoupCookie *cookie, GString *header, gboolean set_cookie) char *timestamp; g_string_append (header, "; expires="); - timestamp = soup_date_to_string (cookie->expires, - SOUP_DATE_COOKIE); + timestamp = soup_date_time_to_string (cookie->expires, + SOUP_DATE_COOKIE); g_string_append (header, timestamp); g_free (timestamp); } @@ -872,7 +876,7 @@ soup_cookie_free (SoupCookie *cookie) g_free (cookie->value); g_free (cookie->domain); g_free (cookie->path); - g_clear_pointer (&cookie->expires, soup_date_free); + g_clear_pointer (&cookie->expires, g_date_time_unref); g_dataset_destroy (cookie); g_slice_free (SoupCookie, cookie); @@ -1085,7 +1089,7 @@ soup_cookie_applies_to_uri (SoupCookie *cookie, SoupURI *uri) if (cookie->secure && !soup_uri_is_https (uri, NULL)) return FALSE; - if (cookie->expires && soup_date_is_past (cookie->expires)) + if (cookie->expires && soup_date_time_is_past (cookie->expires)) return FALSE; /* uri->path is required to be non-NULL */ diff --git a/libsoup/cookies/soup-cookie.h b/libsoup/cookies/soup-cookie.h index eb533a55..7f514d1f 100644 --- a/libsoup/cookies/soup-cookie.h +++ b/libsoup/cookies/soup-cookie.h @@ -24,13 +24,13 @@ typedef enum { } SoupSameSitePolicy; struct _SoupCookie { - char *name; - char *value; - char *domain; - char *path; - SoupDate *expires; - gboolean secure; - gboolean http_only; + char *name; + char *value; + char *domain; + char *path; + GDateTime *expires; + gboolean secure; + gboolean http_only; }; SOUP_AVAILABLE_IN_2_24 @@ -78,10 +78,10 @@ SOUP_AVAILABLE_IN_2_24 void soup_cookie_set_max_age (SoupCookie *cookie, int max_age); SOUP_AVAILABLE_IN_2_32 -SoupDate *soup_cookie_get_expires (SoupCookie *cookie); +GDateTime *soup_cookie_get_expires (SoupCookie *cookie); SOUP_AVAILABLE_IN_2_24 void soup_cookie_set_expires (SoupCookie *cookie, - SoupDate *expires); + GDateTime *expires); SOUP_AVAILABLE_IN_2_32 gboolean soup_cookie_get_secure (SoupCookie *cookie); SOUP_AVAILABLE_IN_2_24 diff --git a/libsoup/hsts/soup-hsts-enforcer-db.c b/libsoup/hsts/soup-hsts-enforcer-db.c index 1caa46bf..fd1a6997 100644 --- a/libsoup/hsts/soup-hsts-enforcer-db.c +++ b/libsoup/hsts/soup-hsts-enforcer-db.c @@ -148,7 +148,7 @@ query_all_callback (void *data, int argc, char **argv, char **colname) gulong expire_time; unsigned long max_age; time_t now; - SoupDate *expires; + GDateTime *expires; gboolean include_subdomains = FALSE; now = time (NULL); @@ -159,7 +159,7 @@ query_all_callback (void *data, int argc, char **argv, char **colname) if (now >= expire_time) return 0; - expires = soup_date_new_from_time_t (expire_time); + expires = g_date_time_new_from_unix_utc (expire_time); max_age = strtoul (argv[COL_MAX_AGE], NULL, 10); include_subdomains = (g_strcmp0 (argv[COL_SUBDOMAINS], "1") == 0); @@ -169,7 +169,7 @@ query_all_callback (void *data, int argc, char **argv, char **colname) soup_hsts_enforcer_set_policy (hsts_enforcer, policy); soup_hsts_policy_free (policy); } else - soup_date_free (expires); + g_date_time_unref (expires); return 0; } @@ -277,7 +277,7 @@ soup_hsts_enforcer_db_changed (SoupHSTSEnforcer *hsts_enforcer, if (new_policy && new_policy->expires) { gulong expires; - expires = (gulong)soup_date_to_time_t (new_policy->expires); + expires = (gulong)g_date_time_to_unix (new_policy->expires); query = sqlite3_mprintf (QUERY_INSERT, new_policy->domain, new_policy->domain, diff --git a/libsoup/hsts/soup-hsts-policy.c b/libsoup/hsts/soup-hsts-policy.c index 3158143a..39bce01d 100644 --- a/libsoup/hsts/soup-hsts-policy.c +++ b/libsoup/hsts/soup-hsts-policy.c @@ -15,6 +15,7 @@ #include <string.h> #include "soup-hsts-policy.h" +#include "soup-date-utils-private.h" #include "soup.h" /** @@ -76,7 +77,7 @@ soup_hsts_policy_copy (SoupHSTSPolicy *policy) copy->domain = g_strdup (policy->domain); copy->max_age = policy->max_age; copy->expires = policy->expires ? - soup_date_copy (policy->expires) : NULL; + g_date_time_ref (policy->expires) : NULL; copy->include_subdomains = policy->include_subdomains; return copy; @@ -113,8 +114,7 @@ soup_hsts_policy_equal (SoupHSTSPolicy *policy1, SoupHSTSPolicy *policy2) return FALSE; if (policy1->expires && policy2->expires && - soup_date_to_time_t (policy1->expires) != - soup_date_to_time_t (policy2->expires)) + !g_date_time_equal (policy1->expires, policy2->expires)) return FALSE; return TRUE; @@ -158,15 +158,18 @@ soup_hsts_policy_new (const char *domain, unsigned long max_age, gboolean include_subdomains) { - SoupDate *expires; + GDateTime *expires; if (max_age == SOUP_HSTS_POLICY_MAX_AGE_PAST) { /* Use a date way in the past, to protect against * clock skew. */ - expires = soup_date_new (1970, 1, 1, 0, 0, 0); - } else - expires = soup_date_new_from_now (max_age); + expires = g_date_time_new_from_unix_utc (0); + } else { + GDateTime *now = g_date_time_new_now_utc (); + expires = g_date_time_add_seconds (now, max_age); + g_date_time_unref (now); + } return soup_hsts_policy_new_full (domain, max_age, expires, include_subdomains); } @@ -188,7 +191,7 @@ soup_hsts_policy_new (const char *domain, SoupHSTSPolicy * soup_hsts_policy_new_full (const char *domain, unsigned long max_age, - SoupDate *expires, + GDateTime *expires, gboolean include_subdomains) { SoupHSTSPolicy *policy; @@ -208,7 +211,7 @@ soup_hsts_policy_new_full (const char *domain, } policy->max_age = max_age; - policy->expires = expires; + policy->expires = expires ? g_date_time_ref (expires) : NULL; policy->include_subdomains = include_subdomains; return policy; @@ -345,7 +348,7 @@ soup_hsts_policy_is_expired (SoupHSTSPolicy *policy) { g_return_val_if_fail (policy != NULL, TRUE); - return policy->expires && soup_date_is_past (policy->expires); + return policy->expires && soup_date_time_is_past (policy->expires); } /** @@ -399,6 +402,6 @@ soup_hsts_policy_free (SoupHSTSPolicy *policy) g_return_if_fail (policy != NULL); g_free (policy->domain); - g_clear_pointer (&policy->expires, soup_date_free); + g_clear_pointer (&policy->expires, g_date_time_unref); g_slice_free (SoupHSTSPolicy, policy); } diff --git a/libsoup/hsts/soup-hsts-policy.h b/libsoup/hsts/soup-hsts-policy.h index b55f496b..4879f282 100644 --- a/libsoup/hsts/soup-hsts-policy.h +++ b/libsoup/hsts/soup-hsts-policy.h @@ -13,7 +13,7 @@ G_BEGIN_DECLS struct _SoupHSTSPolicy { char *domain; unsigned long max_age; - SoupDate *expires; + GDateTime *expires; gboolean include_subdomains; }; @@ -30,7 +30,7 @@ SoupHSTSPolicy *soup_hsts_policy_new (const char *domain, SOUP_AVAILABLE_IN_2_68 SoupHSTSPolicy *soup_hsts_policy_new_full (const char *domain, unsigned long max_age, - SoupDate *expires, + GDateTime *expires, gboolean include_subdomains); SOUP_AVAILABLE_IN_2_68 SoupHSTSPolicy *soup_hsts_policy_new_session_policy (const char *domain, diff --git a/libsoup/include/soup-installed.h b/libsoup/include/soup-installed.h index c1e45b01..1abe966e 100644 --- a/libsoup/include/soup-installed.h +++ b/libsoup/include/soup-installed.h @@ -28,7 +28,7 @@ extern "C" { #include <libsoup/soup-cookie-jar.h> #include <libsoup/soup-cookie-jar-db.h> #include <libsoup/soup-cookie-jar-text.h> -#include <libsoup/soup-date.h> +#include <libsoup/soup-date-utils.h> #include <libsoup/soup-enum-types.h> #include <libsoup/soup-form.h> #include <libsoup/soup-headers.h> diff --git a/libsoup/meson.build b/libsoup/meson.build index 8c991547..d353e927 100644 --- a/libsoup/meson.build +++ b/libsoup/meson.build @@ -50,7 +50,7 @@ soup_sources = [ 'soup-body-output-stream.c', 'soup-client-input-stream.c', 'soup-connection.c', - 'soup-date.c', + 'soup-date-utils.c', 'soup-directory-input-stream.c', 'soup-filter-input-stream.c', 'soup-form.c', @@ -121,7 +121,7 @@ soup_introspection_headers = [ 'websocket/soup-websocket-extension-deflate.h', 'websocket/soup-websocket-extension-manager.h', - 'soup-date.h', + 'soup-date-utils.h', 'soup-form.h', 'soup-headers.h', 'soup-logger.h', diff --git a/libsoup/soup-date-utils-private.h b/libsoup/soup-date-utils-private.h new file mode 100644 index 00000000..568b11a3 --- /dev/null +++ b/libsoup/soup-date-utils-private.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2020 Igalia, S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include "soup-types.h" + +G_BEGIN_DECLS + +gboolean soup_date_time_is_past (GDateTime *date); + +G_END_DECLS + + diff --git a/libsoup/soup-date-utils.c b/libsoup/soup-date-utils.c new file mode 100644 index 00000000..7884f068 --- /dev/null +++ b/libsoup/soup-date-utils.c @@ -0,0 +1,329 @@ +/* + * Copyright (C) 2020 Igalia, S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "soup-date-utils.h" +#include "soup-date-utils-private.h" + +/** + * soup_date_time_is_past: + * @date: a #GDateTime + * + * Determines if @date is in the past. + * + * Return value: %TRUE if @date is in the past + */ +gboolean +soup_date_time_is_past (GDateTime *date) +{ + g_return_val_if_fail (date != NULL, TRUE); + + /* optimization */ + if (g_date_time_get_year (date) < 2020) + return TRUE; + + return g_date_time_to_unix (date) < time (NULL); +} + +/** + * SoupDateFormat: + * @SOUP_DATE_HTTP: RFC 1123 format, used by the HTTP "Date" header. Eg + * "Sun, 06 Nov 1994 08:49:37 GMT" + * @SOUP_DATE_COOKIE: The format for the "Expires" timestamp in the + * Netscape cookie specification. Eg, "Sun, 06-Nov-1994 08:49:37 GMT". + * + * Date formats that soup_date_time_to_string() can use. + * + * @SOUP_DATE_HTTP and @SOUP_DATE_COOKIE always coerce the time to + * UTC. + * + * This enum may be extended with more values in future releases. + **/ + +/* Do not internationalize */ +static const char *const months[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +/* Do not internationalize */ +static const char *const days[] = { + "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" +}; + +/** + * soup_date_time_to_string: + * @date: a #GDateTime + * @format: the format to generate the date in + * + * Converts @date to a string in the format described by @format. + * + * Return: (transfer full): @date as a string or %NULL + **/ +char * +soup_date_time_to_string (GDateTime *date, + SoupDateFormat format) +{ + g_return_val_if_fail (date != NULL, NULL); + + if (format == SOUP_DATE_HTTP || format == SOUP_DATE_COOKIE) { + /* HTTP and COOKIE formats require UTC timestamp, so coerce + * @date if it's non-UTC. + */ + GDateTime *utcdate = g_date_time_to_utc (date); + char *date_format; + char *formatted_date; + + // We insert days/months ourselves to avoid locale specific formatting + if (format == SOUP_DATE_HTTP) { + /* "Sun, 06 Nov 1994 08:49:37 GMT" */ + date_format = g_strdup_printf ("%s, %%d %s %%Y %%T GMT", + days[g_date_time_get_day_of_week (utcdate) - 1], + months[g_date_time_get_month (utcdate) - 1]); + } else { + /* "Sun, 06-Nov-1994 08:49:37 GMT" */ + date_format = g_strdup_printf ("%s, %%d-%s-%%Y %%T GMT", + days[g_date_time_get_day_of_week (utcdate) - 1], + months[g_date_time_get_month (utcdate) - 1]); + } + + formatted_date = g_date_time_format (utcdate, (const char*)date_format); + g_date_time_unref (utcdate); + g_free (date_format); + return formatted_date; + } + + g_return_val_if_reached (NULL); +} + +static inline gboolean +parse_day (int *day, const char **date_string) +{ + char *end; + + *day = strtoul (*date_string, &end, 10); + if (end == (char *)*date_string) + return FALSE; + + while (*end == ' ' || *end == '-') + end++; + *date_string = end; + return TRUE; +} + +static inline gboolean +parse_month (int *month, const char **date_string) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (months); i++) { + if (!g_ascii_strncasecmp (*date_string, months[i], 3)) { + *month = i + 1; + *date_string += 3; + while (**date_string == ' ' || **date_string == '-') + (*date_string)++; + return TRUE; + } + } + return FALSE; +} + +static inline gboolean +parse_year (int *year, const char **date_string) +{ + char *end; + + *year = strtoul (*date_string, &end, 10); + if (end == (char *)*date_string) + return FALSE; + + if (end == (char *)*date_string + 2) { + if (*year < 70) + *year += 2000; + else + *year += 1900; + } else if (end == (char *)*date_string + 3) + *year += 1900; + + while (*end == ' ' || *end == '-') + end++; + *date_string = end; + return TRUE; +} + +static inline gboolean +parse_time (int *hour, int *minute, int *second, const char **date_string) +{ + char *p, *end; + + *hour = strtoul (*date_string, &end, 10); + if (end == (char *)*date_string || *end++ != ':') + return FALSE; + p = end; + *minute = strtoul (p, &end, 10); + if (end == p || *end++ != ':') + return FALSE; + p = end; + *second = strtoul (p, &end, 10); + if (end == p) + return FALSE; + p = end; + + while (*p == ' ') + p++; + *date_string = p; + return TRUE; +} + +static inline gboolean +parse_timezone (GTimeZone **timezone, const char **date_string) +{ + gint32 offset_minutes; + gboolean utc; + + if (!**date_string) { + utc = FALSE; + offset_minutes = 0; + } else if (**date_string == '+' || **date_string == '-') { + gulong val; + int sign = (**date_string == '+') ? 1 : -1; + val = strtoul (*date_string + 1, (char **)date_string, 10); + if (**date_string == ':') + val = 60 * val + strtoul (*date_string + 1, (char **)date_string, 10); + else + val = 60 * (val / 100) + (val % 100); + offset_minutes = sign * val; + utc = (sign == -1) && !val; + } else if (**date_string == 'Z') { + offset_minutes = 0; + utc = TRUE; + (*date_string)++; + } else if (!strcmp (*date_string, "GMT") || + !strcmp (*date_string, "UTC")) { + offset_minutes = 0; + utc = TRUE; + (*date_string) += 3; + } else if (strchr ("ECMP", **date_string) && + ((*date_string)[1] == 'D' || (*date_string)[1] == 'S') && + (*date_string)[2] == 'T') { + offset_minutes = -60 * (5 * strcspn ("ECMP", *date_string)); + if ((*date_string)[1] == 'D') + offset_minutes += 60; + utc = FALSE; + } else + return FALSE; + + if (utc) + *timezone = g_time_zone_new_utc (); + else + *timezone = g_time_zone_new_offset (offset_minutes * 60); + return TRUE; +} + +static GDateTime * +parse_textual_date (const char *date_string) +{ + int month, day, year, hour, minute, second; + GTimeZone *tz = NULL; + GDateTime *date; + + /* If it starts with a word, it must be a weekday, which we skip */ + if (g_ascii_isalpha (*date_string)) { + while (g_ascii_isalpha (*date_string)) + date_string++; + if (*date_string == ',') + date_string++; + while (g_ascii_isspace (*date_string)) + date_string++; + } + + /* If there's now another word, this must be an asctime-date */ + if (g_ascii_isalpha (*date_string)) { + /* (Sun) Nov 6 08:49:37 1994 */ + if (!parse_month (&month, &date_string) || + !parse_day (&day, &date_string) || + !parse_time (&hour, &minute, &second, &date_string) || + !parse_year (&year, &date_string)) + return NULL; + + /* There shouldn't be a timezone, but check anyway */ + parse_timezone (&tz, &date_string); + } else { + /* Non-asctime date, so some variation of + * (Sun,) 06 Nov 1994 08:49:37 GMT + */ + if (!parse_day (&day, &date_string) || + !parse_month (&month, &date_string) || + !parse_year (&year, &date_string) || + !parse_time (&hour, &minute, &second, &date_string)) + return NULL; + + /* This time there *should* be a timezone, but we + * survive if there isn't. + */ + parse_timezone (&tz, &date_string); + } + + if (!tz) + tz = g_time_zone_new_utc (); + + date = g_date_time_new (tz, year, month, day, hour, minute, second); + g_time_zone_unref (tz); + + return date; +} + +/** + * soup_date_time_new_from_http_string: + * @date_string: The date as a string + * + * Parses @date_string and tries to extract a date from it. This + * recognizes all of the "HTTP-date" formats from RFC 2616, RFC 2822 + * dates, and reasonable approximations thereof. (Eg, it is lenient about + * whitespace, leading "0"s, etc.) + * + * Return value: (nullable): a new #GDateTime, or %NULL if @date_string + * could not be parsed. + **/ +GDateTime * +soup_date_time_new_from_http_string (const char *date_string) +{ + g_return_val_if_fail (date_string != NULL, NULL); + + while (g_ascii_isspace (*date_string)) + date_string++; + + /* If it starts with a digit, it's either an ISO 8601 date, or + * an RFC2822 date without the optional weekday; in the later + * case, there will be a month name later on, so look for one + * of the month-start letters. + * Previous versions of this library supported parsing iso8601 strings + * however g_date_time_new_from_iso8601() should be used now. Just + * catch those in case for testing. + */ + if (G_UNLIKELY (g_ascii_isdigit (*date_string) && !strpbrk (date_string, "JFMASOND"))) { + g_debug ("Unsupported format passed to soup_date_time_new_from_http_string(): %s", date_string); + return NULL; + } + + return parse_textual_date (date_string); +} diff --git a/libsoup/soup-date-utils.h b/libsoup/soup-date-utils.h new file mode 100644 index 00000000..dbd4581c --- /dev/null +++ b/libsoup/soup-date-utils.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 Igalia, S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include "soup-types.h" + +G_BEGIN_DECLS + +typedef enum { + SOUP_DATE_HTTP = 1, + SOUP_DATE_COOKIE, +} SoupDateFormat; + +SOUP_AVAILABLE_IN_2_70 +char *soup_date_time_to_string (GDateTime *date, + SoupDateFormat format); + +SOUP_AVAILABLE_IN_2_70 +GDateTime *soup_date_time_new_from_http_string (const char *date_string); + +G_END_DECLS diff --git a/libsoup/soup-date.c b/libsoup/soup-date.c deleted file mode 100644 index aa116724..00000000 --- a/libsoup/soup-date.c +++ /dev/null @@ -1,911 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * soup-date.c: Date/time handling - * - * Copyright (C) 2005, Novell, Inc. - * Copyright (C) 2007, Red Hat, Inc. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <string.h> - -#include "soup-date.h" -#include "soup.h" - -/** - * SoupDate: - * @year: the year, 1 to 9999 - * @month: the month, 1 to 12 - * @day: day of the month, 1 to 31 - * @hour: hour of the day, 0 to 23 - * @minute: minute, 0 to 59 - * @second: second, 0 to 59 (or up to 61 in the case of leap seconds) - * @utc: %TRUE if the date is in UTC - * @offset: offset from UTC - - * A date and time. The date is assumed to be in the (proleptic) - * Gregorian calendar. The time is in UTC if @utc is %TRUE. Otherwise, - * the time is a local time, and @offset gives the offset from UTC in - * minutes (such that adding @offset to the time would give the - * correct UTC time). If @utc is %FALSE and @offset is 0, then the - * %SoupDate represents a "floating" time with no associated timezone - * information. - **/ - -/* Do not internationalize */ -static const char *const months[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -/* Do not internationalize */ -static const char *const days[] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -}; - -static const int nonleap_days_in_month[] = { - 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -}; - -static const int nonleap_days_before[] = { - 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 -}; - -static inline gboolean -is_leap_year (int year) -{ - return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); -} - -/* Computes the number of days since proleptic Gregorian 0000-12-31. - * (That is, 0001-01-01 is "1", and 1970-01-01 is 719163. - */ -static int -rata_die_day (SoupDate *date) -{ - int day; - - day = (date->year - 1) * 365 + ((date->year - 1) / 4) - - ((date->year - 1) / 100) + ((date->year - 1) / 400); - day += nonleap_days_before[date->month] + date->day; - if (is_leap_year (date->year) && date->month > 2) - day++; - return day; -} - -#define TIME_T_EPOCH_RATA_DIE_DAY 719163 - -static inline int -days_in_month (int month, int year) -{ - if (month == 2 && is_leap_year (year)) - return 29; - else - return nonleap_days_in_month[month]; -} - -G_DEFINE_BOXED_TYPE (SoupDate, soup_date, soup_date_copy, soup_date_free) - -static void -soup_date_fixup (SoupDate *date) -{ - /* We only correct date->second if it's negative or too high - * to be a leap second. - */ - if (date->second < 0 || date->second > 61) { - date->minute += date->second / 60; - date->second %= 60; - if (date->second < 0) - date->second += 60; - } - - if (date->minute < 0 || date->minute > 59) { - date->hour += date->minute / 60; - date->minute %= 60; - if (date->minute < 0) - date->minute += 60; - } - - if (date->hour < 0 || date->hour > 23) { - date->day += date->hour / 24; - date->hour %= 24; - if (date->hour < 0) - date->hour += 24; - } - - /* Have to make sure month is valid before we can look at the - * day. - */ - if (date->month < 1 || date->month > 12) { - date->year += ((date->month - 1) / 12) + 1; - date->month = ((date->month - 1) % 12) + 1; - if (date->month < 1) - date->month += 12; - } - - if (date->day < 0) { - while (date->day < 0) { - if (date->month == 1) { - date->month = 12; - date->year--; - } else - date->month--; - date->day += days_in_month (date->month, date->year); - } - } else { - while (date->day > days_in_month (date->month, date->year)) { - date->day -= days_in_month (date->month, date->year); - if (date->month == 12) { - date->month = 1; - date->year++; - } else - date->month++; - } - } -} - -/** - * soup_date_new: - * @year: the year (1-9999) - * @month: the month (1-12) - * @day: the day of the month (1-31, as appropriate for @month) - * @hour: the hour (0-23) - * @minute: the minute (0-59) - * @second: the second (0-59, or up to 61 for leap seconds) - * - * Creates a #SoupDate representing the indicated time, UTC. - * - * Return value: a new #SoupDate - **/ -SoupDate * -soup_date_new (int year, int month, int day, - int hour, int minute, int second) -{ - SoupDate *date = g_slice_new (SoupDate); - - date->year = year; - date->month = month; - date->day = day; - date->hour = hour; - date->minute = minute; - date->second = second; - date->utc = TRUE; - date->offset = 0; - - return date; -} - -/** - * soup_date_new_from_now: - * @offset_seconds: offset from current time - * - * Creates a #SoupDate representing a time @offset_seconds after the - * current time (or before it, if @offset_seconds is negative). If - * offset_seconds is 0, returns the current time. - * - * If @offset_seconds would indicate a time not expressible as a - * <type>time_t</type>, the return value will be clamped into range. - * - * Return value: a new #SoupDate - **/ -SoupDate * -soup_date_new_from_now (int offset_seconds) -{ - time_t now = time (NULL); - time_t then = now + offset_seconds; - - if (sizeof (time_t) == 4) { - if (offset_seconds < 0 && then > now) - return soup_date_new_from_time_t (-G_MAXINT); - else if (offset_seconds > 0 && then < now) - return soup_date_new_from_time_t (G_MAXINT); - } - return soup_date_new_from_time_t (then); -} - -static gboolean -parse_iso8601_date (SoupDate *date, const char *date_string) -{ - gulong val; - - if (strlen (date_string) < 15) - return FALSE; - if (date_string[4] == '-' && - date_string[7] == '-' && - date_string[10] == 'T') { - /* YYYY-MM-DD */ - date->year = atoi (date_string); - date->month = atoi (date_string + 5); - date->day = atoi (date_string + 8); - date_string += 11; - } else if (date_string[8] == 'T') { - /* YYYYMMDD */ - val = atoi (date_string); - date->year = val / 10000; - date->month = (val % 10000) / 100; - date->day = val % 100; - date_string += 9; - } else - return FALSE; - - if (strlen (date_string) >= 8 && - date_string[2] == ':' && date_string[5] == ':') { - /* HH:MM:SS */ - date->hour = atoi (date_string); - date->minute = atoi (date_string + 3); - date->second = atoi (date_string + 6); - date_string += 8; - } else if (strlen (date_string) >= 6) { - /* HHMMSS */ - val = strtoul (date_string, (char **)&date_string, 10); - date->hour = val / 10000; - date->minute = (val % 10000) / 100; - date->second = val % 100; - } else - return FALSE; - - if (*date_string == '.' || *date_string == ',') - (void) strtoul (date_string + 1, (char **)&date_string, 10); - - if (*date_string == 'Z') { - date_string++; - date->utc = TRUE; - date->offset = 0; - } else if (*date_string == '+' || *date_string == '-') { - int sign = (*date_string == '+') ? -1 : 1; - val = strtoul (date_string + 1, (char **)&date_string, 10); - if (*date_string == ':') - val = 60 * val + strtoul (date_string + 1, (char **)&date_string, 10); - else - val = 60 * (val / 100) + (val % 100); - date->offset = sign * val; - date->utc = !val; - } else { - date->offset = 0; - date->utc = FALSE; - } - - return !*date_string; -} - -static inline gboolean -parse_day (SoupDate *date, const char **date_string) -{ - char *end; - - date->day = strtoul (*date_string, &end, 10); - if (end == (char *)*date_string) - return FALSE; - - while (*end == ' ' || *end == '-') - end++; - *date_string = end; - return TRUE; -} - -static inline gboolean -parse_month (SoupDate *date, const char **date_string) -{ - int i; - - for (i = 0; i < G_N_ELEMENTS (months); i++) { - if (!g_ascii_strncasecmp (*date_string, months[i], 3)) { - date->month = i + 1; - *date_string += 3; - while (**date_string == ' ' || **date_string == '-') - (*date_string)++; - return TRUE; - } - } - return FALSE; -} - -static inline gboolean -parse_year (SoupDate *date, const char **date_string) -{ - char *end; - - date->year = strtoul (*date_string, &end, 10); - if (end == (char *)*date_string) - return FALSE; - - if (end == (char *)*date_string + 2) { - if (date->year < 70) - date->year += 2000; - else - date->year += 1900; - } else if (end == (char *)*date_string + 3) - date->year += 1900; - - while (*end == ' ' || *end == '-') - end++; - *date_string = end; - return TRUE; -} - -static inline gboolean -parse_time (SoupDate *date, const char **date_string) -{ - char *p, *end; - - date->hour = strtoul (*date_string, &end, 10); - if (end == (char *)*date_string || *end++ != ':') - return FALSE; - p = end; - date->minute = strtoul (p, &end, 10); - if (end == p || *end++ != ':') - return FALSE; - p = end; - date->second = strtoul (p, &end, 10); - if (end == p) - return FALSE; - p = end; - - while (*p == ' ') - p++; - *date_string = p; - return TRUE; -} - -static inline gboolean -parse_timezone (SoupDate *date, const char **date_string) -{ - if (!**date_string) { - date->utc = FALSE; - date->offset = 0; - } else if (**date_string == '+' || **date_string == '-') { - gulong val; - int sign = (**date_string == '+') ? -1 : 1; - val = strtoul (*date_string + 1, (char **)date_string, 10); - if (**date_string == ':') - val = 60 * val + strtoul (*date_string + 1, (char **)date_string, 10); - else - val = 60 * (val / 100) + (val % 100); - date->offset = sign * val; - date->utc = (sign == -1) && !val; - } else if (**date_string == 'Z') { - date->offset = 0; - date->utc = TRUE; - (*date_string)++; - } else if (!strcmp (*date_string, "GMT") || - !strcmp (*date_string, "UTC")) { - date->offset = 0; - date->utc = TRUE; - (*date_string) += 3; - } else if (strchr ("ECMP", **date_string) && - ((*date_string)[1] == 'D' || (*date_string)[1] == 'S') && - (*date_string)[2] == 'T') { - date->offset = -60 * (5 * strcspn ("ECMP", *date_string)); - if ((*date_string)[1] == 'D') - date->offset += 60; - date->utc = FALSE; - } else - return FALSE; - return TRUE; -} - -static gboolean -parse_textual_date (SoupDate *date, const char *date_string) -{ - /* If it starts with a word, it must be a weekday, which we skip */ - if (g_ascii_isalpha (*date_string)) { - while (g_ascii_isalpha (*date_string)) - date_string++; - if (*date_string == ',') - date_string++; - while (g_ascii_isspace (*date_string)) - date_string++; - } - - /* If there's now another word, this must be an asctime-date */ - if (g_ascii_isalpha (*date_string)) { - /* (Sun) Nov 6 08:49:37 1994 */ - if (!parse_month (date, &date_string) || - !parse_day (date, &date_string) || - !parse_time (date, &date_string) || - !parse_year (date, &date_string)) - return FALSE; - - /* There shouldn't be a timezone, but check anyway */ - parse_timezone (date, &date_string); - } else { - /* Non-asctime date, so some variation of - * (Sun,) 06 Nov 1994 08:49:37 GMT - */ - if (!parse_day (date, &date_string) || - !parse_month (date, &date_string) || - !parse_year (date, &date_string) || - !parse_time (date, &date_string)) - return FALSE; - - /* This time there *should* be a timezone, but we - * survive if there isn't. - */ - parse_timezone (date, &date_string); - } - return TRUE; -} - -/** - * SoupDateFormat: - * @SOUP_DATE_HTTP: RFC 1123 format, used by the HTTP "Date" header. Eg - * "Sun, 06 Nov 1994 08:49:37 GMT" - * @SOUP_DATE_COOKIE: The format for the "Expires" timestamp in the - * Netscape cookie specification. Eg, "Sun, 06-Nov-1994 08:49:37 GMT". - * @SOUP_DATE_RFC2822: RFC 2822 format, eg "Sun, 6 Nov 1994 09:49:37 -0100" - * @SOUP_DATE_ISO8601_COMPACT: ISO 8601 date/time with no optional - * punctuation. Eg, "19941106T094937-0100". - * @SOUP_DATE_ISO8601_FULL: ISO 8601 date/time with all optional - * punctuation. Eg, "1994-11-06T09:49:37-01:00". - * @SOUP_DATE_ISO8601_XMLRPC: ISO 8601 date/time as used by XML-RPC. - * Eg, "19941106T09:49:37". - * @SOUP_DATE_ISO8601: An alias for @SOUP_DATE_ISO8601_FULL. - * - * Date formats that soup_date_to_string() can use. - * - * @SOUP_DATE_HTTP and @SOUP_DATE_COOKIE always coerce the time to - * UTC. @SOUP_DATE_ISO8601_XMLRPC uses the time as given, ignoring the - * offset completely. @SOUP_DATE_RFC2822 and the other ISO 8601 - * variants use the local time, appending the offset information if - * available. - * - * This enum may be extended with more values in future releases. - **/ - -/** - * soup_date_new_from_string: - * @date_string: the date in some plausible format - * - * Parses @date_string and tries to extract a date from it. This - * recognizes all of the "HTTP-date" formats from RFC 2616, all ISO - * 8601 formats containing both a time and a date, RFC 2822 dates, - * and reasonable approximations thereof. (Eg, it is lenient about - * whitespace, leading "0"s, etc.) - * - * Return value: (nullable): a new #SoupDate, or %NULL if @date_string - * could not be parsed. - **/ -SoupDate * -soup_date_new_from_string (const char *date_string) -{ - SoupDate *date; - gboolean success; - - g_return_val_if_fail (date_string != NULL, NULL); - - date = g_slice_new (SoupDate); - - while (g_ascii_isspace (*date_string)) - date_string++; - - /* If it starts with a digit, it's either an ISO 8601 date, or - * an RFC2822 date without the optional weekday; in the later - * case, there will be a month name later on, so look for one - * of the month-start letters. - */ - if (g_ascii_isdigit (*date_string) && - !strpbrk (date_string, "JFMASOND")) - success = parse_iso8601_date (date, date_string); - else - success = parse_textual_date (date, date_string); - - if (!success) { - g_slice_free (SoupDate, date); - return NULL; - } - - if (date->year < 1 || date->year > 9999 || - date->month < 1 || date->month > 12 || - date->day < 1 || - date->day > days_in_month (date->month, date->year) || - date->hour < 0 || date->hour > 24 || - date->minute < 0 || date->minute > 59 || - date->second < 0 || date->second > 61) { - soup_date_free (date); - return NULL; - } - if (date->hour == 24) { - /* ISO8601 allows this explicitly. We allow it for - * other types as well just for simplicity. - */ - if (date->minute == 0 && date->second == 0) - soup_date_fixup (date); - else { - soup_date_free (date); - return NULL; - } - } - - return date; -} - -/** - * soup_date_new_from_time_t: - * @when: a <type>time_t</type> - * - * Creates a #SoupDate corresponding to @when - * - * Return value: a new #SoupDate - **/ -SoupDate * -soup_date_new_from_time_t (time_t when) -{ - struct tm tm; - -#ifdef HAVE_GMTIME_R - gmtime_r (&when, &tm); -#else - tm = *gmtime (&when); -#endif - - return soup_date_new (tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); -} - -static const char * -soup_date_weekday (SoupDate *date) -{ - /* Proleptic Gregorian 0001-01-01 was a Monday, which - * corresponds to 1 in the days[] array. - */ - return days[rata_die_day (date) % 7]; -} - -/** - * soup_date_to_string: - * @date: a #SoupDate - * @format: the format to generate the date in - * - * Converts @date to a string in the format described by @format. - * - * Return value: @date as a string - **/ -char * -soup_date_to_string (SoupDate *date, SoupDateFormat format) -{ - g_return_val_if_fail (date != NULL, NULL); - - if (format == SOUP_DATE_HTTP || format == SOUP_DATE_COOKIE) { - /* HTTP and COOKIE formats require UTC timestamp, so coerce - * @date if it's non-UTC. - */ - SoupDate utcdate; - - if (date->offset != 0) { - memcpy (&utcdate, date, sizeof (SoupDate)); - utcdate.minute += utcdate.offset; - utcdate.offset = 0; - utcdate.utc = TRUE; - soup_date_fixup (&utcdate); - date = &utcdate; - } - - switch (format) { - case SOUP_DATE_HTTP: - /* "Sun, 06 Nov 1994 08:49:37 GMT" */ - return g_strdup_printf ( - "%s, %02d %s %04d %02d:%02d:%02d GMT", - soup_date_weekday (date), date->day, - months[date->month - 1], date->year, - date->hour, date->minute, date->second); - - case SOUP_DATE_COOKIE: - /* "Sun, 06-Nov-1994 08:49:37 GMT" */ - return g_strdup_printf ( - "%s, %02d-%s-%04d %02d:%02d:%02d GMT", - soup_date_weekday (date), date->day, - months[date->month - 1], date->year, - date->hour, date->minute, date->second); - - default: - g_return_val_if_reached (NULL); - } - } else if (format == SOUP_DATE_ISO8601_XMLRPC) { - /* Always "floating", ignore offset */ - return g_strdup_printf ("%04d%02d%02dT%02d:%02d:%02d", - date->year, date->month, date->day, - date->hour, date->minute, date->second); - } else { - int hour_offset, minute_offset; - char zone[8], sign; - - /* For other ISO8601 formats or RFC2822, use the - * offset given in @date. For ISO8601 formats, use "Z" - * for UTC, +-offset for non-UTC, and nothing for - * floating. For RFC2822, use +-offset for UTC or - * non-UTC, and -0000 for floating. - */ - hour_offset = abs (date->offset) / 60; - minute_offset = abs (date->offset) - hour_offset * 60; - - switch (format) { - case SOUP_DATE_ISO8601_COMPACT: - /* "19941106T084937[zone]" */ - if (date->utc) - strcpy (zone, "Z"); - else if (date->offset) { - g_snprintf (zone, sizeof (zone), "%c%02d%02d", - date->offset > 0 ? '-' : '+', - hour_offset, minute_offset); - } else - *zone = '\0'; - - return g_strdup_printf ( - "%04d%02d%02dT%02d%02d%02d%s", - date->year, date->month, date->day, - date->hour, date->minute, date->second, - zone); - - case SOUP_DATE_ISO8601_FULL: - /* "1994-11-06T08:49:37[zone]" */ - if (date->utc) - strcpy (zone, "Z"); - else if (date->offset) { - g_snprintf (zone, sizeof (zone), "%c%02d:%02d", - date->offset > 0 ? '-' : '+', - hour_offset, minute_offset); - } else - *zone = '\0'; - - return g_strdup_printf ( - "%04d-%02d-%02dT%02d:%02d:%02d%s", - date->year, date->month, date->day, - date->hour, date->minute, date->second, - zone); - - case SOUP_DATE_RFC2822: - /* "Sun, 6 Nov 1994 09:49:37 -0100" */ - if (date->offset) - sign = (date->offset > 0) ? '-' : '+'; - else - sign = date->utc ? '+' : '-'; - return g_strdup_printf ( - "%s, %d %s %04d %02d:%02d:%02d %c%02d%02d", - soup_date_weekday (date), date->day, - months[date->month - 1], date->year, - date->hour, date->minute, date->second, - sign, hour_offset, minute_offset); - - default: - return NULL; - } - } -} - -/** - * soup_date_to_time_t: - * @date: a #SoupDate - * - * Converts @date to a <type>time_t</type>, assumming it to be in - * UTC. - * - * If @date is not representable as a <type>time_t</type>, it will be - * clamped into range. (In particular, some HTTP cookies have - * expiration dates after "Y2.038k" (2038-01-19T03:14:07Z).) - * - * Return value: @date as a <type>time_t</type> - **/ -time_t -soup_date_to_time_t (SoupDate *date) -{ - GDateTime *datetime; - gint64 seconds; - - g_return_val_if_fail (date != NULL, 0); - - if (date->year < 1970) - return 0; - - /* If the year is later than 2038, we're guaranteed to - * overflow a 32-bit time_t. (If it's exactly 2038, we'll - * *probably* overflow, but only by a little, and it's easiest - * to just clamp down the value if it's above G_MAXINT32. - */ - if (sizeof (time_t) == 4 && date->year > 2038) - return (time_t)G_MAXINT32; - - datetime = g_date_time_new_utc (date->year, - date->month, - date->day, - date->hour, - date->minute, - date->second); - - seconds = g_date_time_to_unix (datetime); - - g_date_time_unref (datetime); - - return (time_t) (sizeof (time_t) == 4 ? MIN(seconds, G_MAXINT32) : seconds); -} - -/** - * soup_date_is_past: - * @date: a #SoupDate - * - * Determines if @date is in the past. - * - * Return value: %TRUE if @date is in the past - * - * Since: 2.24 - **/ -gboolean -soup_date_is_past (SoupDate *date) -{ - g_return_val_if_fail (date != NULL, TRUE); - - /* optimization */ - if (date->year < 2020) - return TRUE; - - return soup_date_to_time_t (date) < time (NULL); -} - -/** - * soup_date_get_year: - * @date: a #SoupDate - * - * Gets @date's year. - * - * Return value: @date's year - * - * Since: 2.32 - **/ -int -soup_date_get_year (SoupDate *date) -{ - return date->year; -} - -/** - * soup_date_get_month: - * @date: a #SoupDate - * - * Gets @date's month. - * - * Return value: @date's month - * - * Since: 2.32 - **/ -int -soup_date_get_month (SoupDate *date) -{ - return date->month; -} - -/** - * soup_date_get_day: - * @date: a #SoupDate - * - * Gets @date's day. - * - * Return value: @date's day - * - * Since: 2.32 - **/ -int -soup_date_get_day (SoupDate *date) -{ - return date->day; -} - -/** - * soup_date_get_hour: - * @date: a #SoupDate - * - * Gets @date's hour. - * - * Return value: @date's hour - * - * Since: 2.32 - **/ -int -soup_date_get_hour (SoupDate *date) -{ - return date->hour; -} - -/** - * soup_date_get_minute: - * @date: a #SoupDate - * - * Gets @date's minute. - * - * Return value: @date's minute - * - * Since: 2.32 - **/ -int -soup_date_get_minute (SoupDate *date) -{ - return date->minute; -} - -/** - * soup_date_get_second: - * @date: a #SoupDate - * - * Gets @date's second. - * - * Return value: @date's second - * - * Since: 2.32 - **/ -int -soup_date_get_second (SoupDate *date) -{ - return date->second; -} - -/** - * soup_date_get_utc: - * @date: a #SoupDate - * - * Gets @date's UTC flag - * - * Return value: %TRUE if @date is UTC. - * - * Since: 2.32 - **/ -gboolean -soup_date_get_utc (SoupDate *date) -{ - return date->utc; -} - -/** - * soup_date_get_offset: - * @date: a #SoupDate - * - * Gets @date's offset from UTC. - * - * Return value: @date's offset from UTC. If soup_date_get_utc() - * returns %FALSE but soup_date_get_offset() returns 0, that means the - * date is a "floating" time with no associated offset information. - * - * Since: 2.32 - **/ -int -soup_date_get_offset (SoupDate *date) -{ - return date->offset; -} - -/** - * soup_date_copy: - * @date: a #SoupDate - * - * Copies @date. - * - * Since: 2.24 - **/ -SoupDate * -soup_date_copy (SoupDate *date) -{ - SoupDate *copy; - - g_return_val_if_fail (date != NULL, NULL); - - copy = g_slice_new (SoupDate); - memcpy (copy, date, sizeof (SoupDate)); - return copy; -} - -/** - * soup_date_free: - * @date: a #SoupDate - * - * Frees @date. - * - * Since: 2.24 - **/ -void -soup_date_free (SoupDate *date) -{ - g_return_if_fail (date != NULL); - - g_slice_free (SoupDate, date); -} diff --git a/libsoup/soup-date.h b/libsoup/soup-date.h deleted file mode 100644 index cbb0798f..00000000 --- a/libsoup/soup-date.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2005 Novell, Inc. - * Copyright (C) 2007 Red Hat, Inc. - */ - -#pragma once - -#include <time.h> -#include "soup-types.h" - -G_BEGIN_DECLS - -struct _SoupDate { - int year; - int month; - int day; - - int hour; - int minute; - int second; - - gboolean utc; - int offset; -}; - -typedef enum { - SOUP_DATE_HTTP = 1, - SOUP_DATE_COOKIE, - SOUP_DATE_RFC2822, - SOUP_DATE_ISO8601_COMPACT, - SOUP_DATE_ISO8601_FULL, - SOUP_DATE_ISO8601 = SOUP_DATE_ISO8601_FULL, - SOUP_DATE_ISO8601_XMLRPC -} SoupDateFormat; - -SOUP_AVAILABLE_IN_2_24 -GType soup_date_get_type (void); -#define SOUP_TYPE_DATE (soup_date_get_type ()) - -SOUP_AVAILABLE_IN_2_24 -SoupDate *soup_date_new (int year, - int month, - int day, - int hour, - int minute, - int second); -SOUP_AVAILABLE_IN_2_24 -SoupDate *soup_date_new_from_string (const char *date_string); -SOUP_AVAILABLE_IN_2_24 -SoupDate *soup_date_new_from_time_t (time_t when); -SOUP_AVAILABLE_IN_2_24 -SoupDate *soup_date_new_from_now (int offset_seconds); - -SOUP_AVAILABLE_IN_2_24 -char *soup_date_to_string (SoupDate *date, - SoupDateFormat format); -SOUP_AVAILABLE_IN_2_24 -time_t soup_date_to_time_t (SoupDate *date); - -SOUP_AVAILABLE_IN_2_24 -gboolean soup_date_is_past (SoupDate *date); - -SOUP_AVAILABLE_IN_2_32 -int soup_date_get_year (SoupDate *date); -SOUP_AVAILABLE_IN_2_32 -int soup_date_get_month (SoupDate *date); -SOUP_AVAILABLE_IN_2_32 -int soup_date_get_day (SoupDate *date); -SOUP_AVAILABLE_IN_2_32 -int soup_date_get_hour (SoupDate *date); -SOUP_AVAILABLE_IN_2_32 -int soup_date_get_minute (SoupDate *date); -SOUP_AVAILABLE_IN_2_32 -int soup_date_get_second (SoupDate *date); -SOUP_AVAILABLE_IN_2_32 -int soup_date_get_utc (SoupDate *date); -SOUP_AVAILABLE_IN_2_32 -int soup_date_get_offset (SoupDate *date); - -SOUP_AVAILABLE_IN_2_24 -SoupDate *soup_date_copy (SoupDate *date); -SOUP_AVAILABLE_IN_2_24 -void soup_date_free (SoupDate *date); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (SoupDate, soup_date_free) - -G_END_DECLS diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c index 5e44b6ea..ae2301d4 100644 --- a/libsoup/soup-server.c +++ b/libsoup/soup-server.c @@ -971,7 +971,7 @@ got_headers (SoupMessage *msg, SoupClientContext *client) SoupServerPrivate *priv = soup_server_get_instance_private (server); SoupServerHandler *handler; SoupURI *uri; - SoupDate *date; + GDateTime *date; char *date_string; SoupAuthDomain *domain; GSList *iter; @@ -979,12 +979,12 @@ got_headers (SoupMessage *msg, SoupClientContext *client) char *auth_user; /* Add required response headers */ - date = soup_date_new_from_now (0); - date_string = soup_date_to_string (date, SOUP_DATE_HTTP); + date = g_date_time_new_now_utc (); + date_string = soup_date_time_to_string (date, SOUP_DATE_HTTP); soup_message_headers_replace (msg->response_headers, "Date", date_string); g_free (date_string); - soup_date_free (date); + g_date_time_unref (date); if (msg->status_code != 0) return; diff --git a/libsoup/soup-types.h b/libsoup/soup-types.h index c4cc55b0..a2127122 100644 --- a/libsoup/soup-types.h +++ b/libsoup/soup-types.h @@ -19,7 +19,6 @@ typedef struct _SoupAuth SoupAuth; typedef struct _SoupAuthDomain SoupAuthDomain; typedef struct _SoupCookie SoupCookie; typedef struct _SoupCookieJar SoupCookieJar; -typedef struct _SoupDate SoupDate; typedef struct _SoupHSTSEnforcer SoupHSTSEnforcer; typedef struct _SoupHSTSPolicy SoupHSTSPolicy; typedef struct _SoupMessage SoupMessage; diff --git a/libsoup/soup.h b/libsoup/soup.h index f0511b93..4e4d4a62 100644 --- a/libsoup/soup.h +++ b/libsoup/soup.h @@ -28,7 +28,7 @@ extern "C" { #include "cookies/soup-cookie-jar.h" #include "cookies/soup-cookie-jar-db.h" #include "cookies/soup-cookie-jar-text.h" -#include "soup-date.h" +#include "soup-date-utils.h" #include "soup-enum-types.h" #include "soup-form.h" #include "soup-headers.h" diff --git a/tests/cache-test.c b/tests/cache-test.c index 29b409ff..34e26be8 100644 --- a/tests/cache-test.c +++ b/tests/cache-test.c @@ -55,19 +55,16 @@ server_callback (SoupServer *server, SoupMessage *msg, header = soup_message_headers_get_one (msg->request_headers, "If-Modified-Since"); if (header && last_modified) { - SoupDate *date; - time_t lastmod, check; + GDateTime *modified_date, *header_date; - date = soup_date_new_from_string (last_modified); - lastmod = soup_date_to_time_t (date); - soup_date_free (date); + modified_date = soup_date_time_new_from_http_string (last_modified); + header_date = soup_date_time_new_from_http_string (header); - date = soup_date_new_from_string (header); - check = soup_date_to_time_t (date); - soup_date_free (date); - - if (lastmod <= check) + if (g_date_time_compare (modified_date, header_date) <= 0) status = SOUP_STATUS_NOT_MODIFIED; + + g_date_time_unref (modified_date); + g_date_time_unref (header_date); } header = soup_message_headers_get_one (msg->request_headers, diff --git a/tests/date-test.c b/tests/date-test.c index 97ae221f..27cf6805 100644 --- a/tests/date-test.c +++ b/tests/date-test.c @@ -7,27 +7,27 @@ static void check_ok (gconstpointer data); -static SoupDate * +static GDateTime * make_date (const char *strdate) { char *dup; - SoupDate *date; + GDateTime *date; - /* We do it this way so that if soup_date_new_from_string() + /* We do it this way so that if soup_date_time_new_from_http_string() * reads off the end of the string, it will trigger an error * when valgrinding, rather than just reading the start of the * next const string. */ dup = g_strdup (strdate); - date = soup_date_new_from_string (dup); + date = soup_date_time_new_from_http_string (dup); g_free (dup); return date; } -static SoupDate * +static GDateTime * check_correct_date (const char *strdate) { - SoupDate *date; + GDateTime *date; date = make_date (strdate); if (!date) { @@ -35,12 +35,12 @@ check_correct_date (const char *strdate) return NULL; } - g_assert_cmpint (date->year, ==, 2004); - g_assert_cmpint (date->month, ==, 11); - g_assert_cmpint (date->day, ==, 6); - g_assert_cmpint (date->hour, ==, 8); - g_assert_cmpint (date->minute, ==, 9); - g_assert_cmpint (date->second, ==, 7); + g_assert_cmpint (g_date_time_get_year (date), ==, 2004); + g_assert_cmpint (g_date_time_get_month (date), ==, 11); + g_assert_cmpint (g_date_time_get_day_of_month (date), ==, 6); + g_assert_cmpint (g_date_time_get_hour (date), ==, 8); + g_assert_cmpint (g_date_time_get_minute (date), ==, 9); + g_assert_cmpint (g_date_time_get_second (date), ==, 7); return date; } @@ -54,17 +54,13 @@ typedef struct { static const GoodDate good_dates[] = { { SOUP_DATE_HTTP, "Sat, 06 Nov 2004 08:09:07 GMT", NULL }, { SOUP_DATE_COOKIE, "Sat, 06-Nov-2004 08:09:07 GMT", NULL }, - { SOUP_DATE_RFC2822, "Sat, 6 Nov 2004 08:09:07 -0430", "579055" }, - { SOUP_DATE_ISO8601_COMPACT, "20041106T080907", NULL }, - { SOUP_DATE_ISO8601_FULL, "2004-11-06T08:09:07", NULL }, - { SOUP_DATE_ISO8601_XMLRPC, "20041106T08:09:07", NULL } }; static void check_good (gconstpointer data) { GoodDate *good = (GoodDate *)data; - SoupDate *date; + GDateTime *date; char *strdate2; if (good->bugref) @@ -74,8 +70,8 @@ check_good (gconstpointer data) if (!date) return; - strdate2 = soup_date_to_string (date, good->format); - soup_date_free (date); + strdate2 = soup_date_time_to_string (date, good->format); + g_date_time_unref (date); soup_test_assert (strcmp (good->date, strdate2) == 0, "restringification failed: '%s' -> '%s'\n", @@ -114,12 +110,6 @@ static const OkDate ok_dates[] = { { "Sat Nov 6 08:09:07 2004", NULL }, { "Sat Nov 6 08:09:07 2004 GMT", NULL }, - /* ISO 8601 */ - { "2004-11-06T08:09:07Z", NULL }, - { "20041106T08:09:07Z", NULL }, - { "20041106T08:09:07+00:00", NULL }, - { "20041106T080907+00:00", NULL }, - /* Netscape cookie spec date, and broken variants */ { "Sat, 06-Nov-2004 08:09:07 GMT", NULL }, { "Sat, 6-Nov-2004 08:09:07 GMT", NULL }, @@ -143,7 +133,7 @@ static void check_ok (gconstpointer data) { OkDate *ok = (OkDate *)data; - SoupDate *date; + GDateTime *date; if (ok->bugref) g_test_bug (ok->bugref); @@ -151,29 +141,7 @@ check_ok (gconstpointer data) date = check_correct_date (ok->date); if (!date) return; - soup_date_free (date); -} - -#define TIME_T 1099728547L -#define TIME_T_STRING "1099728547" - -static void -check_ok_time_t (void) -{ - SoupDate *date; - - date = soup_date_new_from_time_t (TIME_T); - - g_assert_cmpint (date->year, ==, 2004); - g_assert_cmpint (date->month, ==, 11); - g_assert_cmpint (date->day, ==, 6); - g_assert_cmpint (date->hour, ==, 8); - g_assert_cmpint (date->minute, ==, 9); - g_assert_cmpint (date->second, ==, 7); - - g_assert_cmpuint (TIME_T, ==, soup_date_to_time_t (date)); - - soup_date_free (date); + g_date_time_unref (date); } typedef struct { @@ -221,7 +189,7 @@ static void check_bad (gconstpointer data) { BadDate *bad = (BadDate *)data; - SoupDate *date; + GDateTime *date; if (bad->bugref) g_test_bug (bad->bugref); @@ -230,14 +198,18 @@ check_bad (gconstpointer data) soup_test_assert (date == NULL, "date parsing succeeded for '%s': %d %d %d - %d %d %d", bad->date, - date->year, date->month, date->day, - date->hour, date->minute, date->second); - g_clear_pointer (&date, soup_date_free); + g_date_time_get_year (date), + g_date_time_get_month (date), + g_date_time_get_day_of_month (date), + g_date_time_get_hour (date), + g_date_time_get_minute (date), + g_date_time_get_second (date)); + g_clear_pointer (&date, g_date_time_unref); } typedef struct { const char *source; - const char *http, *cookie, *rfc2822, *compact, *full, *xmlrpc; + const char *http, *cookie; } DateConversion; static const DateConversion conversions[] = { @@ -245,98 +217,38 @@ static const DateConversion conversions[] = { { "Sat, 06 Nov 2004 08:09:07 GMT", "Sat, 06 Nov 2004 08:09:07 GMT", - "Sat, 06-Nov-2004 08:09:07 GMT", - "Sat, 6 Nov 2004 08:09:07 +0000", - "20041106T080907Z", - "2004-11-06T08:09:07Z", - "20041106T08:09:07" }, + "Sat, 06-Nov-2004 08:09:07 GMT" }, /* RFC2822 GMT */ { "Sat, 6 Nov 2004 08:09:07 +0000", "Sat, 06 Nov 2004 08:09:07 GMT", - "Sat, 06-Nov-2004 08:09:07 GMT", - "Sat, 6 Nov 2004 08:09:07 +0000", - "20041106T080907Z", - "2004-11-06T08:09:07Z", - "20041106T08:09:07" }, + "Sat, 06-Nov-2004 08:09:07 GMT" }, /* RFC2822 with positive offset */ { "Sat, 6 Nov 2004 08:09:07 +0430", - "Sat, 06 Nov 2004 04:39:07 GMT", - "Sat, 06-Nov-2004 04:39:07 GMT", - "Sat, 6 Nov 2004 08:09:07 +0430", - "20041106T080907+0430", - "2004-11-06T08:09:07+04:30", - "20041106T08:09:07" }, + "Sat, 06 Nov 2004 03:39:07 GMT", + "Sat, 06-Nov-2004 03:39:07 GMT" }, /* RFC2822 with negative offset */ { "Sat, 6 Nov 2004 08:09:07 -0430", "Sat, 06 Nov 2004 12:39:07 GMT", - "Sat, 06-Nov-2004 12:39:07 GMT", - "Sat, 6 Nov 2004 08:09:07 -0430", - "20041106T080907-0430", - "2004-11-06T08:09:07-04:30", - "20041106T08:09:07" }, + "Sat, 06-Nov-2004 12:39:07 GMT" }, /* RFC2822 floating */ { "Sat, 6 Nov 2004 08:09:07 -0000", "Sat, 06 Nov 2004 08:09:07 GMT", - "Sat, 06-Nov-2004 08:09:07 GMT", - "Sat, 6 Nov 2004 08:09:07 -0000", - "20041106T080907", - "2004-11-06T08:09:07", - "20041106T08:09:07" }, - - /* ISO GMT */ - { "2004-11-06T08:09:07Z", - - "Sat, 06 Nov 2004 08:09:07 GMT", - "Sat, 06-Nov-2004 08:09:07 GMT", - "Sat, 6 Nov 2004 08:09:07 +0000", - "20041106T080907Z", - "2004-11-06T08:09:07Z", - "20041106T08:09:07" }, - - /* ISO with positive offset */ - { "2004-11-06T08:09:07+04:30", - - "Sat, 06 Nov 2004 04:39:07 GMT", - "Sat, 06-Nov-2004 04:39:07 GMT", - "Sat, 6 Nov 2004 08:09:07 +0430", - "20041106T080907+0430", - "2004-11-06T08:09:07+04:30", - "20041106T08:09:07" }, - - /* ISO with negative offset */ - { "2004-11-06T08:09:07-04:30", - - "Sat, 06 Nov 2004 12:39:07 GMT", - "Sat, 06-Nov-2004 12:39:07 GMT", - "Sat, 6 Nov 2004 08:09:07 -0430", - "20041106T080907-0430", - "2004-11-06T08:09:07-04:30", - "20041106T08:09:07" }, - - /* ISO floating */ - { "2004-11-06T08:09:07", - - "Sat, 06 Nov 2004 08:09:07 GMT", - "Sat, 06-Nov-2004 08:09:07 GMT", - "Sat, 6 Nov 2004 08:09:07 -0000", - "20041106T080907", - "2004-11-06T08:09:07", - "20041106T08:09:07" } + "Sat, 06-Nov-2004 08:09:07 GMT" } }; static void check_conversion (gconstpointer data) { const DateConversion *conv = data; - SoupDate *date; + GDateTime *date; char *str; date = make_date (conv->source); @@ -345,31 +257,15 @@ check_conversion (gconstpointer data) return; } - str = soup_date_to_string (date, SOUP_DATE_HTTP); + str = soup_date_time_to_string (date, SOUP_DATE_HTTP); g_assert_cmpstr (str, ==, conv->http); g_free (str); - str = soup_date_to_string (date, SOUP_DATE_COOKIE); + str = soup_date_time_to_string (date, SOUP_DATE_COOKIE); g_assert_cmpstr (str, ==, conv->cookie); g_free (str); - str = soup_date_to_string (date, SOUP_DATE_RFC2822); - g_assert_cmpstr (str, ==, conv->rfc2822); - g_free (str); - - str = soup_date_to_string (date, SOUP_DATE_ISO8601_COMPACT); - g_assert_cmpstr (str, ==, conv->compact); - g_free (str); - - str = soup_date_to_string (date, SOUP_DATE_ISO8601_FULL); - g_assert_cmpstr (str, ==, conv->full); - g_free (str); - - str = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC); - g_assert_cmpstr (str, ==, conv->xmlrpc); - g_free (str); - - soup_date_free (date); + g_date_time_unref (date); } int @@ -391,7 +287,6 @@ main (int argc, char **argv) g_test_add_data_func (path, &ok_dates[i], check_ok); g_free (path); } - g_test_add_func ("/date/ok/" TIME_T_STRING, check_ok_time_t); for (i = 0; i < G_N_ELEMENTS (bad_dates); i++) { path = g_strdup_printf ("/date/bad/%s", bad_dates[i].date); |