Logo Search packages:      
Sourcecode: autoprofile version File versions

comp_rss_parser.c

/*--------------------------------------------------------------------------*
 * AUTOPROFILE                                                              *
 *                                                                          *
 * A Gaim away message and profile manager that supports dynamic text       *
 *                                                                          *
 * AutoProfile is the legal property of its developers.  Please refer to    *
 * the COPYRIGHT file distributed with this source distribution.            *
 *                                                                          *
 * This program is free software; you can redistribute it and/or modify     *
 * it under the terms of the GNU General Public License as published by     *
 * the Free Software Foundation; either version 2 of the License, or        *
 * (at your option) any later version.                                      *
 *                                                                          *
 * This program 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 General Public License for more details.                             *
 *                                                                          *
 * You should have received a copy of the GNU General Public License        *
 * along with this program; if not, write to the Free Software              *
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA *
 *--------------------------------------------------------------------------*/

#include "comp_rss.h"
#include "utility.h"

GList *entries = NULL;

static gboolean parsing_rss = FALSE;
static gboolean parsing_item = FALSE;

static gboolean item_title = FALSE;
static gboolean item_link = FALSE;
static gboolean item_description = FALSE;
static gboolean item_comments = FALSE;
static gboolean item_pubdate = FALSE;

/* Get URL of RSS feed */
static char *get_url ()
{
  int type;
  char *ret;
  const char *username;

  type = gaim_prefs_get_int (
    "/plugins/gtk/autoprofile/components/rss/type");
  
  switch (type) {
    case RSS_LIVEJOURNAL:
      username = gaim_prefs_get_string (
        "/plugins/gtk/autoprofile/components/rss/username");
      ret = (char *) malloc (sizeof (char[50+MAX_USERNAME_LENGTH]));
      *ret = '\0';
      g_snprintf (ret, 50 + MAX_USERNAME_LENGTH,   
        "http://www.livejournal.com/users/%s/data/rss", username);
    break;
    case RSS_XANGA:
      username = gaim_prefs_get_string (
        "/plugins/gtk/autoprofile/components/rss/username");
      ret = (char *) malloc (sizeof (char[50+MAX_USERNAME_LENGTH]));
      *ret = '\0';
      g_snprintf (ret, 50 + MAX_USERNAME_LENGTH,
        "http://www.xanga.com/%s/rss", username);
    break;
    case RSS_2:
      ret = strdup (gaim_prefs_get_string (
        "/plugins/gtk/autoprofile/components/rss/location"));
    break;
    default:
      ret = strdup ("");
    break;
  }

  return ret;
}

/* Utility functions */
static void free_entries () {
  GList *tmp;
  struct rss_entry *e;

  while (entries) {
    e = (struct rss_entry *) entries->data;
    if (e->title)
      free (e->title);
    if (e->entry)
      free (e->entry);
    if (e->url)
      free (e->url);
    if (e->comments)
      free (e->comments);
    if (e->t)
      free (e->t);
  
    free (e);
    tmp = entries;
    entries = entries->next;
    g_list_free_1 (tmp);
  }
}


/* Date parsing functions */
static struct tm *parse_date_rfc822 (const char *date_string)
{
  time_t t, gmt_time, local_time;
  struct tm *ret, *result;
  
  local_time = time(NULL);
  gmt_time = time(NULL);
  gmt_time = mktime(gmtime(&gmt_time));  

  
  t = rfc_parse_date_time (date_string);
 // if (rfc_parse_was_gmt ()) {
    
 // } else {
    ret = (struct tm *) malloc (sizeof (struct tm));
    result = localtime(&t);
    ret->tm_sec = result->tm_sec;
    ret->tm_min = result->tm_min;
    ret->tm_hour = result->tm_hour;
    ret->tm_mday = result->tm_mday;
    ret->tm_mon = result->tm_mon;
    ret->tm_year = result->tm_year;
  //}

  return ret;
}

/* XML Parser Callbacks */
static void start_element_handler (GMarkupParseContext *context,
                                   const gchar *element_name,
                                   const gchar **attribuate_names,
                                   const gchar **attribute_values,
                                   gpointer user_data, GError **error)
{
  struct rss_entry *e;

  //printf ("start:%s\n", element_name);
 
  if (!parsing_rss && !strcmp (element_name, "rss"))
    parsing_rss = TRUE;

  else if (parsing_rss && !parsing_item && 
      !strcmp (element_name, "item")) {
    parsing_item = TRUE;
    e = (struct rss_entry *) malloc (sizeof(struct rss_entry));
    entries = g_list_prepend (entries, e);
    e->t = NULL;
    e->title = NULL;
    e->entry = NULL;
    e->url = NULL;
    e->comments = NULL;
  }

  else if (parsing_item && !strcmp (element_name, "title"))
    item_title = TRUE;
  else if (parsing_item && !strcmp (element_name, "link"))
    item_link = TRUE;
  else if (parsing_item && !strcmp (element_name, "description"))
    item_description = TRUE;
  else if (parsing_item && !strcmp (element_name, "comments"))
    item_comments = TRUE;
  else if (parsing_item && !strcmp (element_name, "pubDate"))
    item_pubdate = TRUE;
}

static void end_element_handler (GMarkupParseContext *context,
                                 const gchar *element_name,
                                 gpointer user_data, GError **error)
{
  //printf ("end:%s\n", element_name);

  if (!strcmp (element_name, "rss"))
    parsing_rss = FALSE;
  else if (!strcmp (element_name, "item")) 
    parsing_item = FALSE;
    
  else if (!strcmp (element_name, "title"))
    item_title = FALSE;
  else if (!strcmp (element_name, "link"))
    item_link = FALSE;
  else if (!strcmp (element_name, "description"))
    item_description = FALSE;
  else if (!strcmp (element_name, "comments"))
    item_comments = FALSE;
  else if (!strcmp (element_name, "pubDate"))
    item_pubdate = FALSE;
}

static void text_handler (GMarkupParseContext *context,
                          const gchar *text, gsize text_len,
                          gpointer user_data, GError **error)
{
  struct rss_entry *e;

  //printf ("text:%s\n", text);

  if (entries == NULL)
    return;

  e = (struct rss_entry *) entries->data;

  if (item_link) {
    if (e->url) {
      free (e->url);
    }
    e->url = strdup (text);
  }
    
  else if (item_description) {
    if (e->entry) {
      free (e->entry);
    }
    e->entry = gaim_unescape_html (text);

    // If there is a standard format for Xanga titles (there really isn't)
    // it will probably be devised from the actual content.  Will be placed
    // here if there is proven demand.
  }

  else if (item_comments) {
    if (e->comments) {
      free (e->comments);
    }
    e->comments = strdup (text);
  }

  else if (item_title) {
    if (e->title) {
      free (e->title);
    }
    e->title = strdup (text);
  }

  else if (item_pubdate) {
    if (e->t) {
      free (e->t);
    }
    e->t = parse_date_rfc822 (text);
  }
}

/* Final parser variable */
GMarkupParser rss_parser =
{
  start_element_handler,
  end_element_handler,
  text_handler,
  NULL,
  NULL
};

/* Callback for HTTP data fetcher */
static void url_callback (void *data, const char *text, size_t size)
{
  GMarkupParseContext *context;
  gchar *filtered_text;

  /* Make sure URL exists/connected to Internet */
  if (text == NULL) {
    auto_debug ("rss", "error, unable to fetch page via internet");
    return;
  }


  parsing_rss = FALSE;
  parsing_item = FALSE;

  item_title = FALSE;
  item_link = FALSE;
  item_description = FALSE;
  item_comments = FALSE;
  item_pubdate = FALSE;

  free_entries (entries);

  // Sanity checking
  filtered_text = gaim_utf8_salvage (text);

  gchar *convert = gaim_utf8_try_convert ("<");
  gchar *next = g_utf8_strchr (filtered_text, 10, g_utf8_get_char (convert));
  free (convert);

  if (next == NULL) {
    free (filtered_text);
    // TODO: error out
    return;
  }

  if (gaim_prefs_get_int (
    "/plugins/gtk/autoprofile/components/rss/type") == RSS_XANGA) {
    parse_xanga_rss (filtered_text);
    entries = g_list_reverse (entries);
    free (filtered_text);
    return;
  }


  GError *err = NULL;

  context = g_markup_parse_context_new (&rss_parser, 0, 
    NULL, NULL);

  if (!g_markup_parse_context_parse (context, next, size, &err)) {
    g_markup_parse_context_free (context);
    auto_debug ("rss", "error, unable to start parser");
    auto_debug ("rss", err->message); 
    free (filtered_text);
    return;
  }
  
  if (!g_markup_parse_context_end_parse (context, &err)) {
    g_markup_parse_context_free (context);
    auto_debug ("rss", "error, unable to end parser");
    free (filtered_text);
    return;
  }
  
  g_markup_parse_context_free (context);

  entries = g_list_reverse (entries);
  free (filtered_text);
}

void parse_rss ()
{
  char *url;

  url = get_url ();
  if (strcmp (url, "") != 0) {
    gaim_url_fetch (url, TRUE, NULL, FALSE, url_callback, NULL);
  }
  free (url);
}



Generated by  Doxygen 1.6.0   Back to index