[Evolution-hackers] utility to duplicate incoming and outgoing filters in filters.xml



Howdy all,

I'm not a member of these list but I search the archives on occasion.

Something I could never find was an easy way to duplicate my incoming
filters in Evolution 1.2.2 as outgoing ones.  And I didn't want to
duplicate the effort for my 50+ filters manually. As such, I wrote 
a quick hack today. I'm much happier (my Sent box just emptied out).

I've attached the source below. It is my first attempt at
using libxml, so it may not be error/fool-proof but it
seems to work here.

Please pardon the line wrap as I haven't figured out how to 
make 1.2.2 turn it off. :)

jack 
j-perdue tamu edu

Bcc: developer's and user's list since it might be useful to both


/*
**    dupefilters.c - Duplicate incoming/outgoing filters for Ximian's
Evolution
**
**    This utility will duplicate the incoming filters defined in
filters.xml
**    as outgoing filters and vice versa.  Written for Ximian Evolution
v.1.2.2
**    (stock Redhat 9 version) since I was sick of making filters twice.
**
**    Copyright(C) 2004 - Jack Perdue (a.k.a. Silicon Slick)
**
**    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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

#define GNOMENAMING
#ifndef GNOMENAMING
#include <libxml/xmlmemory.h>	/* untested */
#include <libxml/parser.h>
#else
#include <gnome-xml/xmlmemory.h>
#include <gnome-xml/parser.h>
#endif

#define MAXRULES 10000	/* for debugging - avoid infinite loops */

xmlNodePtr findRule(const xmlDocPtr doc, const xmlNodePtr firstrule,
		    const xmlChar * title, const xmlChar * direction)
{
  xmlNodePtr rule, node, found = NULL;
  xmlChar *key, *source;

  rule = firstrule;
  while (rule != NULL && found == NULL) {
    source = xmlGetProp(rule, "source");
    if (source && !xmlStrcmp(source, direction)) {
      node = rule->xmlChildrenNode;
      while (node != NULL) {
	if ((!xmlStrcmp(node->name, (const xmlChar *) "title"))) {
	  key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
	  if (!xmlStrcmp(key, title)) {
	    found = rule;
	    xmlFree(key);
	    break;
	  } else {
	    xmlFree(key);
	  }
	}
	node = node->next;
      }
    }
    xmlFree(source);
    rule = rule->next;
  }
  return found;
}	/* findRule() */

void duplicateRule(const xmlDocPtr doc, const xmlNodePtr firstrule,
		   const xmlNodePtr rule)
{

  xmlChar *source, *title, *newsource;
  xmlNodePtr cur, rulematch, newrule;

#ifdef DEBUG
  fprintf(stderr, "\nfound rule\n");
  xmlElemDump(stderr, doc, rule);
  fprintf(stderr, "\n\n");
#endif

  source = xmlGetProp(rule, "source");
  if (!xmlStrcmp(source, "incoming")
      || !xmlStrcmp(source, "outgoing")) {

    /* find title */
    cur = rule->xmlChildrenNode;
    while (cur != NULL) {
      if ((!xmlStrcmp(cur->name, (const xmlChar *) "title"))) {
	title = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
	break;
      }
      cur = cur->next;
    }
    if (!title) {
      fprintf(stderr, "Could not find rule title\n");
      xmlElemDump(stderr, doc, rule);
      exit(1);
    }

    /* set newsource to complementing rule */
    if (!xmlStrcmp(source, "outgoing")) {
      newsource = "incoming";
    } else if (!xmlStrcmp(source, "incoming")) {
      newsource = "outgoing";
    } else {
      fprintf(stderr, "Unknown source %s\n", source);
      exit(1);
    }

    /* add complementing rule if it doesn't already exist */
    rulematch = findRule(doc, firstrule, title, newsource);
    xmlFree(title);
    if (!rulematch) {
      newrule = xmlCopyNode(rule, 1);
      xmlSetProp(newrule, "source", newsource);
#ifdef DEBUG
      fprintf(stderr, "\nAdding new rule...\n");
      xmlElemDump(stderr, doc, newrule);
      fprintf(stderr, "\n\n");
#endif
      xmlAddPrevSibling(rule, newrule);	/* add new rule just before this
one (to avoid processing again) */
    }
  } else {
    fprintf(stderr, "Unknown source %s\n", source);
    exit(1);
  }
  xmlFree(source);
  return;
}	/* duplicateRule() */

void duplicateRules(const char *docname)
{

  xmlDocPtr doc;
  xmlNodePtr root, ruleset, firstrule, rule;
  int rulectr = 0;

  doc = xmlParseFile(docname);
  if (doc == NULL) {
    fprintf(stderr, "Document %s not parsed successfully.\n",
	    docname);
    exit(1);
  }

  root = xmlDocGetRootElement(doc);
  if (root == NULL) {
    fprintf(stderr, "empty document\n");
    xmlFreeDoc(doc);
    exit(1);
  }

  /* assume root is "filteroptions" */
  if (xmlStrcmp(root->name, (const xmlChar *) "filteroptions")) {
    fprintf(stderr,
	    "document of the wrong type, root node %s != %s\n",
	    root->name, "filteroptions");
    xmlFreeDoc(doc);
    exit(1);
  }

  /* assume there is one and only one "ruleset" that is a child of
"filteroptions" */
  ruleset = root->xmlChildrenNode;
  if (xmlStrcmp(ruleset->name, (const xmlChar *) "ruleset")) {
    fprintf(stderr,
	    "document of the wrong type, root child node %s != %s\n",
	    ruleset->name, "ruleset");
    xmlFreeDoc(doc);
    exit(1);
  }

  /* assume all the children of "ruleset" are "rule"s */
  firstrule = rule = ruleset->xmlChildrenNode;
  while (rule != NULL) {
    assert(++rulectr < 10000);	/* prevent infinite loops */
    if ((!xmlStrcmp(rule->name, (const xmlChar *) "rule"))) {
      duplicateRule(doc, firstrule, rule);
    } else {
      printf("ERROR - EXPECTED RULE - %s\n", rule->name);
    }
    rule = rule->next;
  }
  xmlDocDump(stdout, doc);	/* write new filters to standard out */
  xmlFreeDoc(doc);
  return;
}	/* duplicateRules() */

int main(int argc, char **argv)
{
  char *docname;
  if (argc <= 1) {
    printf("\n\tUsage: %s <path to Evolution's filters.xml>\n",
	   argv[0]);
    printf("\n\t\t e.g. %s docname ~/evolution/filters.xml\n\n",
	   argv[0]);
    return (0);
  }
  docname = argv[1];
  duplicateRules(docname);	/* duplicate incoming rules as outgoing and
vice versa */
  exit(0);
}	/* main() */

/* EOF */





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]