diff options
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | gst-libs/gst/Makefile.am | 1 | ||||
-rw-r--r-- | gst-libs/gst/http/Makefile.am | 26 | ||||
-rw-r--r-- | gst-libs/gst/http/gsthttpcookie.c | 504 | ||||
-rw-r--r-- | gst-libs/gst/http/gsthttpcookie.h | 111 | ||||
-rw-r--r-- | gst-libs/gst/http/gsthttpcookiejar.c | 381 | ||||
-rw-r--r-- | gst-libs/gst/http/gsthttpcookiejar.h | 84 | ||||
-rw-r--r-- | pkgconfig/Makefile.am | 5 | ||||
-rw-r--r-- | pkgconfig/gstreamer-http-uninstalled.pc.in | 16 | ||||
-rw-r--r-- | pkgconfig/gstreamer-http.pc.in | 16 | ||||
-rw-r--r-- | pkgconfig/gstreamer-plugins-base-uninstalled.pc.in | 4 | ||||
-rw-r--r-- | pkgconfig/gstreamer-plugins-base.pc.in | 2 |
12 files changed, 1149 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac index 44db09836..051b22f1f 100644 --- a/configure.ac +++ b/configure.ac @@ -867,6 +867,7 @@ gst-libs/gst/allocators/Makefile gst-libs/gst/audio/Makefile gst-libs/gst/app/Makefile gst-libs/gst/fft/Makefile +gst-libs/gst/http/Makefile gst-libs/gst/riff/Makefile gst-libs/gst/rtp/Makefile gst-libs/gst/rtsp/Makefile @@ -885,6 +886,8 @@ pkgconfig/gstreamer-app.pc pkgconfig/gstreamer-app-uninstalled.pc pkgconfig/gstreamer-fft.pc pkgconfig/gstreamer-fft-uninstalled.pc +pkgconfig/gstreamer-http.pc +pkgconfig/gstreamer-http-uninstalled.pc pkgconfig/gstreamer-pbutils.pc pkgconfig/gstreamer-pbutils-uninstalled.pc pkgconfig/gstreamer-riff.pc diff --git a/gst-libs/gst/Makefile.am b/gst-libs/gst/Makefile.am index ae796ff90..a00381eea 100644 --- a/gst-libs/gst/Makefile.am +++ b/gst-libs/gst/Makefile.am @@ -1,6 +1,7 @@ SUBDIRS = \ tag \ fft \ + http \ rtp \ sdp \ rtsp \ diff --git a/gst-libs/gst/http/Makefile.am b/gst-libs/gst/http/Makefile.am new file mode 100644 index 000000000..6fa8587e1 --- /dev/null +++ b/gst-libs/gst/http/Makefile.am @@ -0,0 +1,26 @@ +lib_LTLIBRARIES = libgsthttp-@GST_API_VERSION@.la + +libgsthttp_@GST_API_VERSION@_la_SOURCES = \ + gsthttpcookie.c gsthttpcookiejar.c + +libgsthttp_@GST_API_VERSION@includedir = \ + $(includedir)/gstreamer-@GST_API_VERSION@/gst/http + +libgsthttp_@GST_API_VERSION@include_HEADERS = \ + gsthttpcookie.h gsthttpcookiejar.h + +noinst_HEADERS = + +libgsthttp_@GST_API_VERSION@_la_CFLAGS = \ + $(GST_PLUGINS_BAD_CFLAGS) \ + -DGST_USE_UNSTABLE_API \ + $(GST_CFLAGS) + +libgsthttp_@GST_API_VERSION@_la_LIBADD = \ + $(GST_BASE_LIBS) \ + $(GST_LIBS) + +libgsthttp_@GST_API_VERSION@_la_LDFLAGS = \ + $(GST_LIB_LDFLAGS) \ + $(GST_ALL_LDFLAGS) \ + $(GST_LT_LDFLAGS) diff --git a/gst-libs/gst/http/gsthttpcookie.c b/gst-libs/gst/http/gsthttpcookie.c new file mode 100644 index 000000000..0ab3d8728 --- /dev/null +++ b/gst-libs/gst/http/gsthttpcookie.c @@ -0,0 +1,504 @@ +/* GStreamer HTTP library + * + * Copyright (C) 2007 Red Hat, Inc. + * Copyright (C) 2016 Samsung Electronics. All rights reserved. + * Author: Thiago Santos <thiagoss@osg.samsung.com> + * + * 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; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/* + * This code was copied from libsoup at commit + * 45cf9db7d46ff6ecabd6bbd4e7ae99cfefbc1626 + * on 20/01/2016. + * + * libsoup is LGPL v2. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <string.h> + +#include "gsthttpcookie.h" + +/** + * SECTION:gst-http-cookie + * @short_description: HTTP Cookies + * @see_also: #GstHttpCookieJar + * + * #GstHttpCookie implements HTTP cookies, as described by <ulink + * url="http://tools.ietf.org/html/rfc6265.txt">RFC 6265</ulink>. + **/ + +/** + * GstHttpCookie: + * @name: the cookie name + * @value: the cookie value + * @domain: the "domain" attribute, or else the hostname that the + * cookie came from. + * @path: the "path" attribute, or %NULL + * @expires: the cookie expiration time, or %NULL for a session cookie + * @secure: %TRUE if the cookie should only be tranferred over SSL + * @http_only: %TRUE if the cookie should not be exposed to scripts + * + * An HTTP cookie. + * + * @name and @value will be set for all cookies. If the cookie is + * generated from a string that appears to have no name, then @name + * will be the empty string. + * + * @domain and @path give the host or domain, and path within that + * host/domain, to restrict this cookie to. If @domain starts with + * ".", that indicates a domain (which matches the string after the + * ".", or any hostname that has @domain as a suffix). Otherwise, it + * is a hostname and must match exactly. + * + * @expires will be non-%NULL if the cookie uses either the original + * "expires" attribute, or the newer "max-age" attribute. If @expires + * is %NULL, it indicates that neither "expires" nor "max-age" was + * specified, and the cookie expires at the end of the session. + * + * If @http_only is set, the cookie should not be exposed to untrusted + * code (eg, javascript), so as to minimize the danger posed by + * cross-site scripting attacks. + * + * Since: 1.10 + **/ + +G_DEFINE_BOXED_TYPE (GstHttpCookie, gst_http_cookie, gst_http_cookie_copy, + gst_http_cookie_free); + +/** + * gst_http_cookie_copy: + * @cookie: a #GstHttpCookie + * + * Copies @cookie. + * + * Return value: a copy of @cookie + * + * Since: 1.10 + **/ +GstHttpCookie * +gst_http_cookie_copy (GstHttpCookie * cookie) +{ + GstHttpCookie *copy = g_slice_new0 (GstHttpCookie); + + 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 = g_date_time_ref (cookie->expires); + copy->secure = cookie->secure; + copy->http_only = cookie->http_only; + + return copy; +} + +static GstHttpCookie * +cookie_new_internal (const char *name, const char *value, + const char *domain, const char *path, int max_age) +{ + GstHttpCookie *cookie; + + cookie = g_slice_new0 (GstHttpCookie); + cookie->name = g_strdup (name); + cookie->value = g_strdup (value); + cookie->domain = g_strdup (domain); + cookie->path = g_strdup (path); + gst_http_cookie_set_max_age (cookie, max_age); + + return cookie; +} + +/** + * gst_http_cookie_new: + * @name: cookie name + * @value: cookie value + * @domain: cookie domain or hostname + * @path: cookie path, or %NULL + * @max_age: max age of the cookie, or -1 for a session cookie + * + * Creates a new #GstHttpCookie with the given attributes. (Use + * gst_http_cookie_set_secure() and gst_http_cookie_set_http_only() if you + * need to set those attributes on the returned cookie.) + * + * If @domain starts with ".", that indicates a domain (which matches + * the string after the ".", or any hostname that has @domain as a + * suffix). Otherwise, it is a hostname and must match exactly. + * + * @max_age is used to set the "expires" attribute on the cookie; pass + * -1 to not include the attribute (indicating that the cookie expires + * with the current session), 0 for an already-expired cookie, or a + * lifetime in seconds. + * + * Return value: a new #GstHttpCookie. + * + * Since: 1.10 + **/ +GstHttpCookie * +gst_http_cookie_new (const char *name, const char *value, + const char *domain, const char *path, int max_age) +{ + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (value != NULL, NULL); + + /* We ought to return if domain is NULL too, but this used to + * do be incorrectly documented as legal, and it wouldn't + * break anything as long as you called + * gst_http_cookie_set_domain() immediately after. So we warn but + * don't return, to discourage that behavior but not actually + * break anyone doing it. + */ + g_warn_if_fail (domain != NULL); + + return cookie_new_internal (name, value, domain, path, max_age); +} + +/** + * gst_http_cookie_get_name: + * @cookie: a #GstHttpCookie + * + * Gets @cookie's name + * + * Return value: @cookie's name + * + * Since: 1.10 + **/ +const char * +gst_http_cookie_get_name (GstHttpCookie * cookie) +{ + return cookie->name; +} + +/** + * gst_http_cookie_set_name: + * @cookie: a #GstHttpCookie + * @name: the new name + * + * Sets @cookie's name to @name + * + * Since: 1.10 + **/ +void +gst_http_cookie_set_name (GstHttpCookie * cookie, const char *name) +{ + g_free (cookie->name); + cookie->name = g_strdup (name); +} + +/** + * gst_http_cookie_get_value: + * @cookie: a #GstHttpCookie + * + * Gets @cookie's value + * + * Return value: @cookie's value + * + * Since: 1.10 + **/ +const char * +gst_http_cookie_get_value (GstHttpCookie * cookie) +{ + return cookie->value; +} + +/** + * gst_http_cookie_set_value: + * @cookie: a #GstHttpCookie + * @value: the new value + * + * Sets @cookie's value to @value + * + * Since: 1.10 + **/ +void +gst_http_cookie_set_value (GstHttpCookie * cookie, const char *value) +{ + g_free (cookie->value); + cookie->value = g_strdup (value); +} + +/** + * gst_http_cookie_get_domain: + * @cookie: a #GstHttpCookie + * + * Gets @cookie's domain + * + * Return value: @cookie's domain + * + * Since: 1.10 + **/ +const char * +gst_http_cookie_get_domain (GstHttpCookie * cookie) +{ + return cookie->domain; +} + +/** + * gst_http_cookie_set_domain: + * @cookie: a #GstHttpCookie + * @domain: the new domain + * + * Sets @cookie's domain to @domain + * + * Since: 1.10 + **/ +void +gst_http_cookie_set_domain (GstHttpCookie * cookie, const char *domain) +{ + g_free (cookie->domain); + cookie->domain = g_strdup (domain); +} + +/** + * gst_http_cookie_get_path: + * @cookie: a #GstHttpCookie + * + * Gets @cookie's path + * + * Return value: @cookie's path + * + * Since: 1.10 + **/ +const char * +gst_http_cookie_get_path (GstHttpCookie * cookie) +{ + return cookie->path; +} + +/** + * gst_http_cookie_set_path: + * @cookie: a #GstHttpCookie + * @path: the new path + * + * Sets @cookie's path to @path + * + * Since: 1.10 + **/ +void +gst_http_cookie_set_path (GstHttpCookie * cookie, const char *path) +{ + g_free (cookie->path); + cookie->path = g_strdup (path); +} + +/** + * gst_http_cookie_set_max_age: + * @cookie: a #GstHttpCookie + * @max_age: the new max age + * + * Sets @cookie's max age to @max_age. If @max_age is -1, the cookie + * is a session cookie, and will expire at the end of the client's + * session. Otherwise, it is the number of seconds until the cookie + * expires. (A value of 0 indicates that the cookie should be + * considered already-expired.) + * + * (This sets the same property as gst_http_cookie_set_expires().) + * + * Since: 1.10 + **/ +void +gst_http_cookie_set_max_age (GstHttpCookie * cookie, int max_age) +{ + if (cookie->expires) + g_date_time_unref (cookie->expires); + + if (max_age == -1) + cookie->expires = NULL; + else if (max_age == 0) { + /* Use a date way in the past, to protect against + * clock skew. + */ + cookie->expires = g_date_time_new (NULL, 1970, 1, 1, 0, 0, 0); + } else { + GDateTime *now = g_date_time_new_now_local (); + cookie->expires = g_date_time_add_seconds (now, max_age); + g_date_time_unref (now); + } +} + +/** + * gst_http_cookie_get_expires: + * @cookie: a #GstHttpCookie + * + * Gets @cookie's expiration time + * + * Return value: (transfer none): @cookie's expiration time, which is + * owned by @cookie and should not be modified or freed. + * + * Since: 1.10 + **/ +GDateTime * +gst_http_cookie_get_expires (GstHttpCookie * cookie) +{ + return cookie->expires; +} + +/** + * gst_http_cookie_set_expires: + * @cookie: a #GstHttpCookie + * @expires: the new expiration time, or %NULL + * + * Sets @cookie's expiration time to @expires. If @expires is %NULL, + * @cookie will be a session cookie and will expire at the end of the + * client's session. + * + * (This sets the same property as gst_http_cookie_set_max_age().) + * + * Since: 1.10 + **/ +void +gst_http_cookie_set_expires (GstHttpCookie * cookie, GDateTime * expires) +{ + if (cookie->expires) + g_date_time_unref (cookie->expires); + + if (expires) + cookie->expires = g_date_time_ref (expires); + else + cookie->expires = NULL; +} + +/** + * gst_http_cookie_get_secure: + * @cookie: a #GstHttpCookie + * + * Gets @cookie's secure attribute + * + * Return value: @cookie's secure attribute + * + * Since: 1.10 + **/ +gboolean +gst_http_cookie_get_secure (GstHttpCookie * cookie) +{ + return cookie->secure; +} + +/** + * gst_http_cookie_set_secure: + * @cookie: a #GstHttpCookie + * @secure: the new value for the secure attribute + * + * Sets @cookie's secure attribute to @secure. If %TRUE, @cookie will + * only be transmitted from the client to the server over secure + * (https) connections. + * + * Since: 1.10 + **/ +void +gst_http_cookie_set_secure (GstHttpCookie * cookie, gboolean secure) +{ + cookie->secure = secure; +} + +/** + * gst_http_cookie_get_http_only: + * @cookie: a #GstHttpCookie + * + * Gets @cookie's HttpOnly attribute + * + * Return value: @cookie's HttpOnly attribute + * + * Since: 1.10 + **/ +gboolean +gst_http_cookie_get_http_only (GstHttpCookie * cookie) +{ + return cookie->http_only; +} + +/** + * gst_http_cookie_set_http_only: + * @cookie: a #GstHttpCookie + * @http_only: the new value for the HttpOnly attribute + * + * Sets @cookie's HttpOnly attribute to @http_only. If %TRUE, @cookie + * will be marked as "http only", meaning it should not be exposed to + * web page scripts or other untrusted code. + * + * Since: 1.10 + **/ +void +gst_http_cookie_set_http_only (GstHttpCookie * cookie, gboolean http_only) +{ + cookie->http_only = http_only; +} + +/** + * gst_http_cookie_free: + * @cookie: a #GstHttpCookie + * + * Frees @cookie + * + * Since: 1.10 + **/ +void +gst_http_cookie_free (GstHttpCookie * cookie) +{ + g_return_if_fail (cookie != NULL); + + g_free (cookie->name); + g_free (cookie->value); + g_free (cookie->domain); + g_free (cookie->path); + if (cookie->expires) + g_date_time_unref (cookie->expires); + + g_slice_free (GstHttpCookie, cookie); +} + +/** + * gst_http_cookies_free: (skip) + * @cookies: (element-type GstHttpCookie): a #GSList of #GstHttpCookie + * + * Frees @cookies. + * + * Since: 1.10 + **/ +void +gst_http_cookies_free (GSList * cookies) +{ + g_slist_free_full (cookies, (GDestroyNotify) gst_http_cookie_free); +} + +/** + * gst_http_cookie_equal: + * @cookie1: a #GstHttpCookie + * @cookie2: a #GstHttpCookie + * + * Tests if @cookie1 and @cookie2 are equal. + * + * Note that currently, this does not check that the cookie domains + * match. This may change in the future. + * + * Return value: whether the cookies are equal. + * + * Since: 1.10 + */ +gboolean +gst_http_cookie_equal (GstHttpCookie * cookie1, GstHttpCookie * 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)); +} diff --git a/gst-libs/gst/http/gsthttpcookie.h b/gst-libs/gst/http/gsthttpcookie.h new file mode 100644 index 000000000..ffceb01d4 --- /dev/null +++ b/gst-libs/gst/http/gsthttpcookie.h @@ -0,0 +1,111 @@ +/* GStreamer HTTP library + * + * Copyright (C) 2007 Red Hat, Inc. + * Copyright (C) 2016 Samsung Electronics. All rights reserved. + * Author: Thiago Santos <thiagoss@osg.samsung.com> + * + * 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; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/* + * This code was copied from libsoup at commit + * 45cf9db7d46ff6ecabd6bbd4e7ae99cfefbc1626 + * on 20/01/2016. + * + * libsoup is LGPL v2. + */ + +#ifndef GST_HTTP_COOKIE_H +#define GST_HTTP_COOKIE_H 1 + +#include <gst/gst.h> + +G_BEGIN_DECLS + +struct _GstHttpCookie { + char *name; + char *value; + char *domain; + char *path; + GDateTime *expires; + gboolean secure; + gboolean http_only; +}; + +typedef struct _GstHttpCookie GstHttpCookie; + +GType gst_http_cookie_get_type (void); +#define GST_TYPE_HTTP_COOKIE (gst_http_cookie_get_type()) + +GstHttpCookie *gst_http_cookie_new (const char *name, + const char *value, + const char *domain, + const char *path, + int max_age); + +GstHttpCookie *gst_http_cookie_copy (GstHttpCookie *cookie); + + +const char *gst_http_cookie_get_name (GstHttpCookie *cookie); + +void gst_http_cookie_set_name (GstHttpCookie *cookie, + const char *name); + +const char *gst_http_cookie_get_value (GstHttpCookie *cookie); + +void gst_http_cookie_set_value (GstHttpCookie *cookie, + const char *value); + +const char *gst_http_cookie_get_domain (GstHttpCookie *cookie); + +void gst_http_cookie_set_domain (GstHttpCookie *cookie, + const char *domain); + +const char *gst_http_cookie_get_path (GstHttpCookie *cookie); + +void gst_http_cookie_set_path (GstHttpCookie *cookie, + const char *path); + +void gst_http_cookie_set_max_age (GstHttpCookie *cookie, + int max_age); + +GDateTime *gst_http_cookie_get_expires (GstHttpCookie *cookie); + +void gst_http_cookie_set_expires (GstHttpCookie *cookie, + GDateTime *expires); + +gboolean gst_http_cookie_get_secure (GstHttpCookie *cookie); + +void gst_http_cookie_set_secure (GstHttpCookie *cookie, + gboolean secure); + +gboolean gst_http_cookie_get_http_only (GstHttpCookie *cookie); + +void gst_http_cookie_set_http_only (GstHttpCookie *cookie, + gboolean http_only); + + +gboolean gst_http_cookie_equal (GstHttpCookie *cookie1, + GstHttpCookie *cookie2); + + +void gst_http_cookie_free (GstHttpCookie *cookie); + + +void gst_http_cookies_free (GSList *cookies); + +G_END_DECLS + +#endif /* GST_HTTP_COOKIE_H */ diff --git a/gst-libs/gst/http/gsthttpcookiejar.c b/gst-libs/gst/http/gsthttpcookiejar.c new file mode 100644 index 000000000..d737c0b49 --- /dev/null +++ b/gst-libs/gst/http/gsthttpcookiejar.c @@ -0,0 +1,381 @@ +/* GStreamer HTTP library + * + * Copyright (C) 2008 Red Hat, Inc. + * Copyright (C) 2016 Samsung Electronics. All rights reserved. + * Author: Thiago Santos <thiagoss@osg.samsung.com> + * + * 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; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/* + * This code was copied from libsoup at commit + * 45cf9db7d46ff6ecabd6bbd4e7ae99cfefbc1626 + * on 20/01/2016. + * + * libsoup is LGPL v2. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> +#include <gst/gst.h> + +#include "gsthttpcookiejar.h" + +/** + * SECTION:gst-http-cookie-jar + * @short_description: Automatic cookie sharing + * + * A #GstHttpCookieJar stores #GstHttpCookie<!-- -->s. + * + * Note that the base #GstHttpCookieJar class does not support any form + * of long-term cookie persistence. + **/ + +G_DEFINE_TYPE (GstHttpCookieJar, gst_http_cookie_jar, GST_TYPE_OBJECT); + +enum +{ + CHANGED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +typedef struct +{ + gboolean constructed; + GHashTable *domains, *serials; + guint serial; +} GstHttpCookieJarPrivate; +#define GST_HTTP_COOKIE_JAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GST_TYPE_HTTP_COOKIE_JAR, GstHttpCookieJarPrivate)) + +/** + * gst_http_str_case_hash: + * @key: ASCII string to hash + * + * Hashes @key in a case-insensitive manner. + * + * Return value: the hash code. + **/ +static guint +gst_http_str_case_hash (gconstpointer key) +{ + const char *p = key; + guint h = g_ascii_toupper (*p); + + if (h) + for (p += 1; *p != '\0'; p++) + h = (h << 5) - h + g_ascii_toupper (*p); + + return h; +} + +/** + * gst_http_str_case_equal: + * @v1: an ASCII string + * @v2: another ASCII string + * + * Compares @v1 and @v2 in a case-insensitive manner + * + * Return value: %TRUE if they are equal (modulo case) + **/ +static gboolean +gst_http_str_case_equal (gconstpointer v1, gconstpointer v2) +{ + const char *string1 = v1; + const char *string2 = v2; + + return g_ascii_strcasecmp (string1, string2) == 0; +} + + +static void +gst_http_cookie_jar_init (GstHttpCookieJar * jar) +{ + GstHttpCookieJarPrivate *priv = GST_HTTP_COOKIE_JAR_GET_PRIVATE (jar); + + priv->domains = g_hash_table_new_full (gst_http_str_case_hash, + gst_http_str_case_equal, g_free, NULL); + priv->serials = g_hash_table_new (NULL, NULL); +} + +static void +gst_http_cookie_jar_constructed (GObject * object) +{ + GstHttpCookieJarPrivate *priv = GST_HTTP_COOKIE_JAR_GET_PRIVATE (object); + + priv->constructed = TRUE; +} + +static void +gst_http_cookie_jar_finalize (GObject * object) +{ + GstHttpCookieJarPrivate *priv = GST_HTTP_COOKIE_JAR_GET_PRIVATE (object); + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init (&iter, priv->domains); + while (g_hash_table_iter_next (&iter, &key, &value)) + gst_http_cookies_free (value); + g_hash_table_destroy (priv->domains); + g_hash_table_destroy (priv->serials); + + G_OBJECT_CLASS (gst_http_cookie_jar_parent_class)->finalize (object); +} + +static void +gst_http_cookie_jar_class_init (GstHttpCookieJarClass * jar_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (jar_class); + + g_type_class_add_private (jar_class, sizeof (GstHttpCookieJarPrivate)); + + object_class->constructed = gst_http_cookie_jar_constructed; + object_class->finalize = gst_http_cookie_jar_finalize; + + /** + * GstHttpCookieJar::changed: + * @jar: the #GstHttpCookieJar + * @author: a pointer to the author of the change + * @old_cookie: the old #GstHttpCookie value + * @new_cookie: the new #GstHttpCookie value + * + * Emitted when @jar changes. If a cookie has been added, + * @new_cookie will contain the newly-added cookie and + * @old_cookie will be %NULL. If a cookie has been deleted, + * @old_cookie will contain the to-be-deleted cookie and + * @new_cookie will be %NULL. If a cookie has been changed, + * @old_cookie will contain its old value, and @new_cookie its + * new value. + * + * Signal listeners should check the author field to verify + * if the change was made by themselves and ignore that change + **/ + signals[CHANGED] = + g_signal_new ("changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GstHttpCookieJarClass, changed), + NULL, NULL, + NULL, + G_TYPE_NONE, 3, + G_TYPE_POINTER | G_SIGNAL_TYPE_STATIC_SCOPE, + GST_TYPE_HTTP_COOKIE | G_SIGNAL_TYPE_STATIC_SCOPE, + GST_TYPE_HTTP_COOKIE | G_SIGNAL_TYPE_STATIC_SCOPE); +} + +/** + * gst_http_cookie_jar_new: + * + * Creates a new #GstHttpCookieJar. The base #GstHttpCookieJar class does + * not support persistent storage of cookies; use a subclass for that. + * + * Returns: a new #GstHttpCookieJar + * + * Since: 1.10 + **/ +GstHttpCookieJar * +gst_http_cookie_jar_new (void) +{ + return g_object_new (GST_TYPE_HTTP_COOKIE_JAR, NULL); +} + +static void +gst_http_cookie_jar_changed (GstHttpCookieJar * jar, gpointer author, + GstHttpCookie * old, GstHttpCookie * new) +{ + GstHttpCookieJarPrivate *priv = GST_HTTP_COOKIE_JAR_GET_PRIVATE (jar); + + if (old && old != new) + g_hash_table_remove (priv->serials, old); + if (new) { + priv->serial++; + g_hash_table_insert (priv->serials, new, GUINT_TO_POINTER (priv->serial)); + } + + if (!priv->constructed) + return; + + g_signal_emit (jar, signals[CHANGED], 0, author, old, new); +} + +static gboolean +date_time_is_past (GDateTime * dt) +{ + GDateTime *now = g_date_time_new_now_utc (); + GTimeSpan diff; + + diff = g_date_time_difference (now, dt); + + g_date_time_unref (now); + + return diff > 0; +} + +/** + * gst_http_cookie_jar_add_cookie: + * @jar: a #GstHttpCookieJar + * @cookie: (transfer full): a #GstHttpCookie + * + * 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. + * + * Since: 1.10 + **/ +void +gst_http_cookie_jar_add_cookie (GstHttpCookieJar * jar, gpointer author, + GstHttpCookie * cookie) +{ + GstHttpCookieJarPrivate *priv; + GSList *old_cookies, *oc, *last = NULL; + GstHttpCookie *old_cookie; + + g_return_if_fail (GST_HTTP_IS_COOKIE_JAR (jar)); + g_return_if_fail (cookie != NULL); + +#if 0 + /* Never accept cookies for public domains. */ + if (!g_hostname_is_ip_address (cookie->domain) && + soup_tld_domain_is_public_suffix (cookie->domain)) { + gst_http_cookie_free (cookie); + return; + } +#endif + + priv = GST_HTTP_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) && + !g_strcmp0 (cookie->path, old_cookie->path)) { + if (cookie->expires && 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 + * remove the cookie. + */ + old_cookies = g_slist_delete_link (old_cookies, oc); + g_hash_table_insert (priv->domains, + g_strdup (cookie->domain), old_cookies); + gst_http_cookie_jar_changed (jar, author, old_cookie, NULL); + gst_http_cookie_free (old_cookie); + gst_http_cookie_free (cookie); + } else { + oc->data = cookie; + /* TODO something else might have changed */ + if (strcmp (cookie->value, old_cookie->value)) + gst_http_cookie_jar_changed (jar, author, old_cookie, cookie); + gst_http_cookie_free (old_cookie); + } + + return; + } + last = oc; + } + + /* The new cookie is... a new cookie */ + if (cookie->expires && date_time_is_past (cookie->expires)) { + gst_http_cookie_free (cookie); + return; + } + + if (last) + last->next = g_slist_append (NULL, cookie); + else { + old_cookies = g_slist_append (NULL, cookie); + g_hash_table_insert (priv->domains, g_strdup (cookie->domain), old_cookies); + } + + gst_http_cookie_jar_changed (jar, author, NULL, cookie); +} + +/** + * gst_http_cookie_jar_all_cookies: + * @jar: a #GstHttpCookieJar + * + * 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: (transfer full) (element-type Soup.Cookie): a #GSList + * with all the cookies in the @jar. + * + * Since: 1.10 + **/ +GSList * +gst_http_cookie_jar_all_cookies (GstHttpCookieJar * jar) +{ + GstHttpCookieJarPrivate *priv; + GHashTableIter iter; + GSList *l = NULL; + gpointer key, value; + + g_return_val_if_fail (GST_HTTP_IS_COOKIE_JAR (jar), NULL); + + priv = GST_HTTP_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, gst_http_cookie_copy (p->data)); + } + + return l; +} + +/** + * gst_http_cookie_jar_delete_cookie: + * @jar: a #GstHttpCookieJar + * @cookie: a #GstHttpCookie + * + * Deletes @cookie from @jar, emitting the 'changed' signal. + * + * Since: 1.10 + **/ +void +gst_http_cookie_jar_delete_cookie (GstHttpCookieJar * jar, gpointer author, + GstHttpCookie * cookie) +{ + GstHttpCookieJarPrivate *priv; + GSList *cookies, *p; + + g_return_if_fail (GST_HTTP_IS_COOKIE_JAR (jar)); + g_return_if_fail (cookie != NULL); + + priv = GST_HTTP_COOKIE_JAR_GET_PRIVATE (jar); + + cookies = g_hash_table_lookup (priv->domains, cookie->domain); + if (cookies == NULL) + return; + + for (p = cookies; p; p = p->next) { + GstHttpCookie *c = (GstHttpCookie *) p->data; + if (gst_http_cookie_equal (cookie, c)) { + cookies = g_slist_delete_link (cookies, p); + g_hash_table_insert (priv->domains, g_strdup (cookie->domain), cookies); + gst_http_cookie_jar_changed (jar, author, c, NULL); + gst_http_cookie_free (c); + return; + } + } +} diff --git a/gst-libs/gst/http/gsthttpcookiejar.h b/gst-libs/gst/http/gsthttpcookiejar.h new file mode 100644 index 000000000..74a57e060 --- /dev/null +++ b/gst-libs/gst/http/gsthttpcookiejar.h @@ -0,0 +1,84 @@ +/* GStreamer HTTP library + * + * Copyright (C) 2008 Red Hat, Inc. + * Copyright (C) 2016 Samsung Electronics. All rights reserved. + * Author: Thiago Santos <thiagoss@osg.samsung.com> + * + * 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; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/* + * This code was copied from libsoup at commit + * 45cf9db7d46ff6ecabd6bbd4e7ae99cfefbc1626 + * on 20/01/2016. + * + * libsoup is LGPL v2. + */ + +#ifndef GST_HTTP_COOKIE_JAR_H +#define GST_HTTP_COOKIE_JAR_H 1 + +#include <gst/gst.h> +#include "gsthttpcookie.h" + +G_BEGIN_DECLS + +#define GST_TYPE_HTTP_COOKIE_JAR (gst_http_cookie_jar_get_type ()) +#define GST_HTTP_COOKIE_JAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_HTTP_COOKIE_JAR, GstHttpCookieJar)) +#define GST_HTTP_COOKIE_JAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_HTTP_COOKIE_JAR, GstHttpCookieJarClass)) +#define GST_HTTP_IS_COOKIE_JAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_HTTP_COOKIE_JAR)) +#define GST_HTTP_IS_COOKIE_JAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), GST_TYPE_HTTP_COOKIE_JAR)) +#define GST_HTTP_COOKIE_JAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_HTTP_COOKIE_JAR, GstHttpCookieJarClass)) + +typedef struct _GstHttpCookieJar { + GstObject parent; + +} GstHttpCookieJar; + +typedef struct { + GstObjectClass parent_class; + + /* signals */ + void (*changed) (GstHttpCookieJar *jar, + gpointer author, + GstHttpCookie *old_cookie, + GstHttpCookie *new_cookie); + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); +} GstHttpCookieJarClass; + +GType gst_http_cookie_jar_get_type (void); + +GstHttpCookieJar * gst_http_cookie_jar_new (void); + +void gst_http_cookie_jar_add_cookie (GstHttpCookieJar *jar, + gpointer author, + GstHttpCookie *cookie); + +void gst_http_cookie_jar_add_cookie_with_first_party (GstHttpCookieJar *jar, + gchar *first_party, + GstHttpCookie *cookie); + +void gst_http_cookie_jar_delete_cookie (GstHttpCookieJar *jar, + gpointer author, + GstHttpCookie *cookie); + +GSList * gst_http_cookie_jar_all_cookies (GstHttpCookieJar *jar); + +G_END_DECLS + +#endif /* GST_HTTP_COOKIE_JAR_H */ diff --git a/pkgconfig/Makefile.am b/pkgconfig/Makefile.am index 9976f95ef..73c1a41fc 100644 --- a/pkgconfig/Makefile.am +++ b/pkgconfig/Makefile.am @@ -4,6 +4,7 @@ pcverfiles = \ gstreamer-audio-@GST_API_VERSION@.pc \ gstreamer-app-@GST_API_VERSION@.pc \ gstreamer-fft-@GST_API_VERSION@.pc \ + gstreamer-http-@GST_API_VERSION@.pc \ gstreamer-pbutils-@GST_API_VERSION@.pc \ gstreamer-riff-@GST_API_VERSION@.pc \ gstreamer-rtp-@GST_API_VERSION@.pc \ @@ -17,6 +18,7 @@ pcverfiles_uninstalled = \ gstreamer-audio-@GST_API_VERSION@-uninstalled.pc \ gstreamer-app-@GST_API_VERSION@-uninstalled.pc \ gstreamer-fft-@GST_API_VERSION@-uninstalled.pc \ + gstreamer-http-@GST_API_VERSION@-uninstalled.pc \ gstreamer-pbutils-@GST_API_VERSION@-uninstalled.pc \ gstreamer-riff-@GST_API_VERSION@-uninstalled.pc \ gstreamer-rtp-@GST_API_VERSION@-uninstalled.pc \ @@ -43,10 +45,11 @@ pkgconfig_DATA = $(pcverfiles) CLEANFILES = $(pcverfiles) $(pcverfiles_uninstalled) pcinfiles = \ - gstreamer-allocators.pc.in gstreamer-allocators-uninstalled.pc.in \ + gstreamer-allocators.pc.in gstreamer-allocators-uninstalled.pc.in \ gstreamer-audio.pc.in gstreamer-audio-uninstalled.pc.in \ gstreamer-app.pc.in gstreamer-app-uninstalled.pc.in \ gstreamer-fft.pc.in gstreamer-fft-uninstalled.pc.in \ + gstreamer-http.pc.in gstreamer-http-uninstalled.pc.in \ gstreamer-pbutils.pc.in gstreamer-pbutils-uninstalled.pc.in \ gstreamer-riff.pc.in gstreamer-riff-uninstalled.pc.in \ gstreamer-rtp.pc.in gstreamer-rtp-uninstalled.pc.in \ diff --git a/pkgconfig/gstreamer-http-uninstalled.pc.in b/pkgconfig/gstreamer-http-uninstalled.pc.in new file mode 100644 index 000000000..c1e406618 --- /dev/null +++ b/pkgconfig/gstreamer-http-uninstalled.pc.in @@ -0,0 +1,16 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir= +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@/gst-libs +girdir=@abs_top_builddir@/gst-libs/gst/http +typelibdir=@abs_top_builddir@/gst-libs/gst/http + +Name: GStreamer HTTP Library, Uninstalled +Description: HTTP helper functions, uninstalled +Version: @VERSION@ +Requires: gstreamer-@GST_API_VERSION@ +Libs: @abs_top_builddir@/gst-libs/gst/http/libgsthttp-@GST_API_VERSION@.la +Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs + diff --git a/pkgconfig/gstreamer-http.pc.in b/pkgconfig/gstreamer-http.pc.in new file mode 100644 index 000000000..bdaa218ed --- /dev/null +++ b/pkgconfig/gstreamer-http.pc.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_API_VERSION@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer HTTP Library +Description: HTTP helper functions +Requires: gstreamer-@GST_API_VERSION@ +Version: @VERSION@ +Libs: -L${libdir} -lgsthttp-@GST_API_VERSION@ +Cflags: -I${includedir} + diff --git a/pkgconfig/gstreamer-plugins-base-uninstalled.pc.in b/pkgconfig/gstreamer-plugins-base-uninstalled.pc.in index 970c051bb..fd83167d9 100644 --- a/pkgconfig/gstreamer-plugins-base-uninstalled.pc.in +++ b/pkgconfig/gstreamer-plugins-base-uninstalled.pc.in @@ -10,7 +10,7 @@ Name: GStreamer Base Plugins Libraries, Uninstalled Description: Streaming media framework, base plugins libraries, uninstalled Version: @VERSION@ Requires: gstreamer-@GST_API_VERSION@ -Libs: -L@abs_top_builddir@/gst-libs/gst/allocators -L@abs_top_builddir@/gst-libs/gst/app -L@abs_top_builddir@/gst-libs/gst/audio -L@abs_top_builddir@/gst-libs/gst/fft -L@abs_top_builddir@/gst-libs/gst/pbutils -L@abs_top_builddir@/gst-libs/gst/riff -L@abs_top_builddir@/gst-libs/gst/rtp -L@abs_top_builddir@/gst-libs/gst/rtsp -L@abs_top_builddir@/gst-libs/gst/sdp -L@abs_top_builddir@/gst-libs/gst/tag -L@abs_top_builddir@/gst-libs/gst/video +Libs: -L@abs_top_builddir@/gst-libs/gst/allocators -L@abs_top_builddir@/gst-libs/gst/app -L@abs_top_builddir@/gst-libs/gst/audio -L@abs_top_builddir@/gst-libs/gst/fft -L@abs_top_builddir@/gst-libs/gst/http -L@abs_top_builddir@/gst-libs/gst/pbutils -L@abs_top_builddir@/gst-libs/gst/riff -L@abs_top_builddir@/gst-libs/gst/rtp -L@abs_top_builddir@/gst-libs/gst/rtsp -L@abs_top_builddir@/gst-libs/gst/sdp -L@abs_top_builddir@/gst-libs/gst/tag -L@abs_top_builddir@/gst-libs/gst/video Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs -libraries=allocators app audio fft pbutils riff rtp rtsp sdp tag video +libraries=allocators app audio fft http pbutils riff rtp rtsp sdp tag video diff --git a/pkgconfig/gstreamer-plugins-base.pc.in b/pkgconfig/gstreamer-plugins-base.pc.in index e81774665..5da075c4f 100644 --- a/pkgconfig/gstreamer-plugins-base.pc.in +++ b/pkgconfig/gstreamer-plugins-base.pc.in @@ -11,4 +11,4 @@ Version: @VERSION@ Libs: -L${libdir} Cflags: -I${includedir} -libraries=allocators app audio fft pbutils riff rtp rtsp sdp tag video +libraries=allocators app audio fft http pbutils riff rtp rtsp sdp tag video |