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

serverlist.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 <string.h>

#include <glib.h>

#include <pan/base/base-prefs.h>
#include <pan/base/debug.h>
#include <pan/base/log.h>
#include <pan/base/newsrc-port.h>
#include <pan/base/pan-config.h>
#include <pan/base/pan-i18n.h>
#include <pan/base/pan-glib-extensions.h>
#include <pan/base/server.h>
#include <pan/base/serverlist.h>
#include <pan/base/util-file.h>

#define SERVER_NAME_KEY "/Pan/Servers/Names"
static GSList * serverlist = NULL;
static Server * _active = NULL;

PString PAN_SENT;
PString PAN_SENDLATER;

/**
***  Private Utilities
**/

static gint
server_name_compare (gconstpointer a, gconstpointer b)
{
      const Server* sa = (const Server*) a;
      const Server* sb = (const Server*) b;
      return g_strcasecmp (server_get_name (sa), server_get_name (sb));
}

/**
***  Server Module
**/

static Server*
server_fetch (const PString * name_in)
{
      PString name = PSTRING_INIT;
      Server * server = NULL;
      char section_name[PATH_MAX];
      debug_enter ("server_fetch");

      /* sanity clause */
      g_return_val_if_fail (pstring_is_set (name_in), NULL);
      name = pstring_shallow (name_in->str, name_in->len);
      name = pstring_strstrip_shallow (&name);
      g_return_val_if_fail (pstring_is_set (&name), NULL);

      /* find the section */
      g_snprintf (section_name, sizeof(section_name), "/Pan/%*.*s", name.len, name.len, name.str);
      if (pan_config_has_section (section_name))
      {
            server = server_new ();
            pstring_copy (&server->name, &name);

            /* initialize the server from pan_config */
            pan_config_push_prefix (section_name);
            server->address = pstring_shallow (pan_config_get_string ("Address", NULL), -1);
            server->port = pan_config_get_int ("Port", 119);
            server->max_connections = pan_config_get_int ("Max_Connections", 2);
            server->idle_secs_before_timeout = pan_config_get_int ("Idle_Timeout_Secs", 180);
            server->last_newgroup_list_time = pan_config_get_ulong ("Last_Grouplist_Update", 0ul);
            server->use_newsrc = pan_config_get_bool ("Use_Newsrc", FALSE);
            server->newsrc_filename = pstring_shallow (pan_config_get_string ("Newsrc_Filename", NULL), -1);
            server->need_auth = pan_config_get_bool ("Auth_Required", FALSE);
            server->username = pstring_shallow (pan_config_get_string ("Username", NULL), -1);
            server->password = pstring_shallow (pan_config_get_string ("Password", NULL), -1);
            pan_config_pop_prefix ();

            /* if server is OK, then keep it.   Otherwise unref and return NULL */
            if (server_is_valid (server) && pstring_is_set (&server->name) && pstring_is_set (&server->address))
            {
                  /* make sure that server's directory exists */
                  char path[PATH_MAX];
                  g_snprintf (path, sizeof(path), "%s" G_DIR_SEPARATOR_S "%*.*s", get_data_dir(), name.len, name.len, name.str);
                  pan_file_ensure_path_exists (path);
            }
            else
            {
                  pan_object_unref (PAN_OBJECT(server));
                  server = NULL;
            }
      }

      debug_exit ("server_fetch");
      return server;
}

/**
 * Load a list of servers from the user's ~/.gnome/Pan file
 * @return a GSList of Server's for each server found
 */
static GSList*
server_list_load (void)
{
      GSList * l = NULL;
      gchar * p;
      debug_enter ("server_list_load");

      /* build all the servers in the list */
            p = pan_config_get_string (SERVER_NAME_KEY, NULL); /*commas*/
      if (p != NULL)
      {
            const char * walk = p;
            PString pstr;

            /* create a server object for each server in the list */
            while (get_next_token_pstring (walk, ',', &walk, &pstr)) {
                  if (pstr.len) {
                        Server * server = server_fetch (&pstr);
                        if (server!=NULL && (g_slist_find_custom (l, server, server_name_compare)==NULL))
                              l = g_slist_insert_sorted (l, server, server_name_compare);
                  }
            }

            /* cleanup */
            g_free (p);
      }

      debug_exit ("server_list_load");
      return l;
}

static void
server_init_servers (void)
{
      static gboolean inited = FALSE;
      debug_enter ("server_init_servers");

      if (!inited)
      {
            inited = TRUE;
            serverlist = server_list_load ();
      }

      debug_exit ("server_init_servers");
}

void
serverlist_get_servers (GPtrArray * fillme)
{
      GSList * l;

      g_return_if_fail (fillme!=NULL);

      pan_g_ptr_array_reserve (fillme, g_slist_length(serverlist));
      for (l=serverlist; l!=NULL; l=l->next)
            g_ptr_array_add (fillme, l->data);
}

void
serverlist_shutdown (void)
{
      GSList * l;

      /* save the updated server info */
      serverlist_save ();

      /* close down the servers */
      l = serverlist;
      serverlist = NULL;
      g_slist_foreach (l, (GFunc)pan_object_unref, NULL);
      g_slist_free (l);
}

Server*
serverlist_get_active_server (void)
{
      return _active;
}

void
serverlist_set_active_server (Server * server)
{
      g_return_if_fail (server != NULL);

      /* import the first time the server is activated */
      if (server->use_newsrc && !server->newsrc_imported) {
            newsrc_import (server, &server->newsrc_filename, FALSE);
            server->newsrc_imported = TRUE;
      }

      /* activate it */
      _active = server;
      if (_active!=NULL && pstring_is_set(&_active->name))
            pan_config_set_string ("/Pan/State/Server", _active->name.str);
      else
            pan_config_clean_key ("/Pan/State/Server");
      pan_callback_call (serverlist_get_server_activated_callback(), _active, NULL);
}

Server*
serverlist_get_named_server (const PString* servername)
{
      GSList * l;
      Server * retval = NULL;
      debug_enter ("server_get_by_name");

      g_return_val_if_fail (pstring_is_set (servername), NULL);

      server_init_servers ();

      for (l=serverlist; retval==NULL && l!=NULL; l=l->next) {
            Server * s = SERVER(l->data);
            if (pstring_equal (servername, &s->name))
                  retval = s;
      }

      debug_exit ("server_get_by_name");
      return retval;
}

Group*
serverlist_get_named_folder (const PString * foldername)
{
      Server * server;
             
      /* sanity clause */
      g_return_val_if_fail (pstring_is_set (foldername), NULL);
                   
      /* get the folder server... */
      server = serverlist_get_named_server (&INTERNAL_SERVER_NAME);
      g_return_val_if_fail (server_is_valid (server), NULL);
                               
      /* get the folder... */
      return server_get_named_group (server, foldername);
}

static Server*
get_default_server (void)
{
      GSList * l;
      gchar * name;
      Server * retval = NULL;

      g_return_val_if_fail (serverlist!=NULL, NULL);

      /* look in the gnome config for a default */
      name = pan_config_get_string ("/Pan/State/Server", NULL);
      if (is_nonempty_string (name)) {
            const PString pname = pstring_shallow (name, -1);
            retval = serverlist_get_named_server (&pname);
      }
      g_free (name);

      /* otherwise just use the first server */
      for (l=serverlist; retval==NULL && l!=NULL; l=l->next) {
            Server * s = SERVER(l->data);
            if (!pstring_equal (&s->name, &INTERNAL_SERVER_NAME))
                  retval = s;
      }

      /* return what we've got */
      return retval;
}



/****
*****
*****  SERVER LOADING ON STARTUP
*****
****/

void
serverlist_init (void)
{
      Server * s;

      server_init_servers ();

      s = get_default_server ();
      if (s != NULL)
            serverlist_set_active_server (s);
}

void
serverlist_add_server (Server * server, GError ** err)
{
      g_return_if_fail (err==NULL || *err==NULL);

      server_init_servers ();

      if (!server_is_valid (server)) {
            if (err != NULL)
                  *err = g_error_new (g_quark_from_string("serverlist"), 1, _("Server is corrupt"));
            return;
      }

      if (serverlist_get_named_server (&server->name) != NULL) {
            if (err != NULL)
                  *err = g_error_new (g_quark_from_string("serverlist"), 2, _("A Server with that name already exists."));
            return;
      }

      serverlist = g_slist_insert_sorted (serverlist,
                                          server,
                                          server_name_compare);

      if (!pstring_equal (&server->name, &INTERNAL_SERVER_NAME))
            serverlist_save ();
}

void
serverlist_remove_server (Server * server)
{
      g_return_if_fail (server_is_valid (server));

      serverlist = g_slist_remove (serverlist, server);
      /* might be best to just let this leak.
      pan_object_unref (PAN_OBJECT(server)); */
}


void
serverlist_save (void)
{
      /* out with the old */
      {
            char * p = pan_config_get_string (SERVER_NAME_KEY, NULL);
            if (p != NULL) {
                  GString * tmp = g_string_new (NULL);
                  PString pstr = PSTRING_INIT;
                  const char * walk = p;
                  while (get_next_token_pstring (walk, ',', &walk, &pstr)) {
                        if (pstr.len) {
                              g_string_assign (tmp, "/Pan/");
                              g_string_append_len (tmp, pstr.str, pstr.len);
                              pan_config_clean_section (tmp->str);
                        }
                  }
                  g_string_free (tmp, TRUE);
                  g_free (p);
            }
      }

      /* in with the new */
      {
            GSList * l = NULL;
            GString * servers = g_string_new (NULL);

            for (l=serverlist; l!=NULL; l=l->next)
            {
                  Server * s = SERVER(l->data);

                  if (server_is_valid (s) && pstring_is_set(&s->name) && !pstring_equal(&INTERNAL_SERVER_NAME, &s->name))
                  {
                        char section_name[PATH_MAX];
                        g_snprintf (section_name, sizeof(section_name), "/Pan/%*.*s", s->name.len, s->name.len, s->name.str);

                        pan_config_push_prefix (section_name);
                        pan_config_set_string ("Address", s->address.str);
                        pan_config_set_int ("Port", s->port);
                        pan_config_set_int ("Max_Connections", s->max_connections);
                        pan_config_set_int ("Idle_Timeout_Secs", s->idle_secs_before_timeout);
                        pan_config_set_ulong ("Last_Grouplist_Update", s->last_newgroup_list_time);
                        pan_config_set_bool ("Use_Newsrc", s->use_newsrc);
                        pan_config_set_string ("Newsrc_Filename", s->newsrc_filename.str);
                        pan_config_set_bool ("Auth_Required", s->need_auth);
                        pan_config_set_string ("Username", s->username.str);
                        pan_config_set_string ("Password", s->password.str);
                        pan_config_pop_prefix ();

                        if (servers->len)
                              g_string_append_c (servers, ',');
                        g_string_append_len (servers, s->name.str, s->name.len);
                  }
            }

            pan_config_set_string (SERVER_NAME_KEY, servers->str);
            g_string_free (servers, TRUE);
      }

      pan_config_sync ();
}

/**
***  Server Activated
**/

PanCallback*
serverlist_get_server_activated_callback (void)
{
      static PanCallback * cb = NULL;
      if (cb==NULL) cb = pan_callback_new ();
      return cb;
}

Generated by  Doxygen 1.6.0   Back to index