libsoup r1200 - in trunk: . libsoup
- From: danw svn gnome org
- To: svn-commits-list gnome org
- Subject: libsoup r1200 - in trunk: . libsoup
- Date: Tue, 4 Nov 2008 20:30:37 +0000 (UTC)
Author: danw
Date: Tue Nov 4 20:30:37 2008
New Revision: 1200
URL: http://svn.gnome.org/viewvc/libsoup?rev=1200&view=rev
Log:
* libsoup/soup-cookie-jar-text.c: implementation of SoupCookieJar
that persists to a text file in the old Mozilla cookies.txt
format.
* libsoup/soup-cookie-jar-sqlite.c: implementation of
SoupCookieJar that persists to an sqlite database in the new
Mozilla cookies.sqlite format. (Part of libsoup-gnome.)
* libsoup/soup-cookie-jar.c: add various functionality needed by
the two new subclasses. Does not break API/ABI compat with 2.24.
* libsoup/soup-cookie.c (soup_cookie_get_type): register
SoupCookie as a boxed type.
(domain_matches): fix a bug here that meant "foo.com" couldn't set
a cookie for domain=.foo.com
(soup_cookie_applies_to_uri): fix path checking
* configure.in: if building --with-gnome, require sqlite3
Added:
trunk/libsoup/soup-cookie-jar-sqlite.c
trunk/libsoup/soup-cookie-jar-sqlite.h
trunk/libsoup/soup-cookie-jar-text.c
trunk/libsoup/soup-cookie-jar-text.h
Modified:
trunk/ChangeLog
trunk/configure.in
trunk/libsoup/Makefile.am
trunk/libsoup/soup-cookie-jar.c
trunk/libsoup/soup-cookie-jar.h
trunk/libsoup/soup-cookie.c
trunk/libsoup/soup-cookie.h
trunk/libsoup/soup-gnome.h
trunk/libsoup/soup-marshal.list
trunk/libsoup/soup.h
Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in (original)
+++ trunk/configure.in Tue Nov 4 20:30:37 2008
@@ -199,6 +199,13 @@
One or the other is required for GNOME proxy support.
Pass "--without-gnome" to configure if you want to build without GNOME support.])])
fi
+
+ PKG_CHECK_MODULES(SQLITE, sqlite3, :, [AC_MSG_ERROR(dnl
+[Could not find sqlite3 devel files:
+
+$SQLITE_PKG_ERRORS
+
+Pass "--without-gnome" to configure if you want to build without GNOME support.])])
fi
AC_SUBST(HAVE_GNOME)
AC_SUBST(GCONF_CFLAGS)
@@ -207,6 +214,8 @@
AC_SUBST(LIBPROXY_CFLAGS)
AC_SUBST(LIBPROXY_LIBS)
AM_CONDITIONAL(WITH_LIBPROXY, [test -n "$LIBPROXY_LIBS"])
+AC_SUBST(SQLITE_CFLAGS)
+AC_SUBST(SQLITE_LIBS)
dnl ***************
Modified: trunk/libsoup/Makefile.am
==============================================================================
--- trunk/libsoup/Makefile.am (original)
+++ trunk/libsoup/Makefile.am Tue Nov 4 20:30:37 2008
@@ -13,6 +13,7 @@
$(XML_CFLAGS) \
$(GCONF_CFLAGS) \
$(LIBPROXY_CFLAGS) \
+ $(SQLITE_CFLAGS) \
$(LIBGCRYPT_CFLAGS) \
$(LIBGNUTLS_CFLAGS)
@@ -56,6 +57,7 @@
soup-auth-domain-digest.h \
soup-cookie.h \
soup-cookie-jar.h \
+ soup-cookie-jar-text.h \
soup-date.h \
soup-form.h \
soup-headers.h \
@@ -118,6 +120,7 @@
soup-connection.c \
soup-cookie.c \
soup-cookie-jar.c \
+ soup-cookie-jar-text.c \
soup-date.c \
soup-dns.h \
soup-dns.c \
@@ -161,6 +164,7 @@
libsoupgnomeincludedir = $(libsoupincludedir)
libsoupgnomeinclude_HEADERS = \
+ soup-cookie-jar-sqlite.h\
soup-gnome.h \
soup-gnome-features.h
@@ -168,9 +172,12 @@
libsoup_gnome_2_4_la_LDFLAGS = $(libsoup_2_4_la_LDFLAGS)
-libsoup_gnome_2_4_la_LIBADD = libsoup-2.4.la
+libsoup_gnome_2_4_la_LIBADD = \
+ libsoup-2.4.la \
+ $(SQLITE_LIBS)
libsoup_gnome_2_4_la_SOURCES = \
+ soup-cookie-jar-sqlite.c \
soup-gnome-features.c
if WITH_LIBPROXY
Added: trunk/libsoup/soup-cookie-jar-sqlite.c
==============================================================================
--- (empty file)
+++ trunk/libsoup/soup-cookie-jar-sqlite.c Tue Nov 4 20:30:37 2008
@@ -0,0 +1,286 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * soup-cookie-jar-sqlite.c: ff sqlite-based cookie storage
+ *
+ * Using danw's soup-cookie-jar-text as template
+ * Copyright (C) 2008 Diego Escalante Urrelo
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sqlite3.h>
+
+#include "soup-cookie-jar-sqlite.h"
+#include "soup-cookie.h"
+#include "soup-date.h"
+
+/**
+ * SECTION:soup-cookie-jar-sqlite
+ * @short_description: SQLite-based Cookie Jar
+ *
+ * #SoupCookieJarSqlite is a #SoupCookieJar that reads cookies from and
+ * writes them to an SQLite file in the new Mozilla format.
+ **/
+
+enum {
+ PROP_0,
+
+ PROP_FILENAME,
+
+ LAST_PROP
+};
+
+typedef struct {
+ char *filename;
+
+} SoupCookieJarSqlitePrivate;
+
+#define SOUP_COOKIE_JAR_SQLITE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_COOKIE_JAR_SQLITE, SoupCookieJarSqlitePrivate))
+
+G_DEFINE_TYPE (SoupCookieJarSqlite, soup_cookie_jar_sqlite, SOUP_TYPE_COOKIE_JAR)
+
+static void load (SoupCookieJar *jar);
+static void changed (SoupCookieJar *jar,
+ SoupCookie *old_cookie,
+ SoupCookie *new_cookie);
+
+static void set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec);
+static void get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec);
+
+static void
+soup_cookie_jar_sqlite_init (SoupCookieJarSqlite *sqlite)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+ SoupCookieJarSqlitePrivate *priv =
+ SOUP_COOKIE_JAR_SQLITE_GET_PRIVATE (object);
+
+ g_free (priv->filename);
+
+ G_OBJECT_CLASS (soup_cookie_jar_sqlite_parent_class)->finalize (object);
+}
+
+static void
+soup_cookie_jar_sqlite_class_init (SoupCookieJarSqliteClass *sqlite_class)
+{
+ SoupCookieJarClass *cookie_jar_class =
+ SOUP_COOKIE_JAR_CLASS (sqlite_class);
+ GObjectClass *object_class = G_OBJECT_CLASS (sqlite_class);
+
+ g_type_class_add_private (sqlite_class, sizeof (SoupCookieJarSqlitePrivate));
+
+ cookie_jar_class->changed = changed;
+
+ object_class->finalize = finalize;
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+
+ g_object_class_install_property (
+ object_class, PROP_FILENAME,
+ g_param_spec_string (SOUP_COOKIE_JAR_SQLITE_FILENAME,
+ "Filename",
+ "Cookie-storage filename",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ SoupCookieJarSqlitePrivate *priv =
+ SOUP_COOKIE_JAR_SQLITE_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_FILENAME:
+ priv->filename = g_value_dup_string (value);
+ load (SOUP_COOKIE_JAR (object));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ SoupCookieJarSqlitePrivate *priv =
+ SOUP_COOKIE_JAR_SQLITE_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_FILENAME:
+ g_value_set_string (value, priv->filename);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/**
+ * soup_cookie_jar_sqlite_new:
+ * @filename: the filename to read to/write from, or %NULL
+ * @read_only: %TRUE if @filename is read-only
+ *
+ * Creates a #SoupCookieJarSqlite.
+ *
+ * @filename will be read in at startup to create an initial set of
+ * cookies. If @read_only is %FALSE, then the non-session cookies will
+ * be written to @filename when the 'changed' signal is emitted from
+ * the jar. (If @read_only is %TRUE, then the cookie jar will only be
+ * used for this session, and changes made to it will be lost when the
+ * jar is destroyed.)
+ *
+ * Return value: the new #SoupCookieJar
+ **/
+SoupCookieJar *
+soup_cookie_jar_sqlite_new (const char *filename, gboolean read_only)
+{
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ return g_object_new (SOUP_TYPE_COOKIE_JAR_SQLITE,
+ SOUP_COOKIE_JAR_SQLITE_FILENAME, filename,
+ SOUP_COOKIE_JAR_READ_ONLY, read_only,
+ NULL);
+}
+
+#define QUERY_ALL "SELECT * FROM moz_cookies;"
+#define QUERY_INSERT "INSERT INTO moz_cookies VALUES(NULL, %Q, %Q, %Q, %Q, %d, NULL, %d, %d);"
+#define QUERY_DELETE "DELETE FROM moz_cookies WHERE name=%Q AND domain=%Q;"
+
+enum {
+ COL_ID,
+ COL_NAME,
+ COL_VALUE,
+ COL_HOST,
+ COL_PATH,
+ COL_EXPIRY,
+ COL_LAST_ACCESS,
+ COL_SECURE,
+ COL_HTTP_ONLY,
+ N_COL,
+};
+
+static int
+callback (void *data, int argc, char **argv, char **colname)
+{
+ SoupCookie *cookie = NULL;
+ SoupCookieJar *jar = SOUP_COOKIE_JAR (data);
+
+ char *name, *value, *host, *path;
+ time_t max_age, now;
+ gboolean http_only = FALSE, secure = FALSE;
+
+ now = time (NULL);
+
+ name = argv[COL_NAME];
+ value = argv[COL_VALUE];
+ host = argv[COL_HOST];
+ path = argv[COL_PATH];
+ max_age = strtoul (argv[COL_EXPIRY], NULL, 10) - now;
+
+ if (max_age <= 0)
+ return 0;
+
+ http_only = (strcmp (argv[COL_HTTP_ONLY], "FALSE") != 0);
+ secure = (strcmp (argv[COL_SECURE], "FALSE") != 0);
+
+ cookie = soup_cookie_new (name, value, host, path, max_age);
+
+ if (secure)
+ soup_cookie_set_secure (cookie, TRUE);
+ if (http_only)
+ soup_cookie_set_http_only (cookie, TRUE);
+
+ soup_cookie_jar_add_cookie (jar, cookie);
+
+ return 0;
+}
+
+static void
+load (SoupCookieJar *jar)
+{
+ SoupCookieJarSqlitePrivate *priv =
+ SOUP_COOKIE_JAR_SQLITE_GET_PRIVATE (jar);
+
+ sqlite3 *db;
+ char *error = 0;
+
+ if (sqlite3_open (priv->filename, &db)) {
+ sqlite3_close (db);
+ g_debug ("Can't open %s", priv->filename);
+ }
+
+ if (sqlite3_exec (db, QUERY_ALL, callback, (void *)jar, &error)) {
+ g_debug ("Failed to execute query: %s", error);
+ sqlite3_free (error);
+ }
+
+ sqlite3_close (db);
+}
+
+static void
+changed (SoupCookieJar *jar,
+ SoupCookie *old_cookie,
+ SoupCookie *new_cookie)
+{
+ SoupCookieJarSqlitePrivate *priv =
+ SOUP_COOKIE_JAR_SQLITE_GET_PRIVATE (jar);
+ sqlite3 *db;
+ char *error = NULL;
+ char *query;
+
+ if (sqlite3_open (priv->filename, &db)) {
+ sqlite3_close (db);
+ g_warning ("Can't open %s", priv->filename);
+ return;
+ }
+
+ if (old_cookie) {
+ query = sqlite3_mprintf (QUERY_DELETE,
+ old_cookie->name,
+ old_cookie->domain);
+ if (sqlite3_exec (db, query, NULL, NULL, &error)) {
+ g_warning ("Failed to execute query: %s", error);
+ sqlite3_free (error);
+ }
+ sqlite3_free (query);
+ }
+
+ if (new_cookie) {
+ int expires;
+
+ if (new_cookie->expires)
+ expires = soup_date_to_time_t (new_cookie->expires);
+ else
+ expires = 0;
+
+ query = sqlite3_mprintf (QUERY_INSERT,
+ new_cookie->name,
+ new_cookie->value,
+ new_cookie->domain,
+ new_cookie->path,
+ expires,
+ new_cookie->secure,
+ new_cookie->http_only);
+ if (sqlite3_exec (db, query, NULL, NULL, &error)) {
+ g_warning ("Failed to execute query: %s", error);
+ sqlite3_free (error);
+ }
+ sqlite3_free (query);
+ }
+
+ sqlite3_close (db);
+}
Added: trunk/libsoup/soup-cookie-jar-sqlite.h
==============================================================================
--- (empty file)
+++ trunk/libsoup/soup-cookie-jar-sqlite.h Tue Nov 4 20:30:37 2008
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Diego Escalante Urrelo
+ */
+
+#ifndef SOUP_COOKIE_JAR_SQLITE_H
+#define SOUP_COOKIE_JAR_SQLITE_H 1
+
+#include <libsoup/soup-cookie-jar.h>
+
+#define SOUP_TYPE_COOKIE_JAR_SQLITE (soup_cookie_jar_sqlite_get_type ())
+#define SOUP_COOKIE_JAR_SQLITE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_COOKIE_JAR_SQLITE, SoupCookieJarSqlite))
+#define SOUP_COOKIE_JAR_SQLITE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_COOKIE_JAR_SQLITE, SoupCookieJarSqliteClass))
+#define SOUP_IS_COOKIE_JAR_SQLITE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_COOKIE_JAR_SQLITE))
+#define SOUP_IS_COOKIE_JAR_SQLITE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_COOKIE_JAR_SQLITE))
+#define SOUP_COOKIE_JAR_SQLITE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_COOKIE_JAR_SQLITE, SoupCookieJarSqliteClass))
+
+typedef struct {
+ SoupCookieJar parent;
+
+} SoupCookieJarSqlite;
+
+typedef struct {
+ SoupCookieJarClass parent_class;
+
+ /* Padding for future expansion */
+ void (*_libsoup_reserved1) (void);
+ void (*_libsoup_reserved2) (void);
+ void (*_libsoup_reserved3) (void);
+ void (*_libsoup_reserved4) (void);
+} SoupCookieJarSqliteClass;
+
+#define SOUP_COOKIE_JAR_SQLITE_FILENAME "filename"
+
+GType soup_cookie_jar_sqlite_get_type (void);
+
+SoupCookieJar *soup_cookie_jar_sqlite_new (const char *filename,
+ gboolean read_only);
+
+#endif /* SOUP_COOKIE_JAR_SQLITE_H */
Added: trunk/libsoup/soup-cookie-jar-text.c
==============================================================================
--- (empty file)
+++ trunk/libsoup/soup-cookie-jar-text.c Tue Nov 4 20:30:37 2008
@@ -0,0 +1,349 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * soup-cookie-jar-text.c: cookies.txt-based cookie storage
+ *
+ * Copyright (C) 2007, 2008 Red Hat, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "soup-cookie-jar-text.h"
+#include "soup-cookie.h"
+#include "soup-date.h"
+
+/**
+ * SECTION:soup-cookie-jar-text
+ * @short_description: Text-file-based ("cookies.txt") Cookie Jar
+ *
+ * #SoupCookieJarText is a #SoupCookieJar that reads cookies from and
+ * writes them to a text file in the Mozilla "cookies.txt" format.
+ **/
+
+enum {
+ PROP_0,
+
+ PROP_FILENAME,
+
+ LAST_PROP
+};
+
+typedef struct {
+ char *filename;
+
+} SoupCookieJarTextPrivate;
+#define SOUP_COOKIE_JAR_TEXT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_COOKIE_JAR_TEXT, SoupCookieJarTextPrivate))
+
+G_DEFINE_TYPE (SoupCookieJarText, soup_cookie_jar_text, SOUP_TYPE_COOKIE_JAR)
+
+static void load (SoupCookieJar *jar);
+static void changed (SoupCookieJar *jar,
+ SoupCookie *old_cookie,
+ SoupCookie *new_cookie);
+
+static void set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec);
+static void get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec);
+
+static void
+soup_cookie_jar_text_init (SoupCookieJarText *text)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+ SoupCookieJarTextPrivate *priv =
+ SOUP_COOKIE_JAR_TEXT_GET_PRIVATE (object);
+
+ g_free (priv->filename);
+
+ G_OBJECT_CLASS (soup_cookie_jar_text_parent_class)->finalize (object);
+}
+
+static void
+soup_cookie_jar_text_class_init (SoupCookieJarTextClass *text_class)
+{
+ SoupCookieJarClass *cookie_jar_class =
+ SOUP_COOKIE_JAR_CLASS (text_class);
+ GObjectClass *object_class = G_OBJECT_CLASS (text_class);
+
+ g_type_class_add_private (text_class, sizeof (SoupCookieJarTextPrivate));
+
+ cookie_jar_class->changed = changed;
+
+ object_class->finalize = finalize;
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+
+ g_object_class_install_property (
+ object_class, PROP_FILENAME,
+ g_param_spec_string (SOUP_COOKIE_JAR_TEXT_FILENAME,
+ "Filename",
+ "Cookie-storage filename",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ SoupCookieJarTextPrivate *priv =
+ SOUP_COOKIE_JAR_TEXT_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_FILENAME:
+ priv->filename = g_value_dup_string (value);
+ load (SOUP_COOKIE_JAR (object));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ SoupCookieJarTextPrivate *priv =
+ SOUP_COOKIE_JAR_TEXT_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_FILENAME:
+ g_value_set_string (value, priv->filename);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/**
+ * soup_cookie_jar_text_new:
+ * @filename: the filename to read to/write from
+ * @read_only: %TRUE if @filename is read-only
+ *
+ * Creates a #SoupCookieJarText.
+ *
+ * @filename will be read in at startup to create an initial set of
+ * cookies. If @read_only is %FALSE, then the non-session cookies will
+ * be written to @filename when the 'changed' signal is emitted from
+ * the jar. (If @read_only is %TRUE, then the cookie jar will only be
+ * used for this session, and changes made to it will be lost when the
+ * jar is destroyed.)
+ *
+ * Return value: the new #SoupCookieJar
+ **/
+SoupCookieJar *
+soup_cookie_jar_text_new (const char *filename, gboolean read_only)
+{
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ return g_object_new (SOUP_TYPE_COOKIE_JAR_TEXT,
+ SOUP_COOKIE_JAR_TEXT_FILENAME, filename,
+ SOUP_COOKIE_JAR_READ_ONLY, read_only,
+ NULL);
+}
+
+static SoupCookie*
+parse_cookie (char *line, time_t now)
+{
+ char **result;
+ SoupCookie *cookie = NULL;
+ gboolean http_only;
+ time_t max_age;
+ char *host, *is_domain, *path, *secure, *expires, *name, *value;
+
+ if (g_str_has_prefix (line, "#HttpOnly_")) {
+ http_only = TRUE;
+ line += strlen ("#HttpOnly_");
+ } else if (*line == '#' || g_ascii_isspace (*line))
+ return cookie;
+ else
+ http_only = FALSE;
+
+ result = g_strsplit (line, "\t", -1);
+ if (g_strv_length (result) != 7)
+ goto out;
+
+ /* Check this first */
+ expires = result[4];
+ max_age = strtoul (expires, NULL, 10) - now;
+ if (max_age <= 0)
+ goto out;
+
+ host = result[0];
+ is_domain = result[1];
+ path = result[2];
+ secure = result[3];
+
+ name = result[5];
+ value = result[6];
+
+ cookie = soup_cookie_new (name, value, host, path, max_age);
+
+ if (strcmp (secure, "FALSE") != 0)
+ soup_cookie_set_secure (cookie, TRUE);
+ if (http_only)
+ soup_cookie_set_http_only (cookie, TRUE);
+
+ out:
+ g_strfreev (result);
+
+ return cookie;
+}
+
+static void
+parse_line (SoupCookieJar *jar, char *line, time_t now)
+{
+ SoupCookie *cookie;
+
+ cookie = parse_cookie (line, now);
+ if (cookie)
+ soup_cookie_jar_add_cookie (jar, cookie);
+}
+
+static void
+load (SoupCookieJar *jar)
+{
+ SoupCookieJarTextPrivate *priv =
+ SOUP_COOKIE_JAR_TEXT_GET_PRIVATE (jar);
+ char *contents = NULL, *line, *p;
+ gsize length = 0;
+ time_t now = time (NULL);
+
+ /* FIXME: error? */
+ if (!g_file_get_contents (priv->filename, &contents, &length, NULL))
+ return;
+
+ line = contents;
+ for (p = contents; *p; p++) {
+ /* \r\n comes out as an extra empty line and gets ignored */
+ if (*p == '\r' || *p == '\n') {
+ *p = '\0';
+ parse_line (jar, line, now);
+ line = p + 1;
+ }
+ }
+ parse_line (jar, line, now);
+
+ g_free (contents);
+}
+
+static void
+write_cookie (FILE *out, SoupCookie *cookie)
+{
+ fseek (out, 0, SEEK_END);
+
+ fprintf (out, "%s%s\t%s\t%s\t%s\t%lu\t%s\t%s\n",
+ cookie->http_only ? "#HttpOnly_" : "",
+ cookie->domain,
+ *cookie->domain == '.' ? "TRUE" : "FALSE",
+ cookie->path,
+ cookie->secure ? "TRUE" : "FALSE",
+ (gulong)soup_date_to_time_t (cookie->expires),
+ cookie->name,
+ cookie->value);
+}
+
+static void
+delete_cookie (const char *filename, SoupCookie *cookie)
+{
+ char *contents = NULL, *line, *p;
+ gsize length = 0;
+ FILE *f;
+ SoupCookie *c;
+ time_t now = time (NULL);
+
+ if (!g_file_get_contents (filename, &contents, &length, NULL))
+ return;
+
+ f = fopen (filename, "w");
+ if (!f) {
+ g_free (contents);
+ return;
+ }
+
+ line = contents;
+ for (p = contents; *p; p++) {
+ /* \r\n comes out as an extra empty line and gets ignored */
+ if (*p == '\r' || *p == '\n') {
+ *p = '\0';
+ c = parse_cookie (line, now);
+ if (!c)
+ continue;
+ if (!soup_cookie_equal (cookie, c))
+ write_cookie (f, c);
+ line = p + 1;
+ soup_cookie_free (c);
+ }
+ }
+ c = parse_cookie (line, now);
+ if (c) {
+ if (!soup_cookie_equal (cookie, c))
+ write_cookie (f, c);
+ soup_cookie_free (c);
+ }
+
+ g_free (contents);
+ fclose (f);
+}
+
+static void
+changed (SoupCookieJar *jar,
+ SoupCookie *old_cookie,
+ SoupCookie *new_cookie)
+{
+ FILE *out;
+ SoupCookieJarTextPrivate *priv =
+ SOUP_COOKIE_JAR_TEXT_GET_PRIVATE (jar);
+
+ /* We can sort of ignore the semantics of the 'changed'
+ * signal here and simply delete the old cookie if present
+ * and write the new cookie if present. That will do the
+ * right thing for all 'added', 'deleted' and 'modified'
+ * meanings.
+ */
+ /* Also, delete_cookie takes the filename and write_cookie
+ * a FILE pointer. Seems more convenient that way considering
+ * the implementations of the functions
+ */
+ if (old_cookie)
+ delete_cookie (priv->filename, old_cookie);
+
+ if (new_cookie) {
+ gboolean write_header = FALSE;
+
+ if (!g_file_test (priv->filename, G_FILE_TEST_EXISTS))
+ write_header = TRUE;
+
+ out = fopen (priv->filename, "a");
+ if (!out) {
+ /* FIXME: error? */
+ return;
+ }
+
+ if (write_header) {
+ fprintf (out, "# HTTP Cookie File\n");
+ fprintf (out, "# http://www.netscape.com/newsref/std/cookie_spec.html\n");
+ fprintf (out, "# This is a generated file! Do not edit.\n");
+ fprintf (out, "# To delete cookies, use the Cookie Manager.\n\n");
+ }
+
+ if (new_cookie->expires)
+ write_cookie (out, new_cookie);
+
+ if (fclose (out) != 0) {
+ /* FIXME: error? */
+ return;
+ }
+ }
+}
Added: trunk/libsoup/soup-cookie-jar-text.h
==============================================================================
--- (empty file)
+++ trunk/libsoup/soup-cookie-jar-text.h Tue Nov 4 20:30:37 2008
@@ -0,0 +1,43 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Red Hat, Inc.
+ */
+
+#ifndef SOUP_COOKIE_JAR_TEXT_H
+#define SOUP_COOKIE_JAR_TEXT_H 1
+
+#include <libsoup/soup-cookie-jar.h>
+
+#define SOUP_TYPE_COOKIE_JAR_TEXT (soup_cookie_jar_text_get_type ())
+#define SOUP_COOKIE_JAR_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_COOKIE_JAR_TEXT, SoupCookieJarText))
+#define SOUP_COOKIE_JAR_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_COOKIE_JAR_TEXT, SoupCookieJarTextClass))
+#define SOUP_IS_COOKIE_JAR_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_COOKIE_JAR_TEXT))
+#define SOUP_IS_COOKIE_JAR_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_COOKIE_JAR_TEXT))
+#define SOUP_COOKIE_JAR_TEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_COOKIE_JAR_TEXT, SoupCookieJarTextClass))
+
+typedef struct {
+ SoupCookieJar parent;
+
+} SoupCookieJarText;
+
+typedef struct {
+ SoupCookieJarClass parent_class;
+
+ /* Padding for future expansion */
+ void (*_libsoup_reserved1) (void);
+ void (*_libsoup_reserved2) (void);
+ void (*_libsoup_reserved3) (void);
+ void (*_libsoup_reserved4) (void);
+} SoupCookieJarTextClass;
+
+#define SOUP_COOKIE_JAR_TEXT_FILENAME "filename"
+#ifndef LIBSOUP_DISABLE_DEPRECATED
+#define SOUP_COOKIE_JAR_TEXT_READ_ONLY SOUP_COOKIE_JAR_READ_ONLY
+#endif
+
+GType soup_cookie_jar_text_get_type (void);
+
+SoupCookieJar *soup_cookie_jar_text_new (const char *filename,
+ gboolean read_only);
+
+#endif /* SOUP_COOKIE_JAR_TEXT_H */
Modified: trunk/libsoup/soup-cookie-jar.c
==============================================================================
--- trunk/libsoup/soup-cookie-jar.c (original)
+++ trunk/libsoup/soup-cookie-jar.c Tue Nov 4 20:30:37 2008
@@ -15,6 +15,7 @@
#include "soup-cookie.h"
#include "soup-cookie-jar.h"
#include "soup-date.h"
+#include "soup-marshal.h"
#include "soup-message.h"
#include "soup-session-feature.h"
#include "soup-uri.h"
@@ -45,11 +46,32 @@
G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE,
soup_cookie_jar_session_feature_init))
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+enum {
+ PROP_0,
+
+ PROP_READ_ONLY,
+
+ LAST_PROP
+};
+
typedef struct {
+ gboolean constructed, read_only;
GHashTable *domains;
} SoupCookieJarPrivate;
#define SOUP_COOKIE_JAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_COOKIE_JAR, SoupCookieJarPrivate))
+static void set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec);
+static void get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec);
+
static void
soup_cookie_jar_init (SoupCookieJar *jar)
{
@@ -60,6 +82,14 @@
}
static void
+constructed (GObject *object)
+{
+ SoupCookieJarPrivate *priv = SOUP_COOKIE_JAR_GET_PRIVATE (object);
+
+ priv->constructed = TRUE;
+}
+
+static void
finalize (GObject *object)
{
SoupCookieJarPrivate *priv = SOUP_COOKIE_JAR_GET_PRIVATE (object);
@@ -81,7 +111,29 @@
g_type_class_add_private (jar_class, sizeof (SoupCookieJarPrivate));
+ object_class->constructed = constructed;
object_class->finalize = finalize;
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+
+ signals[CHANGED] =
+ g_signal_new ("changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (SoupCookieJarClass, changed),
+ NULL, NULL,
+ soup_marshal_NONE__BOXED_BOXED,
+ G_TYPE_NONE, 2,
+ SOUP_TYPE_COOKIE | G_SIGNAL_TYPE_STATIC_SCOPE,
+ SOUP_TYPE_COOKIE | G_SIGNAL_TYPE_STATIC_SCOPE);
+
+ g_object_class_install_property (
+ object_class, PROP_READ_ONLY,
+ g_param_spec_boolean (SOUP_COOKIE_JAR_READ_ONLY,
+ "Read-only",
+ "Whether or not the cookie jar is read-only",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}
static void
@@ -93,10 +145,45 @@
feature_interface->request_unqueued = request_unqueued;
}
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ SoupCookieJarPrivate *priv =
+ SOUP_COOKIE_JAR_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_READ_ONLY:
+ priv->read_only = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ SoupCookieJarPrivate *priv =
+ SOUP_COOKIE_JAR_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_READ_ONLY:
+ g_value_set_boolean (value, priv->read_only);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
/**
* soup_cookie_jar_new:
*
- * Creates a new #SoupCookieJar.
+ * Creates a new #SoupCookieJar. The base #SoupCookieJar class does
+ * not support persistent storage of cookies; use a subclass for that.
*
* Returns: a new #SoupCookieJar
**/
@@ -106,18 +193,22 @@
return g_object_new (SOUP_TYPE_COOKIE_JAR, NULL);
}
-/**
- * soup_cookie_jar_save:
- * @jar: a SoupCookieJar
- *
- * Tells @jar to save the state of its (non-session) cookies to some
- * sort of permanent storage.
- **/
void
soup_cookie_jar_save (SoupCookieJar *jar)
{
- if (SOUP_COOKIE_JAR_GET_CLASS (jar)->save)
- SOUP_COOKIE_JAR_GET_CLASS (jar)->save (jar);
+ /* Does nothing, obsolete */
+}
+
+static void
+soup_cookie_jar_changed (SoupCookieJar *jar,
+ SoupCookie *old, SoupCookie *new)
+{
+ SoupCookieJarPrivate *priv = SOUP_COOKIE_JAR_GET_PRIVATE (jar);
+
+ if (priv->read_only || !priv->constructed)
+ return;
+
+ g_signal_emit (jar, signals[CHANGED], 0, old, new);
}
/**
@@ -148,6 +239,7 @@
SoupCookieJarPrivate *priv;
GSList *cookies, *domain_cookies;
char *domain, *cur, *next, *result;
+ GSList *new_head, *cookies_to_remove = NULL, *p;
g_return_val_if_fail (SOUP_IS_COOKIE_JAR (jar), NULL);
priv = SOUP_COOKIE_JAR_GET_PRIVATE (jar);
@@ -161,14 +253,23 @@
domain = cur = g_strdup_printf (".%s", uri->host);
next = domain + 1;
do {
- domain_cookies = g_hash_table_lookup (priv->domains, cur);
+ new_head = domain_cookies = g_hash_table_lookup (priv->domains, cur);
while (domain_cookies) {
+ GSList *next = domain_cookies->next;
SoupCookie *cookie = domain_cookies->data;
- if (soup_cookie_applies_to_uri (cookie, uri) &&
- (for_http || !cookie->http_only))
+ if (cookie->expires && soup_date_is_past (cookie->expires)) {
+ cookies_to_remove = g_slist_append (cookies_to_remove,
+ cookie);
+ new_head = g_slist_delete_link (new_head, domain_cookies);
+ g_hash_table_insert (priv->domains,
+ g_strdup (cur),
+ new_head);
+ } else if (soup_cookie_applies_to_uri (cookie, uri) &&
+ (for_http || !cookie->http_only))
cookies = g_slist_append (cookies, cookie);
- domain_cookies = domain_cookies->next;
+
+ domain_cookies = next;
}
cur = next;
if (cur)
@@ -176,6 +277,14 @@
} while (cur);
g_free (domain);
+ for (p = cookies_to_remove; p; p = p->next) {
+ SoupCookie *cookie = p->data;
+
+ soup_cookie_jar_changed (jar, cookie, NULL);
+ soup_cookie_free (cookie);
+ }
+ g_slist_free (cookies_to_remove);
+
if (cookies) {
/* FIXME: sort? */
result = soup_cookies_to_cookie_header (cookies);
@@ -185,63 +294,71 @@
return NULL;
}
-static GSList *
-get_cookies_for_domain (SoupCookieJar *jar, const char *domain)
-{
- SoupCookieJarPrivate *priv = SOUP_COOKIE_JAR_GET_PRIVATE (jar);
- GSList *cookies, *orig_cookies, *c;
- SoupCookie *cookie;
-
- cookies = g_hash_table_lookup (priv->domains, domain);
- c = orig_cookies = cookies;
- while (c) {
- cookie = c->data;
- c = c->next;
- if (cookie->expires && soup_date_is_past (cookie->expires)) {
- cookies = g_slist_remove (cookies, cookie);
- soup_cookie_free (cookie);
- }
- }
-
- if (cookies != orig_cookies)
- g_hash_table_insert (priv->domains, g_strdup (domain), cookies);
- return cookies;
-}
-
-static void
-set_cookie (SoupCookieJar *jar, SoupCookie *cookie)
+/**
+ * soup_cookie_jar_add_cookie:
+ * @jar: a #SoupCookieJar
+ * @cookie: a #SoupCookie
+ *
+ * Adds @cookie to @jar, emitting the 'changed' signal if we are modifying
+ * an existing cookie or adding a valid new cookie ('valid' means
+ * that the cookie's expire date is not in the past).
+ *
+ * @cookie will be 'stolen' by the jar, so don't free it afterwards.
+ **/
+void
+soup_cookie_jar_add_cookie (SoupCookieJar *jar, SoupCookie *cookie)
{
- SoupCookieJarPrivate *priv = SOUP_COOKIE_JAR_GET_PRIVATE (jar);
+ SoupCookieJarPrivate *priv;
GSList *old_cookies, *oc, *prev = NULL;
SoupCookie *old_cookie;
- old_cookies = get_cookies_for_domain (jar, cookie->domain);
+ g_return_if_fail (SOUP_IS_COOKIE_JAR (jar));
+ g_return_if_fail (cookie != NULL);
+
+ priv = SOUP_COOKIE_JAR_GET_PRIVATE (jar);
+ old_cookies = g_hash_table_lookup (priv->domains, cookie->domain);
for (oc = old_cookies; oc; oc = oc->next) {
old_cookie = oc->data;
if (!strcmp (cookie->name, old_cookie->name)) {
- /* The new cookie is a replacement for an old
- * cookie. It might be pre-expired, but we
- * don't worry about that here;
- * get_cookies_for_domain() will delete it
- * later.
- */
- soup_cookie_free (old_cookie);
- oc->data = cookie;
+ if (cookie->expires && soup_date_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
+ * remove the cookie.
+ */
+ old_cookies = g_slist_delete_link (old_cookies, oc);
+ g_hash_table_insert (priv->domains,
+ g_strdup (cookie->domain),
+ old_cookies);
+ soup_cookie_jar_changed (jar, old_cookie, NULL);
+ soup_cookie_free (old_cookie);
+ soup_cookie_free (cookie);
+ } else {
+ oc->data = cookie;
+ soup_cookie_jar_changed (jar, old_cookie, cookie);
+ soup_cookie_free (old_cookie);
+ }
+
return;
}
prev = oc;
}
/* The new cookie is... a new cookie */
- if (cookie->expires && soup_date_is_past (cookie->expires))
+ if (cookie->expires && soup_date_is_past (cookie->expires)) {
soup_cookie_free (cookie);
- else if (prev)
+ return;
+ }
+
+ if (prev)
prev = g_slist_append (prev, cookie);
else {
old_cookies = g_slist_append (NULL, cookie);
g_hash_table_insert (priv->domains, g_strdup (cookie->domain),
old_cookies);
}
+
+ soup_cookie_jar_changed (jar, NULL, cookie);
}
/**
@@ -264,8 +381,8 @@
soup_cookie = soup_cookie_parse (cookie, uri);
if (soup_cookie) {
- set_cookie (jar, soup_cookie);
- /* set_cookie will steal or free soup_cookie */
+ /* will steal or free soup_cookie */
+ soup_cookie_jar_add_cookie (jar, soup_cookie);
}
}
@@ -277,7 +394,7 @@
new_cookies = soup_cookies_from_response (msg);
for (nc = new_cookies; nc; nc = nc->next)
- set_cookie (jar, nc->data);
+ soup_cookie_jar_add_cookie (jar, nc->data);
g_slist_free (new_cookies);
}
@@ -311,3 +428,75 @@
g_signal_handlers_disconnect_by_func (msg, process_set_cookie_header, feature);
}
+/**
+ * soup_cookie_jar_all_cookies:
+ * @jar: a #SoupCookieJar
+ *
+ * Constructs a #GSList with every cookie inside the @jar.
+ * The cookies in the list are a copy of the original, so
+ * you have to free them when you are done with them.
+ *
+ * Return value: a #GSList with all the cookies in the @jar.
+ **/
+GSList *
+soup_cookie_jar_all_cookies (SoupCookieJar *jar)
+{
+ SoupCookieJarPrivate *priv;
+ GHashTableIter iter;
+ GSList *l = NULL;
+ gpointer key, value;
+
+ g_return_val_if_fail (SOUP_IS_COOKIE_JAR (jar), NULL);
+
+ priv = SOUP_COOKIE_JAR_GET_PRIVATE (jar);
+
+ g_hash_table_iter_init (&iter, priv->domains);
+
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ GSList *p, *cookies = value;
+ for (p = cookies; p; p = p->next)
+ l = g_slist_prepend (l, soup_cookie_copy (p->data));
+ }
+
+ return l;
+}
+
+/**
+ * soup_cookie_jar_delete_cookie:
+ * @jar: a #SoupCookieJar
+ * @cookie: a #SoupCookie
+ *
+ * Deletes @cookie from @jar, emitting the 'changed' signal.
+ **/
+void
+soup_cookie_jar_delete_cookie (SoupCookieJar *jar,
+ SoupCookie *cookie)
+{
+ SoupCookieJarPrivate *priv;
+ GSList *cookies, *p;
+ char *domain;
+
+ g_return_if_fail (SOUP_IS_COOKIE_JAR (jar));
+ g_return_if_fail (cookie != NULL);
+
+ priv = SOUP_COOKIE_JAR_GET_PRIVATE (jar);
+
+ domain = g_strdup (cookie->domain);
+
+ cookies = g_hash_table_lookup (priv->domains, domain);
+ if (cookies == NULL)
+ return;
+
+ for (p = cookies; p; p = p->next ) {
+ SoupCookie *c = (SoupCookie*)p->data;
+ if (soup_cookie_equal (cookie, c)) {
+ cookies = g_slist_delete_link (cookies, p);
+ g_hash_table_insert (priv->domains,
+ domain,
+ cookies);
+ soup_cookie_jar_changed (jar, c, NULL);
+ soup_cookie_free (c);
+ return;
+ }
+ }
+}
Modified: trunk/libsoup/soup-cookie-jar.h
==============================================================================
--- trunk/libsoup/soup-cookie-jar.h (original)
+++ trunk/libsoup/soup-cookie-jar.h Tue Nov 4 20:30:37 2008
@@ -25,27 +25,43 @@
typedef struct {
GObjectClass parent_class;
- void (*save) (SoupCookieJar *jar);
+ void (*save) (SoupCookieJar *jar);
+
+ /* signals */
+ void (*changed) (SoupCookieJar *jar,
+ SoupCookie *old_cookie,
+ SoupCookie *new_cookie);
/* Padding for future expansion */
void (*_libsoup_reserved1) (void);
void (*_libsoup_reserved2) (void);
void (*_libsoup_reserved3) (void);
- void (*_libsoup_reserved4) (void);
} SoupCookieJarClass;
-GType soup_cookie_jar_get_type (void);
+#define SOUP_COOKIE_JAR_READ_ONLY "read-only"
+
+GType soup_cookie_jar_get_type (void);
+
+SoupCookieJar *soup_cookie_jar_new (void);
+
+#ifndef LIBSOUP_DISABLE_DEPRECATED
+void soup_cookie_jar_save (SoupCookieJar *jar);
+#endif
+
+char *soup_cookie_jar_get_cookies (SoupCookieJar *jar,
+ SoupURI *uri,
+ gboolean for_http);
+void soup_cookie_jar_set_cookie (SoupCookieJar *jar,
+ SoupURI *uri,
+ const char *cookie);
-SoupCookieJar *soup_cookie_jar_new (void);
+void soup_cookie_jar_add_cookie (SoupCookieJar *jar,
+ SoupCookie *cookie);
+void soup_cookie_jar_delete_cookie (SoupCookieJar *jar,
+ SoupCookie *cookie);
-void soup_cookie_jar_save (SoupCookieJar *jar);
+GSList *soup_cookie_jar_all_cookies (SoupCookieJar *jar);
-char *soup_cookie_jar_get_cookies (SoupCookieJar *jar,
- SoupURI *uri,
- gboolean for_http);
-void soup_cookie_jar_set_cookie (SoupCookieJar *jar,
- SoupURI *uri,
- const char *cookie);
G_END_DECLS
Modified: trunk/libsoup/soup-cookie.c
==============================================================================
--- trunk/libsoup/soup-cookie.c (original)
+++ trunk/libsoup/soup-cookie.c Tue Nov 4 20:30:37 2008
@@ -122,6 +122,44 @@
* have a trailing ";".
*/
+GType
+soup_cookie_get_type (void)
+{
+ static volatile gsize type_volatile = 0;
+
+ if (g_once_init_enter (&type_volatile)) {
+ GType type = g_boxed_type_register_static (
+ g_intern_static_string ("SoupCookie"),
+ (GBoxedCopyFunc) soup_cookie_copy,
+ (GBoxedFreeFunc) soup_cookie_free);
+ g_once_init_leave (&type_volatile, type);
+ }
+ return type_volatile;
+}
+
+/**
+ * soup_cookie_copy:
+ * @cookie: a #SoupCookie
+ *
+ * Copies @cookie.
+ **/
+SoupCookie *
+soup_cookie_copy (SoupCookie *cookie)
+{
+ SoupCookie *copy = g_slice_new0 (SoupCookie);
+
+ copy->name = g_strdup (cookie->name);
+ copy->value = g_strdup (cookie->value);
+ copy->domain = g_strdup (cookie->domain);
+ copy->path = g_strdup (cookie->path);
+ if (cookie->expires)
+ copy->expires = soup_date_copy(cookie->expires);
+ copy->secure = cookie->secure;
+ copy->http_only = cookie->http_only;
+
+ return copy;
+}
+
static gboolean
domain_matches (const char *domain, const char *host)
{
@@ -132,6 +170,8 @@
return TRUE;
if (*domain != '.')
return FALSE;
+ if (!g_ascii_strcasecmp (domain + 1, host))
+ return TRUE;
dlen = strlen (domain);
while ((match = strstr (host, domain))) {
if (!match[dlen])
@@ -883,5 +923,16 @@
if (uri->path[plen] && uri->path[plen] != '/')
return FALSE;
- return TRUE;
+ return !strncmp (cookie->path, uri->path, plen);
+}
+
+gboolean
+soup_cookie_equal (SoupCookie *cookie1, SoupCookie *cookie2)
+{
+ g_return_val_if_fail (cookie1, FALSE);
+ g_return_val_if_fail (cookie2, FALSE);
+
+ return (!strcmp (cookie1->name, cookie2->name) &&
+ !strcmp (cookie1->value, cookie2->value) &&
+ !strcmp (cookie1->path, cookie2->path));
}
Modified: trunk/libsoup/soup-cookie.h
==============================================================================
--- trunk/libsoup/soup-cookie.h (original)
+++ trunk/libsoup/soup-cookie.h Tue Nov 4 20:30:37 2008
@@ -20,6 +20,9 @@
gboolean http_only;
};
+GType soup_cookie_get_type (void);
+#define SOUP_TYPE_COOKIE (soup_cookie_get_type())
+
#define SOUP_COOKIE_MAX_AGE_ONE_HOUR (60 * 60)
#define SOUP_COOKIE_MAX_AGE_ONE_DAY (SOUP_COOKIE_MAX_AGE_ONE_HOUR * 24)
#define SOUP_COOKIE_MAX_AGE_ONE_WEEK (SOUP_COOKIE_MAX_AGE_ONE_DAY * 7)
@@ -32,6 +35,7 @@
int max_age);
SoupCookie *soup_cookie_parse (const char *header,
SoupURI *origin);
+SoupCookie *soup_cookie_copy (SoupCookie *cookie);
void soup_cookie_set_name (SoupCookie *cookie,
const char *name);
@@ -53,6 +57,11 @@
char *soup_cookie_to_set_cookie_header (SoupCookie *cookie);
char *soup_cookie_to_cookie_header (SoupCookie *cookie);
+gboolean soup_cookie_applies_to_uri (SoupCookie *cookie,
+ SoupURI *uri);
+gboolean soup_cookie_equal (SoupCookie *cookie1,
+ SoupCookie *cookie2);
+
void soup_cookie_free (SoupCookie *cookie);
GSList *soup_cookies_from_response (SoupMessage *msg);
@@ -67,9 +76,6 @@
char *soup_cookies_to_cookie_header (GSList *cookies);
-gboolean soup_cookie_applies_to_uri (SoupCookie *cookie,
- SoupURI *uri);
-
G_END_DECLS
#endif /* SOUP_COOKIE_H */
Modified: trunk/libsoup/soup-gnome.h
==============================================================================
--- trunk/libsoup/soup-gnome.h (original)
+++ trunk/libsoup/soup-gnome.h Tue Nov 4 20:30:37 2008
@@ -8,6 +8,7 @@
#include <libsoup/soup.h>
+#include <libsoup/soup-cookie-jar-sqlite.h>
#include <libsoup/soup-gnome-features.h>
#endif /* SOUP_GNOME_H */
Modified: trunk/libsoup/soup-marshal.list
==============================================================================
--- trunk/libsoup/soup-marshal.list (original)
+++ trunk/libsoup/soup-marshal.list Tue Nov 4 20:30:37 2008
@@ -4,4 +4,5 @@
NONE:OBJECT
NONE:OBJECT,OBJECT
NONE:OBJECT,POINTER
+NONE:BOXED,BOXED
NONE:OBJECT,OBJECT,BOOLEAN
Modified: trunk/libsoup/soup.h
==============================================================================
--- trunk/libsoup/soup.h (original)
+++ trunk/libsoup/soup.h Tue Nov 4 20:30:37 2008
@@ -17,6 +17,7 @@
#include <libsoup/soup-auth-domain-digest.h>
#include <libsoup/soup-cookie.h>
#include <libsoup/soup-cookie-jar.h>
+#include <libsoup/soup-cookie-jar-text.h>
#include <libsoup/soup-date.h>
#include <libsoup/soup-enum-types.h>
#include <libsoup/soup-form.h>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]