/*
Silky - A GTK+ client for SILC.
Copyright (C) 2003,2004 Toni Willberg
- Server list management functions
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
http://silky.sourceforge.net/
*/
#include <glib.h>
#include <silcincludes.h>
#include <silcclient.h>
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "servers.h"
#include "xmllayout.h"
#include "xmlconfig.h"
#include "preferences.h"
#include "log.h"
extern xmlDocPtr config_servers;
extern SilkyXMLElement xml_elements[NUM_CONFIG][NUM_CM];
SilkyServer *servers = NULL;
/* this one should be called from main.c, it takes care of everything
necessary to load server list into silky */
gboolean init_servers(gchar *serverspath) {
debug("Trying to load servers from config: %s", serverspath);
if( g_file_test(serverspath, G_FILE_TEST_EXISTS) ) {
debug("...file found");
if( !(config_servers = xml_read_config(CONFIG_SERVERS, serverspath)) ) {
debug("Failed to load servers from file '%s'!", serverspath);
return FALSE;
}
if( !parse_servers() ) {
debug("Failed to parse servers, none loaded");
return TRUE;
}
debug("Servers loaded, continuing");
return TRUE;
}
return FALSE;
}
/* this one parses the loaded xmlDoc and populates our internal SilkyServer
linked list with servers found there */
gboolean parse_servers() {
xmlXPathObjectPtr result;
xmlXPathContextPtr context;
xmlNodePtr node, n;
gchar *host = NULL;
gchar *port_str = NULL;
gint port = -1, i;
xml_cleanup_config(CONFIG_SERVERS);
debug("Populating SilkyServer list...");
context = xmlXPathNewContext(config_servers);
result = xmlXPathEval(g_strdup_printf("/%s/%s", xml_elements[CONFIG_SERVERS][CS_ROOT].name, xml_elements[CONFIG_SERVERS][CS_SERVER].name), context);
if( !result ) {
debug("No result found for servers!");
return FALSE;
}
if( xmlXPathNodeSetIsEmpty(result->nodesetval) ) {
debug("Zaroo servers found.");
return TRUE;
}
xmlXPathFreeContext(context);
for( i = 0; i < result->nodesetval->nodeNr; i++ ) {
node = result->nodesetval->nodeTab[i];
port = 706;
for( n = node->children; n && strcmp(n->name, xml_elements[CONFIG_SERVERS][CS_SERVER].name) ; n = n->next ) {
if( !strcmp(n->name, xml_elements[CONFIG_SERVERS][CS_SERVER_HOSTNAME].name) ) {
host = g_strdup(xmlNodeGetContent(n));
}
if( !strcmp(n->name, xml_elements[CONFIG_SERVERS][CS_SERVER_PORT].name) ) {
port_str = g_strdup(xmlNodeGetContent(n));
port = atoi(port_str);
}
}
if( !host || !g_utf8_strlen(host, -1) ) {
debug("Hostname empty, ignoring server");
} else if ( port <= 0 ) {
debug("Port number incorrect: %d", port);
} else {
debug("Adding server %s:%d", host, port);
server_add(host, port);
}
}
xmlXPathFreeObject(result);
if( !i ) debug("Zaroo servers found.");
return TRUE;
}
SilkyServer *server_find_by_hostport(gchar *host, gint port) {
SilkyServer *s;
if( !host ) {
debug("host == NULL");
return NULL;
}
for( s = servers; s; s = s->next ) {
if( !strcmp(s->hostname, host) && (port == s->port) ) {
debug("found server '%s:%d'", host, port);
return s;
}
}
debug("server '%s:%d' not found", host, port);
return NULL;
}
SilkyServer *server_add(gchar *hostname, gint port) {
SilkyServer *s, *news;
if( (!hostname || !g_utf8_strlen(hostname, -1)) ||
(port < 1 || port > 65535) ) {
debug("(!!) some server info is missing, cannot add");
return NULL;
}
if( server_find_by_hostport(hostname, port) ) {
debug("server '%s:%d' already exists", hostname, port);
return NULL;
}
debug("creating SilkyServer struct for '%s:%d'", hostname, port);
news = malloc( sizeof( SilkyServer ) );
news->next = NULL;
news->hostname = g_strdup(hostname);
news->port = port;
news->autoconnect = FALSE;
if( !servers ) {
debug("first server, creating linked list");
servers = news;
} else {
debug("there are already some servers, appending to linked list");
for( s = servers; s->next; s = s->next ) {}
s->next = news;
}
return news;
}
/**
* server_remove:
* @server: #SilkyServer to remove from linked list of servers
*
* Removes specified #SilkyServer struct from list of servers, if it is there.
*
* Returns: TRUE if specified server was found in list and removed, FALSE
* otherwise
**/
gboolean server_remove( SilkyServer *server ) {
SilkyServer *s, *prevs;
gint found = 0;
if( !servers ) {
debug("No servers found, not removing anything");
return FALSE;
}
for( s = servers, prevs = servers; s; s = s->next ) {
if( server == s ) {
debug("found our server");
found++;
break;
}
prevs = s;
}
if( !found ) {
debug("server not in list, cannot remove");
return FALSE;
}
debug("removing server from list");
if( s == servers ) {
debug("it is first server in list");
servers = servers->next;
} else {
debug("not first server in list");
prevs->next = s->next;
}
debug("freeing server struct from memory");
g_free(s);
return TRUE;
}
/**
* servers_store_to_xml:
*
* Recreates servers' xmlDoc structure, filling it with servers from stored
* linked list.
*
* Returns: TRUE if succesful, false otherwise
**/
gboolean servers_store_to_xml() {
SilkyServer *s;
xmlNodePtr node;
debug("freeing servers xmlDoc");
if( config_servers ) {
xmlFreeDoc(config_servers);
config_servers = NULL;
}
if( !servers ) {
debug("no servers to store");
return FALSE;
}
if( !(config_servers = xml_create_config(CONFIG_SERVERS)) ) {
debug("Couldn't create config_servers");
return FALSE;
}
for( s = servers; s; s = s->next ) {
node = xmlNewTextChild(xml_get_node(CONFIG_SERVERS, xml_doc(CONFIG_SERVERS), CS_ROOT), NULL, xml_elements[CONFIG_SERVERS][CS_SERVER].name, NULL);
// node = xml_create_node(CONFIG_SERVERS, CS_SERVER);
if( s->hostname && g_utf8_strlen(s->hostname, -1) ) {
debug("Saving server '%s:%d'", s->hostname, s->port);
xmlNewTextChild(node, NULL, xml_elements[CONFIG_SERVERS][CS_SERVER_HOSTNAME].name, s->hostname);
xmlNewTextChild(node, NULL, xml_elements[CONFIG_SERVERS][CS_SERVER_PORT].name, g_strdup_printf("%d", s->port));
xmlNewTextChild(node, NULL, xml_elements[CONFIG_SERVERS][CS_SERVER_AUTOCONNECT].name, (s->autoconnect ? PREF_ON : PREF_OFF));
}
}
return TRUE;
}
syntax highlighted by Code2HTML, v. 0.9.1