/* 
   MultiSync Opie Plugin - Synchronize Opie/Zaurus Devices
   Copyright (C) 2003 Tom Foottit <tom@foottit.com>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 2 as
   published by the Free Software Foundation;

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
   SOFTWARE IS DISCLAIMED.
*/

/*
 *  $Id: opie_config.c,v 1.4 2004/02/09 18:53:31 lincoln Exp $
 */

#include "opie_config.h"
#include <multisync.h>
#include <string.h>

#include <expat.h>

#define PARSE_BUF_SIZE (512)
#define OPIE_CONFIG_FILE "opie_config.xml"

/* start and end expat callbacks for config info */
void config_start_hndl(void *data, const char *el, const char **attr); 
void config_end_hndl(void *data, const char *el); 


/*
 * opie_load_config
 */
gboolean opie_load_config(opie_conn* conn)
{
  char* filename;  
  XML_Parser p = XML_ParserCreate(NULL);
  int done, len;
  char buf[PARSE_BUF_SIZE];
  FILE* fd;
  gboolean rc = TRUE;
  
  if(!p)
    return FALSE;

  filename = g_strdup_printf("%s/%s", 
                             sync_get_datapath(conn->sync_pair),
                             OPIE_CONFIG_FILE);
  
  /* open the XML file */
  fd = fopen(filename, "r");
  if(!fd)
  {
    /* no existing config file - load defaults */
    conn->device_addr = g_strdup("192.168.0.1");
    conn->device_type = DEVICE_OPIE_OPENZAURUS;
    conn->device_port = 4242;
    conn->username = g_strdup("root");    
    conn->password = g_strdup("rootme");
    conn->conn_type = FTP_CONN;
    conn->enable_qcop = TRUE;
    
    rc = TRUE;
  }
  else
  {  
    /* pass the opie_conn into each handler */
    XML_SetUserData(p, (void *) conn);
    XML_SetElementHandler(p, config_start_hndl, config_end_hndl);

    /* parse the XML */    
    while(1)
    {
      fgets(buf, sizeof(buf), fd);
      len = strlen(buf);

      if(ferror(fd))
      {
        /* i/o error */
        rc = FALSE;
        break;
      }

      done = feof(fd);
      if(!XML_Parse(p, buf, len, done))
      {
        /* parse error */
#if 0
        printf("opie_load_config: Parse error at line %d:\n%s\n",
	    XML_GetCurrentLineNumber(p),
	    XML_ErrorString(XML_GetErrorCode(p)));
#endif
        rc = FALSE;
        break;
      }

      if(done)
        break;  
    }

    fclose(fd);
  }
  
  g_free(filename);
  
  return rc;
}


/*
 * opie_save_config
 */
gboolean opie_save_config(opie_conn* conn)
{
  GString *xmlstr;
  char* filename;
  gboolean rc = TRUE;
  FILE* fd;
  
  filename = g_strdup_printf("%s/%s", 
                             sync_get_datapath(conn->sync_pair),
                             OPIE_CONFIG_FILE);
  
  /* prepare XML string */
  xmlstr = g_string_new("<?xml version=\"1.0\"?>\n<Config>\n  <Options");
  if(conn->device_addr)
  {
    g_string_sprintfa(xmlstr, " Ip=\"%s\"", conn->device_addr);
  }
  if(conn->username)
  {
    g_string_sprintfa(xmlstr, " Username=\"%s\"", conn->username);
  }  
  if(conn->password)
  {
    g_string_sprintfa(xmlstr, " Password=\"%s\"", conn->password);
  }
  
  g_string_sprintfa(xmlstr, " Port=\"%u\"", conn->device_port);
  
  switch(conn->conn_type)
  {
    case FTP_CONN:
      g_string_append(xmlstr, " Protocol=\"FTP\"");
      break;
    case SCP_CONN:
      g_string_append(xmlstr, " Protocol=\"SFTP\"");
      break;
    default:
      break;  
  }
  
  g_string_sprintfa(xmlstr, " Device=\"%d\"", conn->device_type);
  
  if(conn->enable_qcop)
  {
    g_string_sprintfa(xmlstr, " QCop=\"1\"");    
  }
  else
  {
    g_string_sprintfa(xmlstr, " QCop=\"0\"");    
  }
  
  g_string_append(xmlstr, "/>\n</Config>");
  
  fd = fopen(filename, "w");
  if(fd)
  {
    fprintf(fd, "%s", xmlstr->str);
    fclose(fd);
  }
  else
  {
    /* failed to open config */
    rc = FALSE;
  }
  
  g_string_free(xmlstr, FALSE);
  g_free(filename);
  return rc;
}


/*
 * config_start_hndl
 */
void config_start_hndl(void *data, const char *el, const char **attr) 
{
  /* data is an opie_conn */
  opie_conn* conn = (opie_conn*)data;
  int i;
  
  if(!strcasecmp(el, "Options"))
  {
    /* populate the opie_conn with the attributes from the connection element */
    for (i = 0; attr[i]; i += 2)
    {
      /* key on the attribute name */
      if(!strcasecmp(attr[i], "Ip"))
      {
        conn->device_addr = g_strdup(attr[i+1]);
      }
      else if(!strcasecmp(attr[i], "Username"))
      {
        conn->username = g_strdup(attr[i+1]);
      }
      else if(!strcasecmp(attr[i], "Password"))
      {
        conn->password = g_strdup(attr[i+1]);
      }
      else if(!strcasecmp(attr[i], "Protocol"))
      {
        /* switched to SFTP, but still support SCP in config files for now */
        if((!strcasecmp(attr[i+1], "SCP")) || (!strcasecmp(attr[i+1], "SFTP")))
        {
          conn->conn_type = SCP_CONN;
        }
        else
        {
          conn->conn_type = FTP_CONN;
        }
      }
      else if(!strcasecmp(attr[i], "Port"))
      {
        conn->device_port = atoi(attr[i+1]);
      }
      else if(!strcasecmp(attr[i], "Device"))
      {
        conn->device_type = (opie_device_type)atoi(attr[i+1]);
      }
      else if(!strcasecmp(attr[i], "QCop"))
      {
        if(!strcasecmp(attr[i+1], "0"))
        {
          conn->enable_qcop = FALSE;   
        }
        else
        {
          conn->enable_qcop = TRUE; 
        }
      }
     } /* for each attribute */
  }
}


/*
 * config_end_hndl
 */
void config_end_hndl(void *data, const char *el) 
{
  /* nothing to do */
}
