/* 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 #include #include #ifdef HAVE_CONFIG_H # include #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; }