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

identity-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
 */

#include <config.h>

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

#include <glib.h>

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

#include <pan/base/debug.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/identities/identity-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 * gstr, char * escapeme)
{
      char * pch = pan_str_escape (escapeme);
      g_string_append (gstr, pch);
      g_free (pch);
}


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

static void
write_identity (GString        * gstr, 
                const Identity * id,
                gint             depth)
{
      gint i;

      g_return_if_fail (gstr!=NULL);
      g_return_if_fail (id!=NULL);

      /* top level */
      newline_depth (gstr, depth);
      g_string_append (gstr, "<profile name=\"");
      pan_g_string_append_escaped (gstr, id->name);
      g_string_append (gstr, "\">");
      depth++;

      /* author name */
      if (is_nonempty_string(id->author_real))
      {
            newline_depth (gstr, depth);
            g_string_append (gstr, "<author_real>");
            pan_g_string_append_escaped (gstr, id->author_real);
            g_string_append (gstr, "</author_real>");
      }

      /* author address */
      if (is_nonempty_string(id->author_addr))
      {
            newline_depth (gstr, depth);
            g_string_append (gstr, "<author_addr>");
            pan_g_string_append_escaped (gstr, id->author_addr);
            g_string_append (gstr, "</author_addr>");
      }

      /* signature */
      if (is_nonempty_string(id->signature))
      {
            newline_depth (gstr, depth);
            g_string_append (gstr, "<signature>");
            pan_g_string_append_escaped (gstr, id->signature);
            g_string_append (gstr, "</signature>");
      }

      /* organization */
      if (is_nonempty_string(id->organization))
      {
            newline_depth (gstr, depth);
            g_string_append (gstr, "<organization>");
            pan_g_string_append_escaped (gstr, id->organization);
            g_string_append (gstr, "</organization>");
      }

      /* reply_to */
      if (is_nonempty_string(id->reply_to))
      {
            newline_depth (gstr, depth);
            g_string_append (gstr, "<reply_to>");
            pan_g_string_append_escaped (gstr, id->reply_to);
            g_string_append (gstr, "</reply_to>");
      }

      /* attribution */
      if (is_nonempty_string(id->attribution))
      {
            newline_depth (gstr, depth);
            g_string_append (gstr, "<attribution>");
            pan_g_string_append_escaped (gstr, id->attribution);
            g_string_append (gstr, "</attribution>");
      }

      /* msg_id fqdn */
      if (is_nonempty_string(id->msg_id_fqdn))
      {
            newline_depth (gstr, depth);
            g_string_append (gstr, "<msg_id_fqdn>");
            pan_g_string_append_escaped (gstr, id->msg_id_fqdn);
            g_string_append (gstr, "</msg_id_fqdn>");
      }

      /* posting charset */
      if (is_nonempty_string(id->posting_charset))
      {
            newline_depth (gstr, depth);
            g_string_append (gstr, "<posting_charset>");
            pan_g_string_append_escaped (gstr, id->posting_charset);
            g_string_append (gstr, "</posting_charset>");
      }

      /* custom headers */
      if (id->custom_headers->len > 0)
      {
            newline_depth (gstr, depth++);
            g_string_append (gstr, "<custom_headers>");

            for (i=0; i<id->custom_headers->len; i++)
            {
                  Header * header;

                  header = g_ptr_array_index (id->custom_headers, i);

                  newline_depth (gstr, depth+1);
                  g_string_append (gstr, "<custom_header name=\"");
                  pan_g_string_append_escaped (gstr, header->name);
                  g_string_append (gstr, "\">");
                  pan_g_string_append_escaped (gstr, header->value);
                  g_string_append (gstr, "</custom_header>");
            }

            newline_depth (gstr, --depth);
            g_string_append (gstr, "</custom_headers>");
      }
      
      /* trailer */
      newline_depth (gstr, --depth);
      g_string_append (gstr, "</profile>");
}

char *
identity_xml_to_string (const Identity    ** identities,
                        int                  identities_qty,
                        const char         * default_news_id,
                        const char         * default_mail_id)
{
      int      i;
      GString * str;
      GString * hdr;

      g_return_val_if_fail (identities_qty>=0, NULL);

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

      /* header */
      hdr = g_string_sized_new (4096);
      g_string_assign (hdr, 
              "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
              "<!DOCTYPE profiles SYSTEM \"profiles.dtd\">\n"
              "<profiles");
      if (is_nonempty_string (default_news_id))
      {
            g_string_append (hdr, " default_news=\"");
            pan_g_string_append_escaped (hdr, (char *) default_news_id);
            g_string_append (hdr, "\"");
      }
      if (is_nonempty_string (default_mail_id))
      {
            g_string_append (hdr, " default_mail=\"");
            pan_g_string_append_escaped (hdr, (char *) default_mail_id);
            g_string_append (hdr, "\"");
      }
      g_string_append (hdr, ">\n");
      g_string_prepend(str, hdr->str);

      /* trailer */
      g_string_append (str, "\n</profiles>");

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

static gboolean
identity_xml_fwrite (FILE               * fp,
                     const Identity    ** identities,
                     int                  identities_qty,
                     const char         * default_news_id,
                     const char         * default_mail_id)
{
        char  * pch;
      size_t   to_write, written;

        g_return_val_if_fail (fp!=NULL, 0);
        g_return_val_if_fail (identities!=NULL, 0);
        g_return_val_if_fail (identities_qty>0, 0);

        pch = identity_xml_to_string (identities, identities_qty,
            default_news_id, default_mail_id);

      to_write = strlen (pch);
        written = fwrite (pch, sizeof(char), to_write, fp);
        g_free (pch);

      return to_write == written;
}

void
identity_xml_write (const char         * filename,
                    const Identity    ** identities,
                    int                  identities_qty,
                    const char         * default_news_id,
                    const char         * default_mail_id) 
{
        /* sanity clause */
        g_return_if_fail (is_nonempty_string(filename));
        g_return_if_fail (identities_qty>=0);

        /* write the file */

        if (identities_qty == 0)
                unlink (filename);
        else {
            FILE * fp;
            char * filename_tmp = pan_file_make_temp (&fp);
            gboolean ok = fp != NULL;
            
                if (ok) {     
                  ok = identity_xml_fwrite (fp, identities, identities_qty, default_news_id, default_mail_id);
                        fclose (fp);
                }
            if (ok && pan_file_swap_datafile (filename_tmp, filename))
                        log_add_va (LOG_INFO, _("Wrote profiles to \"%s\""), filename);

            g_free (filename_tmp);
        }
}


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

static Identity *
create_identity (xmlDoc *doc, xmlNode *node)
{
      Identity     * id = NULL;
      const char   * tag = (const char*) node->name;
      xmlNode      * child;
      xmlChar      * val;

      if (pan_strcmp (tag, "profile") != 0)
            return NULL;


      /* init toplevel */
      id = identity_new ();

      if ((val = xmlGetProp (node, "name")) != NULL) {
            replace_gstr (&id->name, g_strdup (val));
            xmlFree (val);
      }

      /* walk through children */
      for (child=node->xmlChildrenNode; child!=NULL; child=child->next)
      {

            if (!pan_strcmp ((const char*)child->name, "custom_headers"))
            {
                  xmlNode * hdr;

                  /* walk through custom headers */
                  for (hdr=child->xmlChildrenNode; hdr!=NULL; hdr=hdr->next)
                  {
                        if (!pan_strcmp ((const char*)hdr->name, "custom_header"))
                        {
                              Header  * header = g_new0 (Header, 1);
                              xmlChar * str;

                              /* header name */
                              if ((str = xmlGetProp (hdr, "name")) != NULL) {
                                    replace_gstr (&header->name, g_strdup (str));
                                    xmlFree (str);
                              }

                              /* value */
                              if ((str = xmlNodeListGetString (doc, hdr->xmlChildrenNode, FALSE)) != NULL) {
                                    replace_gstr (&header->value, pan_str_unescape ((const char*) str));
                                    xmlFree (str);
                              }

                              g_ptr_array_add (id->custom_headers, header);
                        }
                  }
            }
            else
            {
                  const char * name = (const char*) child->name;
                  void          (*func) (Identity * id, const char *);

                  if (!pan_strcmp (name, "author_real"))
                        func = identity_set_author_real;
                  else
                  if (!pan_strcmp (name, "author_addr"))
                        func = identity_set_author_addr;
                  else
                  if (!pan_strcmp (name, "signature"))
                        func = identity_set_signature;
                  else
                  if (!pan_strcmp (name, "organization"))
                        func = identity_set_organization;
                  else
                  if (!pan_strcmp (name, "reply_to"))
                        func = identity_set_reply_to;
                  else
                  if (!pan_strcmp (name, "attribution"))
                        func = identity_set_attribution;
                  else
                  if (!pan_strcmp (name, "msg_id_fqdn"))
                        func = identity_set_msg_id_fqdn;
                  else
                  if (!pan_strcmp (name, "posting_charset"))
                        func = identity_set_posting_charset;
                  else
                        func = NULL;

                  if (func != NULL && child->xmlChildrenNode != NULL)
                  {
                        xmlChar * raw;
                        char   * contents;

                        /* retrieve contents */
                        raw = xmlNodeListGetString (doc, 
                              child->xmlChildrenNode, FALSE);
                        contents = pan_str_unescape ((const char*) raw);

                        /* copy the field */
                        (*func) (id, contents);

                        /* cleanup toplevel */
                        xmlFree (raw);
                        g_free (contents);
                  }

            }
      }
                  
      return id;
}

void
identity_xml_read (const char  * filename,
                   GPtrArray   * appendme_identities,
                   char       ** default_news_id,
                   char       ** default_mail_id)
{
      /* sanity clause */
      g_return_if_fail (is_nonempty_string (filename));
      g_return_if_fail (appendme_identities!=NULL);

      /* read the file */
      if (pan_file_exists (filename))
      {
            xmlDocPtr doc = xmlParseFile (filename);

            if (doc != NULL)
            {
                  xmlNodePtr cur = xmlDocGetRootElement (doc);

                  if (pan_strcmp((const char*) cur->name, "profiles"))
                        g_warning (_("%s does not appear to be a valid datafile"), filename);
                  else
                  {
                        xmlChar * val;

                        if ((val = xmlGetProp (cur, "default_news")) != NULL) {
                              replace_gstr (default_news_id, g_strdup (val));
                              xmlFree (val);
                        }
                        if ((val = xmlGetProp (cur, "default_mail")) != NULL) {
                              replace_gstr (default_mail_id, g_strdup (val));
                              xmlFree (val);
                        }

                        for (cur=cur->xmlChildrenNode; cur!=NULL; cur=cur->next) {
                              Identity * id = create_identity (doc, cur);
                              if (id != NULL)
                                    g_ptr_array_add (appendme_identities, id);
                        }
                  }

                  xmlFreeDoc (doc);
            }
      }
}

Generated by  Doxygen 1.6.0   Back to index