/*
 * Copyright (c) 2004 Nokia. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * 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.
 *
 * Neither the name of Nokia 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 "Cookie.h"
#include <assert.h>
#include <stdlib.h>
#include <time.h>
#include <glib.h>
#include <glib/gprintf.h>

extern long timezone;
extern int daylight;
 

Cookie::Cookie(const gchar * cookie,
               const gchar * url)
    : m_setCookieString(g_strdup(cookie))
    , m_url(g_strdup(url))
    , m_name(0)
    , m_value(0)
    , m_comment(0)
    , m_domain(0)
    , m_path(0)
    , m_maxAge(0)
    , m_secure(false)
    , m_version(1)    
{
  g_get_current_time(&m_received);
  
  assert(cookie);    
  gchar **chunks = g_strsplit(cookie, ";", 0);
  assert(chunks);
  assert(chunks[0]);
  
  gint i = 0;
  while(chunks[0][i] != '=' && chunks[0][i] != '\0') +i++;
  assert(chunks[0][i] != '\0');
  
  m_name = g_strstrip(g_strndup(chunks[0], i));
  m_value = g_strstrip(g_strdup(chunks[0] + i + 1));
  
  i = 1;
  while(chunks[i]) {
    parseCookie(g_strstrip(chunks[i]));
    ++i;
  }
  g_strfreev(chunks);


  // generate Cookie: -form of this string.
  GString* buffer = NULL;  
  buffer = g_string_sized_new (32);

  g_string_append_printf (buffer, "%s=%s", m_name, m_value);

  if (m_path)
    g_string_append_printf (buffer, ";$Path=%s", m_path);

  if (m_domain)
    g_string_append_printf (buffer, ";$Domain=%s", m_domain);
  
  /* Free only GString not data contained, return the data instead */
  m_cookieString = buffer->str;
  g_string_free (buffer, FALSE); 
}


#define COMMENT "Comment="
#define DOMAIN  "Domain="
#define MAX_AGE "Max-Age="
#define PATH    "Path="
#define SECURE  "Secure"
#define COOKIE_VERSION "Version="
// Old Netscape style cookies have this instead of Max-Age
#define EXPIRES "Expires="

#define COMMENT_LEN  8
#define DOMAIN_LEN   7
#define MAX_AGE_LEN  8
#define PATH_LEN     5
#define SECURE_LEN   6
#define VERSION_LEN  8
#define EXPIRES_LEN  8


void Cookie::parseCookie(const gchar * cookie) {
  gchar* endptr = 0;
  g_printf("parsing cookie %s\n", cookie);
  if (g_ascii_strncasecmp(cookie, COMMENT, COMMENT_LEN) == 0) {
    m_comment = g_strdup(cookie + COMMENT_LEN);
  } else if (g_ascii_strncasecmp(cookie, DOMAIN, DOMAIN_LEN) == 0) {
    m_domain = g_strdup(cookie + DOMAIN_LEN);
  } else if (g_ascii_strncasecmp(cookie, PATH, PATH_LEN) == 0) {
    m_path = g_strdup(cookie + PATH_LEN);
    g_printf("Path %s\n", m_path);
  } else if (g_ascii_strncasecmp(cookie, MAX_AGE, MAX_AGE_LEN) == 0) {
    const gchar * value = cookie + MAX_AGE_LEN;   
    m_maxAge = strtol(value, &endptr, 10);    
    if (!(*value != '\0' && endptr && *endptr=='\0'))
      m_maxAge = 0;    
#ifndef _WIN32
  } else if (g_ascii_strncasecmp(cookie, EXPIRES, EXPIRES_LEN) == 0) {
    tm time_tm;
    strptime(cookie + EXPIRES_LEN + 5, "%d-%b-%Y %T", &time_tm);
    time_t time = mktime(&time_tm);
    // This may not work properly around DST changes, but for now,
    // it'll have to do. -- psalmi
    m_maxAge = ((unsigned int) time) - (unsigned int) m_received.tv_sec - timezone;
#endif
  } else if (g_ascii_strncasecmp(cookie, SECURE, SECURE_LEN) == 0) {
    m_secure = true;
  } else if (g_ascii_strncasecmp(cookie, COOKIE_VERSION, VERSION_LEN) == 0) {
    m_version = strtol(cookie, &endptr, 10);
    if (!(*cookie != '\0' && endptr && *endptr=='\0'))
      m_version = 1;
  }
}



Cookie::~Cookie()
{
  if(m_setCookieString) g_free(m_setCookieString);
  if(m_cookieString) g_free(m_cookieString);
  if(m_url) g_free(m_url);
  if(m_name) g_free(m_name);
  if (m_value) g_free(m_value);
  if(m_comment) g_free(m_comment);
  if(m_domain) g_free(m_domain);
  if (m_path) g_free(m_path);
}
