/*
 * Copyright (C) 2004, 2005 Jean-Yves Lefort
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of Jean-Yves Lefort nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <string.h>
#include <libsoup/soup.h>
#include <libsoup/soup-message-filter.h>
#include "translate-generic-soup-cookie-jar.h"

struct _TranslateGenericSoupCookieJarPrivate
{
  GSList *cookies;
};

static GObjectClass *parent_class = NULL;

static void translate_generic_soup_cookie_jar_register_type (GType *type);
static void translate_generic_soup_cookie_jar_class_init (TranslateGenericSoupCookieJarClass *class);
static void translate_generic_soup_cookie_jar_init (TranslateGenericSoupCookieJar *jar);
static void translate_generic_soup_cookie_jar_filter_init (SoupMessageFilterClass *iface);
static void translate_generic_soup_cookie_jar_finalize (GObject *object);

static void translate_generic_soup_cookie_jar_setup_message (SoupMessageFilter *filter,
							     SoupMessage *message);

GType
translate_generic_soup_cookie_jar_get_type (void)
{
  static GType type;
  static GOnce once = G_ONCE_INIT;

  g_once(&once, (GThreadFunc) translate_generic_soup_cookie_jar_register_type, &type);

  return type;
}

static void
translate_generic_soup_cookie_jar_register_type (GType *type)
{
  static const GTypeInfo info = {
    sizeof(TranslateGenericSoupCookieJarClass),
    NULL,
    NULL,
    (GClassInitFunc) translate_generic_soup_cookie_jar_class_init,
    NULL,
    NULL,
    sizeof(TranslateGenericSoupCookieJar),
    0,
    (GInstanceInitFunc) translate_generic_soup_cookie_jar_init
  };
  static const GInterfaceInfo filter_info = {
    (GInterfaceInitFunc) translate_generic_soup_cookie_jar_filter_init,
    NULL,
    NULL
  };

  *type = g_type_register_static(G_TYPE_OBJECT,
				 "TranslateGenericSoupCookieJar",
				 &info,
				 0);
  g_type_add_interface_static(*type, SOUP_TYPE_MESSAGE_FILTER, &filter_info);
}

static void
translate_generic_soup_cookie_jar_class_init (TranslateGenericSoupCookieJarClass *class)
{
  GObjectClass *object_class = G_OBJECT_CLASS(class);

  g_type_class_add_private(class, sizeof(TranslateGenericSoupCookieJarPrivate));
  parent_class = g_type_class_peek_parent(class);

  object_class->finalize = translate_generic_soup_cookie_jar_finalize;
}

static void
translate_generic_soup_cookie_jar_init (TranslateGenericSoupCookieJar *jar)
{
  jar->priv = G_TYPE_INSTANCE_GET_PRIVATE(jar,
					  TRANSLATE_GENERIC_TYPE_SOUP_COOKIE_JAR,
					  TranslateGenericSoupCookieJarPrivate);
}

static void
translate_generic_soup_cookie_jar_filter_init (SoupMessageFilterClass *iface)
{
  iface->setup_message = translate_generic_soup_cookie_jar_setup_message;
}

static void
translate_generic_soup_cookie_jar_finalize (GObject *object)
{
  TranslateGenericSoupCookieJar *jar = TRANSLATE_GENERIC_SOUP_COOKIE_JAR(object);

  g_slist_foreach(jar->priv->cookies, (GFunc) g_free, NULL);
  g_slist_free(jar->priv->cookies);

  parent_class->finalize(object);
}

static void
translate_generic_soup_cookie_jar_setup_message (SoupMessageFilter *filter,
					 SoupMessage *message)
{
  TranslateGenericSoupCookieJar *jar = TRANSLATE_GENERIC_SOUP_COOKIE_JAR(filter);
  const GSList *cookies;
  const GSList *l;

  /* FIXME: add full RFC 2965 support */

  cookies = soup_message_get_header_list(message->response_headers, "Set-Cookie");
  for (l = cookies; l != NULL; l = l->next)
    {
      const char *cookie = l->data;
      char *s;

      s = strchr(cookie, ';');
      if (s)
	jar->priv->cookies = g_slist_append(jar->priv->cookies, g_strndup(cookie, s - cookie));
    }
  
  if (jar->priv->cookies)
    {
      GString *string;

      string = g_string_new(NULL);
      for (l = jar->priv->cookies; l != NULL; l = l->next)
	{
	  const char *cookie = l->data;

	  g_string_append(string, cookie);
	  if (l->next)
	    g_string_append(string, "; ");
	}

      soup_message_add_header(message->request_headers, "Cookie", string->str);
      g_string_free(string, TRUE);
    }
}

TranslateGenericSoupCookieJar *
translate_generic_soup_cookie_jar_new (void)
{
  return g_object_new(TRANSLATE_GENERIC_TYPE_SOUP_COOKIE_JAR, NULL);
}
