summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Griffis <pgriffis@igalia.com>2020-08-28 17:16:15 -0500
committerPatrick Griffis <pgriffis@igalia.com>2020-09-19 15:41:25 -0700
commit4596b4ec4c14a0e473e3fa0c3f41a0107d846cc8 (patch)
treeb99525eaa9f338a52eeab85df16fd78df5219766
parent4217855114d1357eb16c5cf663b2fa09a6e6bd3c (diff)
downloadlibsoup-4596b4ec4c14a0e473e3fa0c3f41a0107d846cc8.tar.gz
Replace SoupDate with GDateTime
-rw-r--r--docs/reference/libsoup-2.4-sections.txt22
-rw-r--r--libsoup/cache/soup-cache.c30
-rw-r--r--libsoup/cookies/soup-cookie-jar-db.c2
-rw-r--r--libsoup/cookies/soup-cookie-jar-text.c2
-rw-r--r--libsoup/cookies/soup-cookie-jar.c7
-rw-r--r--libsoup/cookies/soup-cookie.c38
-rw-r--r--libsoup/cookies/soup-cookie.h18
-rw-r--r--libsoup/hsts/soup-hsts-enforcer-db.c8
-rw-r--r--libsoup/hsts/soup-hsts-policy.c25
-rw-r--r--libsoup/hsts/soup-hsts-policy.h4
-rw-r--r--libsoup/include/soup-installed.h2
-rw-r--r--libsoup/meson.build4
-rw-r--r--libsoup/soup-date-utils-private.h30
-rw-r--r--libsoup/soup-date-utils.c329
-rw-r--r--libsoup/soup-date-utils.h38
-rw-r--r--libsoup/soup-date.c911
-rw-r--r--libsoup/soup-date.h88
-rw-r--r--libsoup/soup-server.c8
-rw-r--r--libsoup/soup-types.h1
-rw-r--r--libsoup/soup.h2
-rw-r--r--tests/cache-test.c17
-rw-r--r--tests/date-test.c177
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);