Logo Search packages:      
Sourcecode: pan version File versions  Download package

filter-xml.c

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * Pan - A Newsreader for Gtk+
 * Copyright (C) 2002  Charles Kerr <charles@rebelbase.com>
 *
 * 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; version 2 of the License.
 *
 * 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
 */

/*********************
**********************  Includes
*********************/

#include <config.h>

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <glib.h>

#include <libxml/parser.h>
#include <libxml/xmlmemory.h>

#include <pan/base/log.h>
#include <pan/base/pan-i18n.h>
#include <pan/base/pan-glib-extensions.h>
#include <pan/base/util-file.h>

#include <pan/filters/filter-aggregate.h> 
#include <pan/filters/filter-binary.h> 
#include <pan/filters/filter-bytes.h> 
#include <pan/filters/filter-cached.h> 
#include <pan/filters/filter-crosspost.h> 
#include <pan/filters/filter-date.h> 
#include <pan/filters/filter-mine.h> 
#include <pan/filters/filter-linecount.h> 
#include <pan/filters/filter-new.h> 
#include <pan/filters/filter-phrase.h> 
#include <pan/filters/filter-score.h> 
#include <pan/filters/filter-top.h> 
#include <pan/filters/filter.h> 
#include <pan/filters/filter-xml.h>

/************
*************  UTIL
************/

static void
newline_depth (GString * appendme, gint depth)
{
      gint i;
      g_string_append_c (appendme, '\n');
      for (i=0; i<depth; ++i)
            g_string_append_c (appendme, '\t');
}

static void
pan_g_string_append_escaped (GString * str, gchar * escapeme)
{
      gchar * pch = pan_str_escape (escapeme);
      g_string_append (str, pch);
      g_free (pch);
}

/*****
******  
******  
******    WRITING
******  
******  
*****/

static void
write_filter (GString * appendme, const Filter * f, gint depth);

static void
add_filter_arguments (GString * appendme, const Filter * f)
{
      g_return_if_fail (appendme!=NULL);
      g_return_if_fail (f!=NULL);

      /* negate */
      if (f->negate)
            g_string_append (appendme, " negate=\"t\"");
}
static void
add_aggregate_arguments (GString * appendme, const FilterAggregate * f)
{
      g_return_if_fail (appendme!=NULL);
      g_return_if_fail (f!=NULL);

      /* superclass */
      add_filter_arguments (appendme, FILTER(f));

      /* aggregate type */
      switch (f->type) {
            case AGGREGATE_TYPE_AND:
                  g_string_append (appendme, " type=\"and\"");
                  break;
            case AGGREGATE_TYPE_OR:
                  g_string_append (appendme, " type=\"or\"");
                  break;
            default:
                  pan_warn_if_reached ();
                  break;
      }
}
static void
add_aggregate_children (GString * appendme, const FilterAggregate * f, gint depth)
{
      g_return_if_fail (appendme!=NULL);
      g_return_if_fail (f!=NULL);

      if (f->children!=NULL && f->children->len!=0) {
            gint i;
            for (i=0; i<f->children->len; ++i) {
                  Filter * child = FILTER(g_ptr_array_index(f->children,i));
                  write_filter (appendme, child, depth+1);
            }
      }
}
static void
add_top_arguments (GString * appendme, const FilterTop * f)
{
      g_return_if_fail (appendme!=NULL);
      g_return_if_fail (f!=NULL);

      /* superclass */
      add_aggregate_arguments (appendme, FILTER_AGGREGATE(f));

      /* name */
      g_string_append (appendme, " name=\"");
      pan_g_string_append_escaped (appendme, f->name);
      g_string_append (appendme, "\"");

      /* in thread filter list */
      if (f->is_visible)
            g_string_append (appendme, " visible=\"t\"");
}
static void
add_score_arguments (GString * appendme, const FilterScore * f)
{
      add_filter_arguments (appendme, FILTER(f));

      g_string_append (appendme, " mode=\"");
      if (f->mode & SCORE_WATCHED)    g_string_append (appendme, "watched,");
      if (f->mode & SCORE_HIGH)       g_string_append (appendme, "high,");
      if (f->mode & SCORE_MEDIUM)     g_string_append (appendme, "medium,");
      if (f->mode & SCORE_ZERO)       g_string_append (appendme, "zero,");
      if (f->mode & SCORE_LOW)        g_string_append (appendme, "low,");
      if (f->mode & SCORE_IGNORED)    g_string_append (appendme, "ignored,");
      g_string_truncate (appendme, appendme->len-1);
      g_string_append_c (appendme, '"');
}
static void
add_crosspost_arguments (GString * appendme, const FilterCrosspost * f)
{
      add_filter_arguments (appendme, FILTER(f));
      g_string_append_printf (appendme, " min_groups=\"%d\"", f->minimum_crosspost_count);
}
static void
add_date_arguments (GString * appendme, const FilterDate * f)
{
      add_filter_arguments (appendme, FILTER(f));
      g_string_append_printf (appendme, " min_days_old=\"%d\"", f->minimum_days_old);
}
static void
add_mine_arguments (GString * appendme, const FilterMine * f)
{
      add_filter_arguments (appendme, FILTER(f));
}
static void
add_linecount_arguments (GString * appendme, const FilterLineCount * f)
{
      add_filter_arguments (appendme, FILTER(f));
      g_string_append_printf (appendme, " min_lines=\"%d\"", f->minimum_line_count);
}
static void
add_bytes_arguments (GString * appendme, const FilterBytes * f)
{
      add_filter_arguments (appendme, FILTER(f));
      g_string_append_printf (appendme, " minimum=\"%lu\"", f->minimum_bytes);
}
static void
add_new_arguments (GString * appendme, const FilterNew * f)
{
      add_filter_arguments (appendme, FILTER(f));

      switch (f->type) {
            case FILTER_NEW_NEW:
                  g_string_append (appendme, " type=\"new\"");
                  break;
            case FILTER_NEW_UNREAD:
                  g_string_append (appendme, " type=\"unread\"");
                  break;
            case FILTER_NEW_READ:
                  g_string_append (appendme, " type=\"read\"");
                  break;
      }
}
static void
add_phrase_arguments (GString * appendme, const FilterPhrase * f)
{
      const char * str;

      add_filter_arguments (appendme, FILTER(f));

      /* match type */
      str = "";
      switch (f->match_type) {
            case PHRASE_MATCH_CONTAINS:     str = "contains"; break;
            case PHRASE_MATCH_IS:           str = "is"; break;
            case PHRASE_MATCH_STARTS_WITH:  str = "starts_with"; break;
            case PHRASE_MATCH_ENDS_WITH:    str = "ends_with"; break;
            case PHRASE_MATCH_REGEX:        str = "regex"; break;
      }
      g_string_append_printf (appendme, " match_type=\"%s\"", str);

      /* key type */
      str = "";
      switch (f->key_type) {
            case PHRASE_KEY_SUBJECT:      str = "subject"; break;
            case PHRASE_KEY_AUTHOR:       str = "author"; break;
            case PHRASE_KEY_MESSAGE_ID:   str = "message-id"; break;
            case PHRASE_KEY_REFERENCES:   str = "references"; break;
            case PHRASE_KEY_XREF:         str = "xref"; break;
      }
      g_string_append_printf (appendme, " key_type=\"%s\"", str);
      g_string_append_printf (appendme, " case_sensitive=\"%c\"", f->case_sensitive ? 't' : 'f');

      /* key */
      g_string_append (appendme, " key=\"");
      pan_g_string_append_escaped (appendme, f->public_key);
      g_string_append (appendme, "\"");
}
static void
add_binary_arguments (GString * appendme, const FilterBinary * f)
{
      g_return_if_fail (appendme!=NULL);
      g_return_if_fail (f!=NULL);

      /* superclass */
      add_filter_arguments (appendme, FILTER(f));

      /* binary */
      g_string_append (appendme, " state=\"");
      switch (f->state) {
            case FILTER_BINARY_NONBINARY:
                  g_string_append (appendme, "text");
                  break;
            case FILTER_BINARY_INCOMPLETE:
                  g_string_append (appendme, "incomplete");
                  break;
            case FILTER_BINARY_COMPLETE:
                  g_string_append (appendme, "complete");
                  break;
      }
      g_string_append_c (appendme, '"');
}

/**
***
**/

static void
write_binary (GString * appendme, const FilterBinary * f, gint depth)
{
      newline_depth (appendme, depth);
      g_string_append (appendme, "<binary");
      add_binary_arguments (appendme, f);
      g_string_append (appendme, "/>");
}
static void
write_cached (GString * appendme, const FilterCached * f, gint depth)
{
      newline_depth (appendme, depth);
      g_string_append (appendme, "<cached");
      add_filter_arguments (appendme, FILTER(f));
      g_string_append (appendme, "/>");
}
static void
write_score (GString * appendme, const FilterScore * f, gint depth)
{
      newline_depth (appendme, depth);
      g_string_append (appendme, "<score");
      add_score_arguments (appendme, f);
      g_string_append (appendme, "/>");
}
static void
write_crosspost (GString * appendme, const FilterCrosspost * f, gint depth)
{
      newline_depth (appendme, depth);
      g_string_append (appendme, "<crosspost");
      add_crosspost_arguments (appendme, f);
      g_string_append (appendme, "/>");
}
static void
write_date (GString * appendme, const FilterDate * f, gint depth)
{
      newline_depth (appendme, depth);
      g_string_append (appendme, "<date");
      add_date_arguments (appendme, f);
      g_string_append (appendme, "/>");
}
static void
write_mine (GString * appendme, const FilterMine * f, gint depth)
{
      newline_depth (appendme, depth);
      g_string_append (appendme, "<mine");
      add_mine_arguments (appendme, f);
      g_string_append (appendme, "/>");
}
static void
write_linecount (GString * appendme, const FilterLineCount * f, gint depth)
{
      newline_depth (appendme, depth);
      g_string_append (appendme, "<linecount");
      add_linecount_arguments (appendme, f);
      g_string_append (appendme, "/>");
}
static void
write_bytes (GString * appendme, const FilterBytes * f, int depth)
{
      newline_depth (appendme, depth);
      g_string_append (appendme, "<bytes");
      add_bytes_arguments (appendme, f);
      g_string_append (appendme, "/>");
}
static void
write_new (GString * appendme, const FilterNew * f, gint depth)
{
      newline_depth (appendme, depth);
      g_string_append (appendme, "<new");
      add_new_arguments (appendme, f);
      g_string_append (appendme, "/>");
}
static void
write_phrase (GString * appendme, const FilterPhrase * f, gint depth)
{
      newline_depth (appendme, depth);
      g_string_append (appendme, "<phrase");
      add_phrase_arguments (appendme, f);
      g_string_append (appendme, "/>");
}
static void
write_top (GString * appendme, const FilterTop * f, gint depth)
{
      newline_depth (appendme, depth);
      g_string_append (appendme, "<filter");
      add_top_arguments (appendme, f);
      g_string_append (appendme, ">");
      add_aggregate_children (appendme, FILTER_AGGREGATE(f), depth);
      newline_depth (appendme, depth);
      g_string_append (appendme, "</filter>");
}
static void
write_aggregate (GString * appendme, const FilterAggregate * f, gint depth)
{
      newline_depth (appendme, depth);
      g_string_append (appendme, "<aggregate");
      add_aggregate_arguments (appendme, f);
      g_string_append (appendme, ">");
      add_aggregate_children (appendme, f, depth);
      newline_depth (appendme, depth);
      g_string_append (appendme, "</aggregate>");
}



static void
write_filter (GString * appendme, const Filter * f, gint depth)
{
      g_return_if_fail (appendme!=NULL);
      g_return_if_fail (f!=NULL);

      if (!strcmp (f->class_id, FILTER_TOP_CLASS_ID))
            write_top (appendme, FILTER_TOP(f), depth);

      else if (!strcmp (f->class_id, FILTER_AGGREGATE_CLASS_ID))
            write_aggregate (appendme, FILTER_AGGREGATE(f), depth);

      else if (!strcmp (f->class_id, FILTER_BINARY_CLASS_ID))
            write_binary (appendme, FILTER_BINARY(f), depth);

      else if (!strcmp (f->class_id, FILTER_CACHED_CLASS_ID))
            write_cached (appendme, FILTER_CACHED(f), depth);

      else if (!strcmp (f->class_id, FILTER_CROSSPOST_CLASS_ID))
            write_crosspost (appendme, FILTER_CROSSPOST(f), depth);

      else if (!strcmp (f->class_id, FILTER_SCORE_CLASS_ID))
            write_score (appendme, FILTER_SCORE(f), depth);

      else if (!strcmp (f->class_id, FILTER_DATE_CLASS_ID))
            write_date (appendme, FILTER_DATE(f), depth);

      else if (!strcmp (f->class_id, FILTER_MINE_CLASS_ID))
            write_mine (appendme, FILTER_MINE(f), depth);

      else if (!strcmp (f->class_id, FILTER_LINE_COUNT_CLASS_ID))
            write_linecount (appendme, FILTER_LINE_COUNT(f), depth);

      else if (!strcmp (f->class_id, FILTER_BYTES_CLASS_ID))
            write_bytes (appendme, FILTER_BYTES(f), depth);

      else if (!strcmp (f->class_id, FILTER_NEW_CLASS_ID))
            write_new (appendme, FILTER_NEW(f), depth);

      else if (!strcmp (f->class_id, FILTER_PHRASE_CLASS_ID))
            write_phrase (appendme, FILTER_PHRASE(f), depth);

      else pan_warn_if_reached ();
}


char*
filter_xml_to_string  (const Filter  ** filters,
                       int              filter_qty)
{
      int i;
      GString * str;

      g_return_val_if_fail (filters!=NULL, NULL);
      g_return_val_if_fail (filter_qty>0, NULL);

      /* write the filters to a buf */
      str = g_string_sized_new (4096);
      for (i=0; i<filter_qty; ++i) {
            write_filter (str, filters[i], 1);
            if (i!=filter_qty)
                  g_string_append (str, "\n\n");
      }

      g_string_prepend (str, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
                             "<!DOCTYPE rules SYSTEM \"filters.dtd\">\n"
                             "<filters>\n");
      g_string_append (str, "\n</filters>");

      /* return the string */
      return g_string_free (str, FALSE);
}

static gboolean
filter_xml_fwrite (FILE              * fp,
                   const FilterTop  ** filters,
                   int                 filter_qty)
{
      gchar  * pch;
      size_t   to_write, written;

      g_return_val_if_fail (fp!=NULL, 0);
      g_return_val_if_fail (filters!=NULL, 0);
      g_return_val_if_fail (filter_qty>0, 0);

      pch = filter_xml_to_string ((const Filter**)filters, filter_qty);
      to_write = strlen (pch);
      written = fwrite (pch, sizeof(char), to_write, fp);
      g_free (pch);

      return to_write == written;
}

void
filter_xml_write (const char         * filename,
                  const FilterTop   ** filters,
                  int                  filter_qty)
{
      /* sanity clause */
      g_return_if_fail (is_nonempty_string(filename));
      g_return_if_fail (filter_qty>=0);

      /* write the file */
      if (filter_qty == 0)
            unlink (filename);
      else {
            FILE * fp;
            char * filename_tmp = pan_file_make_temp (&fp);
            gboolean   ok = fp ? TRUE : FALSE;

            if (ok) {
                  ok = filter_xml_fwrite (fp, filters, filter_qty);
                  fclose (fp);
            }
            if (ok && pan_file_swap_datafile (filename_tmp, filename))
                  log_add_va (LOG_INFO, _("Wrote filters to \"%s\""), filename);

            g_free (filename_tmp);
      }
}

/***
****  
****    READING
****  
***/

static void
populate_filter (Filter * f, xmlNodePtr node)
{
      xmlChar * val;

      if ((val = xmlGetProp (node, "negate")) != NULL) {
            filter_negate (f);
            xmlFree (val);
      }
}

static void
populate_score (FilterScore * f, xmlNodePtr node)
{
      xmlChar * val;

      populate_filter (FILTER(f), node);

      if ((val = xmlGetProp (node, "mode")) != NULL)
      {
            FilterScoreMode mode = 0;

                if (strstr (val, "watched") != NULL)  mode |= SCORE_WATCHED;
                if (strstr (val, "high") != NULL)     mode |= SCORE_HIGH;
                if (strstr (val, "medium") != NULL)   mode |= SCORE_MEDIUM;
                if (strstr (val, "zero") != NULL)     mode |= SCORE_ZERO;
                if (strstr (val, "low") != NULL)      mode |= SCORE_LOW;
                if (strstr (val, "ignored") != NULL)  mode |= SCORE_IGNORED;

            filter_score_set_mode (f, mode);

            xmlFree (val);
      }
}

static void
populate_binary (FilterBinary * f, xmlNodePtr node)
{
      xmlChar * val;
      FilterBinaryState state = FILTER_BINARY_NONBINARY;

      populate_filter (FILTER(f), node);

      if ((val = xmlGetProp (node, "state")) != NULL)
      {
            if (!pan_strcmp(val,"text")) state = FILTER_BINARY_NONBINARY;
            else if (!pan_strcmp(val,"complete")) state = FILTER_BINARY_COMPLETE;
            else if (!pan_strcmp(val,"incomplete")) state = FILTER_BINARY_INCOMPLETE;

            xmlFree (val);
      }

      filter_binary_set_state (f, state);
}

static void
populate_cached (FilterCached * f, xmlNodePtr node)
{
      populate_filter (FILTER(f), node);
}

static void
populate_new (FilterNew * f, xmlNodePtr node)
{
      xmlChar * val;
      FilterNewType state = FILTER_NEW_NEW;

      populate_filter (FILTER(f), node);

      if ((val = xmlGetProp (node, "type")) != NULL)
      {
            if (!pan_strcmp(val,"new")) state = FILTER_NEW_NEW;
            else if (!pan_strcmp(val,"unread")) state = FILTER_NEW_UNREAD;
            else if (!pan_strcmp(val,"read")) state = FILTER_NEW_READ;

            xmlFree (val);
      }

      filter_new_set_state (f, state);
}

static void
populate_linecount (FilterLineCount * f, xmlNodePtr node)
{
      xmlChar * val;

      populate_filter (FILTER(f), node);

      if ((val = xmlGetProp (node, "min_lines")) != NULL) {
            f->minimum_line_count = atoi (val);
            xmlFree (val);
      }
}

static void
populate_bytes (FilterBytes * f, xmlNodePtr node)
{
      xmlChar * val;

      populate_filter (FILTER(f), node);

      if ((val = xmlGetProp (node, "minimum")) != NULL) {
            f->minimum_bytes = strtoul (val, NULL, 10);
            xmlFree (val);
      }
}

static void
populate_crosspost (FilterCrosspost * f, xmlNodePtr node)
{
      xmlChar * val;

      populate_filter (FILTER(f), node);

      if ((val = xmlGetProp (node, "min_groups")) != NULL) {
            f->minimum_crosspost_count = atoi (val);
            xmlFree (val);
      }
}

static void
populate_date (FilterDate * f, xmlNodePtr node)
{
      xmlChar * val;

      populate_filter (FILTER(f), node);

      if ((val = xmlGetProp (node, "min_days_old")) != NULL) {
            f->minimum_days_old = atoi (val);
            xmlFree (val);
      }
}
static void
populate_mine (FilterMine * f, xmlNodePtr node)
{
      populate_filter (FILTER(f), node);
}

static void
populate_phrase (FilterPhrase * f, xmlNodePtr node)
{
      xmlChar * val;
      gboolean case_sensitive = FALSE;
      gboolean pre_0_13_3_91 = FALSE;
      char * key = NULL;
      PhraseKeyType key_type = PHRASE_KEY_SUBJECT;
      PhraseMatchType match_type = PHRASE_MATCH_CONTAINS;

      populate_filter (FILTER(f), node);

      /* match type */
      val = xmlGetProp (node, "match_type");
      if (val != NULL) {
                 if (!pan_strcmp (val, "contains"))    match_type = PHRASE_MATCH_CONTAINS;
            else if (!pan_strcmp (val, "is"))          match_type = PHRASE_MATCH_IS;
            else if (!pan_strcmp (val, "starts_with")) match_type = PHRASE_MATCH_STARTS_WITH;
            else if (!pan_strcmp (val, "ends_with"))   match_type = PHRASE_MATCH_ENDS_WITH;
            else if (!pan_strcmp (val, "regex"))       match_type = PHRASE_MATCH_REGEX;
            g_free (val);
      }

      /* key type */
      val = xmlGetProp (node, "key_type");
      if (val == NULL)
            val = xmlGetProp (node, "type");
      if (val != NULL) {
                 if (!pan_strcmp (val, "subject"))    key_type = PHRASE_KEY_SUBJECT;
            else if (!pan_strcmp (val, "author"))     key_type = PHRASE_KEY_AUTHOR;
            else if (!pan_strcmp (val, "message-id")) key_type = PHRASE_KEY_MESSAGE_ID;
            else if (!pan_strcmp (val, "references")) key_type = PHRASE_KEY_REFERENCES;
            else if (!pan_strcmp (val, "xref"))       key_type = PHRASE_KEY_XREF;
            else log_add_va (LOG_ERROR, "Invalid filter phrase key type: \"%s\"", val);

            xmlFree (val);
      }

      /* key */
      val = xmlGetProp (node, "key");
      if (val == NULL) {
            pre_0_13_3_91 = TRUE;
            val = xmlGetProp (node, "phrase"); /* pre=0.13.4 */
      }
      if (val != NULL) {
            key = g_strdup (val);
            xmlFree (val);
      }

      /* backwards compatability to 0.13.3.90 and earlier:
       * (1) it wrapped phrases with splats for some brain-damaged reason
       * (2) regular expressions were denoted with their own flag.
       */
      if (pre_0_13_3_91)
      {
            /* remove the splats */
            GString * str = g_string_new (key);
            if (str->len && str->str[0]=='*') g_string_erase (str, 0, 1);
            if (str->len && str->str[str->len-1]=='*') g_string_erase (str, str->len-1, 1);
            replace_gstr (&key, g_string_free (str, FALSE));

            /* check for regex flag */
            if ((val = xmlGetProp (node, "is_regex")) != NULL) {
                  if (*val == 't')
                        match_type = PHRASE_MATCH_REGEX;
                  xmlFree (val);
            }
      }
      else
      {
            /* check for case-sensitive */
            if ((val = xmlGetProp (node, "case_sensitive")) != NULL) {
                  case_sensitive = *val == 't';
                  xmlFree (val);
            }
      }

      filter_phrase_set (f, match_type, key_type, key, case_sensitive);
      g_free (key);
}

static void
populate_aggregate (FilterAggregate * f, xmlNodePtr node)
{
      xmlChar * val;

      populate_filter (FILTER(f), node);

      /* type */
      if ((val = xmlGetProp (node, "type")) != NULL) {
            if (!pan_strcmp(val,"and")) filter_aggregate_set_type (f, AGGREGATE_TYPE_AND);
            else if (!pan_strcmp(val,"or")) filter_aggregate_set_type (f, AGGREGATE_TYPE_OR);
            xmlFree (val);
      }
}

static void
populate_top (FilterTop * f, xmlNodePtr node)
{
      xmlChar * val;

      populate_aggregate (FILTER_AGGREGATE(f), node);

      /* name */
      if ((val = xmlGetProp (node, "name")) != NULL) {
            filter_top_set_name (f, val);
            xmlFree (val);
      }

      /* visible */
      val = xmlGetProp (node, "visible");
      filter_top_set_visible (f, val!=NULL && *val=='t');
      if (val != NULL)
            xmlFree (val);
}

static Filter*
create_filter (xmlDoc * doc, xmlNodePtr node)
{
      Filter * f = NULL;
      const gchar * tag = (const gchar*) node->name;

      if (!pan_strcmp(tag,"aggregate"))
      {
            f = filter_aggregate_new ();
            populate_aggregate (FILTER_AGGREGATE(f), node);
      }
      else if (!pan_strcmp(tag,"filter"))
      {
            f = filter_top_new ();
            populate_top (FILTER_TOP(f), node);
      }
      else if (!pan_strcmp(tag,"phrase"))
      {
            f = filter_phrase_new ();
            populate_phrase (FILTER_PHRASE(f), node);
      }
      else if (!pan_strcmp(tag,"linecount"))
      {
            f = filter_line_count_new ();
            populate_linecount (FILTER_LINE_COUNT(f), node);
      }
      else if (!pan_strcmp(tag,"bytes"))
      {
            f = filter_bytes_new ();
            populate_bytes (FILTER_BYTES(f), node);
      }
      else if (!pan_strcmp(tag,"crosspost"))
      {
            f = filter_crosspost_new ();
            populate_crosspost (FILTER_CROSSPOST(f), node);
      }
      else if (!pan_strcmp(tag,"date"))
      {
            f = filter_date_new ();
            populate_date (FILTER_DATE(f), node);
      }
      else if (!pan_strcmp(tag,"mine"))
      {
            f = filter_mine_new ();
            populate_mine (FILTER_MINE(f), node);
      }
      else if (!pan_strcmp(tag,"read"))
      {
            f = filter_new_article_new (FILTER_NEW_READ);
            populate_new (FILTER_NEW(f), node);
      }
      else if (!pan_strcmp(tag,"binary"))
      {
            f = filter_binary_new ();
            populate_binary (FILTER_BINARY(f), node);
      }
      else if (!pan_strcmp(tag,"score"))
      {
            f = filter_score_new (0);
            populate_score (FILTER_SCORE(f), node);
      }
      else if (!pan_strcmp(tag,"cached"))
      {
            f = filter_cached_new ();
            populate_cached (FILTER_CACHED(f), node);
      }
      else if (!pan_strcmp(tag,"new"))
      {
            f = filter_new_article_new (FILTER_NEW_NEW);
            populate_new (FILTER_NEW(f), node);
      }

      /* Children */
      if (!pan_strcmp(tag,"aggregate") || !pan_strcmp(tag,"filter"))
      {
            xmlNode * n;
            GPtrArray * a = g_ptr_array_new ();

            for (n=node->xmlChildrenNode; n!=NULL; n=n->next) {
                  Filter * child = create_filter (doc, n);
                  if (child != NULL)
                        g_ptr_array_add (a, child);
            }

            if (a->len != 0)
                  filter_aggregate_add (FILTER_AGGREGATE(f), (Filter**)a->pdata, a->len);

            pan_g_ptr_array_foreach (a, (GFunc)pan_object_unref, NULL);
            g_ptr_array_free (a, TRUE);
      }

      return f;
}

 
void
filter_xml_read (const gchar * filename,
               GPtrArray   * appendme_tops)
{
      /* sanity clause */
      g_return_if_fail (is_nonempty_string(filename));
      g_return_if_fail (appendme_tops!=NULL);

      /* read the file */
      if (pan_file_exists (filename))
      {
            xmlDocPtr doc = xmlParseFile (filename);
            if (doc != NULL)
            {
                  xmlNodePtr cur = xmlDocGetRootElement(doc);
                  cur = cur->xmlChildrenNode;

                  for (; cur!=NULL; cur=cur->next)
                  {
                        Filter * f = create_filter (doc, cur);
                        if (f != NULL)
                              g_ptr_array_add (appendme_tops, f);
                  }

                  xmlFreeDoc (doc);
            }
      }
}


#if 0
<?xml version="1.0"?>
<EXAMPLE prop1="gnome is great" prop2="&amp; linux too">
      <head>
            <title>Welcome to Gnome</title>
      </head>
      <chapter>
            <title>The Linux adventure</title>
            <p>bla bla bla ...</p>
            <image href="linus.gif"/>
            <p>...</p>
      </chapter>
</EXAMPLE>
#endif


Generated by  Doxygen 1.6.0   Back to index