Actually remove networks from disk when they have been removed in the configuration.
[jelmer/ctrlproxy.git] / src / settings.c
index 34b1fb08310d01940017bc0d87171786676bc82f..a8548fbcb1a020accbce7540475473450fff3eaf 100644 (file)
@@ -42,6 +42,7 @@
 
 static GList *known_keys = NULL;
 
+static void config_cleanup_networks_dir(struct ctrlproxy_config *cfg);
 static void config_save_log(struct log_file_config *data,
                                                        struct ctrlproxy_config *config);
 static void config_save_auto_away(struct auto_away_config *d, 
@@ -146,13 +147,10 @@ static void config_save_tcp_servers(struct network_config *n, GKeyFile *kf)
        
        for (gl = n->type_settings.tcp_servers; gl; gl = gl->next) {
                struct tcp_server_config *ts = gl->data;
-               char *name = g_strdup_printf("%s:%s", ts->host, ts->port);
+               char *name = irc_create_url(ts->host, ts->port, ts->ssl);
 
                values[i] = name;
 
-               if (g_key_file_has_key(kf, name, "ssl", NULL) || ts->ssl)
-                       g_key_file_set_boolean(kf, name, "ssl", ts->ssl);
-
                if (ts->password)
                        g_key_file_set_string(kf, name, "password", ts->password);
                else
@@ -200,7 +198,8 @@ static void config_save_network(const char *dir, struct network_config *n, GList
        g_key_file_set_string(kf, "global", "username", n->username);
        if (n->queue_speed)
                g_key_file_set_integer(kf, "global", "queue-speed", n->queue_speed);
-       g_key_file_set_integer(kf, "global", "reconnect-interval", n->reconnect_interval);
+       if (n->reconnect_interval != -1)
+               g_key_file_set_integer(kf, "global", "reconnect-interval", n->reconnect_interval);
 
        switch(n->type) {
        case NETWORK_VIRTUAL:
@@ -231,8 +230,10 @@ static void config_save_network(const char *dir, struct network_config *n, GList
                        *channel_keys = g_list_append(*channel_keys, key);
                }
                
-               autojoin_list[autojoin_list_count] = c->name;
-               autojoin_list_count++;
+               if (c->autojoin) {
+                       autojoin_list[autojoin_list_count] = c->name;
+                       autojoin_list_count++;
+               }
 
                g_key_file_remove_group(kf, c->name, NULL);
        }
@@ -335,9 +336,12 @@ static void config_save_networks(struct ctrlproxy_config *cfg, const char *confi
 
        for (gl = networks; gl; gl = gl->next) {
                struct network_config *n = gl->data;
-               config_save_network(networksdir, n, &channel_keys);
+               if (!n->implicit) 
+                       config_save_network(networksdir, n, &channel_keys);
        }
 
+       config_cleanup_networks_dir(cfg);
+
        if (channel_keys != NULL) {
                char *filename = g_build_filename(cfg->config_dir, "keys", 
                                                                          NULL);
@@ -355,6 +359,12 @@ static void config_save_networks(struct ctrlproxy_config *cfg, const char *confi
        g_free(networksdir);
 }
 
+/**
+ * Save configuration to a configuration directory.
+ *
+ * @param cfg The configuration to save.
+ * @param configuration_dir Directory to save to.
+ */
 void save_configuration(struct ctrlproxy_config *cfg, const char *configuration_dir)
 {
        char *fn, **list;
@@ -426,7 +436,7 @@ void save_configuration(struct ctrlproxy_config *cfg, const char *configuration_
 
        config_save_log(cfg->log_file, cfg);
 
-       config_save_auto_away(cfg->auto_away, cfg);
+       config_save_auto_away(&cfg->auto_away, cfg);
 
        i = 0;
        list = g_new0(char *, g_list_length(cfg->networks)+1);
@@ -477,20 +487,13 @@ static void config_load_servers(struct network_config *n)
        for (i = 0; i < size; i++) {
                char *tmp;
                struct tcp_server_config *s = g_new0(struct tcp_server_config, 1);
+
+               irc_parse_url(servers[i], &s->host, &s->port, &s->ssl);
                
                s->password = g_key_file_get_string(n->keyfile, servers[i], "password", NULL);
                if (g_key_file_has_key(n->keyfile, servers[i], "ssl", NULL))
                        s->ssl = g_key_file_get_boolean(n->keyfile, servers[i], "ssl", NULL);
 
-               tmp = strrchr(servers[i], ':');
-
-               if (tmp) {
-                       *tmp = '\0';
-                       tmp++;
-               }
-               
-               s->host = servers[i];
-               s->port = g_strdup(tmp != NULL?tmp:DEFAULT_IRC_PORT);
                s->bind_address = g_key_file_get_string(n->keyfile, servers[i], "bind", NULL);
                if (s->bind_address && (tmp = strchr(s->bind_address, ':'))) {
                        *tmp = '\0';
@@ -498,9 +501,11 @@ static void config_load_servers(struct network_config *n)
                }
 
                n->type_settings.tcp_servers = g_list_append(n->type_settings.tcp_servers, s);
+
+               g_key_file_remove_group(n->keyfile, servers[i], NULL);
        }
 
-       g_free(servers);
+       g_strfreev(servers);
 }
 
 static struct channel_config *config_find_add_channel(struct network_config *nc, const char *name)
@@ -534,7 +539,6 @@ static struct network_config *config_load_network(struct ctrlproxy_config *cfg,
        char **groups;
        GError *error = NULL;
        gsize size;
-       char **autojoin_channels;
 
        kf = g_key_file_new();
 
@@ -632,14 +636,17 @@ static struct network_config *config_load_network(struct ctrlproxy_config *cfg,
                }
        }
 
-       autojoin_channels = g_key_file_get_string_list(n->keyfile, "global", "autojoin", &size, NULL);
-       for (i = 0; i < size; i++) {
-               struct channel_config *cc = config_find_add_channel(n, autojoin_channels[i]);
+       if (g_key_file_has_key(n->keyfile, "global", "autojoin", NULL)) {
+               char **autojoin_channels;
+               autojoin_channels = g_key_file_get_string_list(n->keyfile, "global", "autojoin", &size, NULL);
+               for (i = 0; i < size; i++) {
+                       struct channel_config *cc = config_find_add_channel(n, autojoin_channels[i]);
 
-               cc->autojoin = TRUE;
-       }
+                       cc->autojoin = TRUE;
+               }
 
-       g_strfreev(autojoin_channels);
+               g_strfreev(autojoin_channels);
+       }
 
        return n;
 }
@@ -670,7 +677,7 @@ static struct network_config *find_create_network_config(struct ctrlproxy_config
                        if (g_strncasecmp(sc->host, name, strlen(sc->host)) != 0)
                                continue;
 
-                       tmp = g_strdup_printf("%s:%s", sc->host, sc->port);
+                       tmp = irc_create_url(sc->host, sc->port, FALSE);
 
                        if (g_strcasecmp(tmp, name) == 0)
                                return nc;
@@ -682,17 +689,10 @@ static struct network_config *find_create_network_config(struct ctrlproxy_config
        nc = network_config_init(cfg);
        nc->name = g_strdup(name);
        nc->autoconnect = FALSE;
-       nc->reconnect_interval = DEFAULT_RECONNECT_INTERVAL;
+       nc->reconnect_interval = -1;
        nc->type = NETWORK_TCP;
        tc = g_new0(struct tcp_server_config, 1);
-       tc->host = g_strdup(name);
-       if (strchr(tc->host, ':')) {
-               tc->port = tc->host+1;
-               *tc->port = '\0';
-       } else {
-               tc->port = g_strdup(DEFAULT_IRC_PORT);
-       }
-
+       irc_parse_url(name, &tc->host, &tc->port, &tc->ssl);
        nc->type_settings.tcp_servers = g_list_append(nc->type_settings.tcp_servers, tc);
 
        cfg->networks = g_list_append(cfg->networks, nc);
@@ -844,6 +844,45 @@ static void config_load_listeners(struct ctrlproxy_config *cfg)
        g_free(filename);
 }
 
+struct network_config *config_find_network(struct ctrlproxy_config *cfg, 
+                                                                                  const char *name)
+{
+       GList *gl;
+       for (gl = cfg->networks; gl; gl = gl->next) {
+               struct network_config *nc = gl->data;
+               if (!g_strcasecmp(nc->name, name))
+                       return nc;
+       }
+       return NULL;
+}
+
+#define IS_SPECIAL_FILE(name) (name[0] == '.' || name[strlen(name)-1] == '~')
+
+static void config_cleanup_networks_dir(struct ctrlproxy_config *cfg)
+{
+       char *networksdir = g_build_filename(cfg->config_dir, "networks", NULL);
+       GDir *dir;
+       const char *name;
+
+       dir = g_dir_open(networksdir, 0, NULL);
+       if (dir == NULL)
+               return;
+
+       while ((name = g_dir_read_name(dir))) {
+               char *path;
+               if (IS_SPECIAL_FILE(name) || config_find_network(cfg, name))
+                       continue;
+
+               path = g_build_filename(networksdir, name, NULL);
+               g_unlink(path);
+               g_free(path);
+       }
+
+       g_free(networksdir);
+
+       g_dir_close(dir);
+}
+
 static void config_load_networks(struct ctrlproxy_config *cfg, GList *channel_keys)
 {
        char *networksdir = g_build_filename(cfg->config_dir, "networks", NULL);
@@ -855,7 +894,7 @@ static void config_load_networks(struct ctrlproxy_config *cfg, GList *channel_ke
                return;
 
        while ((name = g_dir_read_name(dir))) {
-               if (name[0] == '.' || name[strlen(name)-1] == '~')
+               if (IS_SPECIAL_FILE(name))
                        continue;
                config_load_network(cfg, networksdir, name, channel_keys);
        }
@@ -878,10 +917,12 @@ static void config_save_log(struct log_file_config *data,
 
        if (data->is_irssi) {
                g_key_file_set_string(config->keyfile, "global", "logging", "irssi");
-               if (data->logbasedir)
-                       g_key_file_set_string(config->keyfile, "global", "logdir", data->logbasedir);
-               else
+               if (data->logbasedir) {
+                       if (!data->logbasedir_is_default)
+                               g_key_file_set_string(config->keyfile, "global", "logdir", data->logbasedir);
+               } else {
                        g_key_file_set_string(config->keyfile, "global", "logfile", data->logfilename);
+               }
        } else {
                STORE_SETTING(data, config->keyfile, "global", "", logfilename);
                STORE_SETTING(data, config->keyfile, "global", "log-format-", nickchange);
@@ -904,7 +945,7 @@ static void config_load_log(struct ctrlproxy_config *config)
        struct log_file_config *data;
        char *logging = NULL;
 
-       if (g_key_file_get_string(kf, "global", "logging", NULL) != NULL) {
+       if (g_key_file_has_key(kf, "global", "logging", NULL)) {
                logging = g_key_file_get_string(kf, "global", "logging", NULL);
        }
 
@@ -978,6 +1019,8 @@ static void config_load_log(struct ctrlproxy_config *config)
                        data->logbasedir = g_build_filename(config->config_dir, 
                                                                                  "log_irssi", NULL);
 
+                       data->logbasedir_is_default = TRUE;
+
                        data->logfilename = g_strdup_printf("%s/%%N/%%@", data->logbasedir);
                }
                g_key_file_remove_group(kf, "log-irssi", NULL);
@@ -999,12 +1042,10 @@ static void config_load_log(struct ctrlproxy_config *config)
 static void config_save_auto_away(struct auto_away_config *d, struct ctrlproxy_config *config)
 {
        GKeyFile *kf = config->keyfile;
-
-       if (config->auto_away == NULL) {
-               g_key_file_set_boolean(kf, "global", "auto-away-enable", FALSE);
-               return;
-       }
-       g_key_file_set_boolean(kf, "global", "auto-away-enable", TRUE);
+       
+       if (g_key_file_has_key(kf, "global", "auto-away-enable", NULL) ||
+               d->enabled)
+               g_key_file_set_boolean(kf, "global", "auto-away-enable", d->enabled);
 
        if (d->message != NULL)
                g_key_file_set_string(kf, "global", "auto-away-message", d->message);
@@ -1015,17 +1056,14 @@ static void config_save_auto_away(struct auto_away_config *d, struct ctrlproxy_c
        if (d->client_limit != -1)
                g_key_file_set_integer(kf, "global", "auto-away-client-limit", d->client_limit);
 
-       g_key_file_set_integer(kf, "global", "auto-away-time", d->max_idle_time);
+       if (d->max_idle_time != -1)
+               g_key_file_set_integer(kf, "global", "auto-away-time", d->max_idle_time);
 }
 
-static void config_load_auto_away(struct ctrlproxy_config *config)
+static void config_load_auto_away(struct auto_away_config *d, GKeyFile *kf)
 {
-       struct auto_away_config *d;
-       GKeyFile *kf = config->keyfile;
-
        if (g_key_file_has_group(kf, "auto-away")) {
-               d = g_new0(struct auto_away_config, 1);
-               
+               d->enabled = TRUE;
                d->message = g_key_file_get_string(kf, "auto-away", "message", NULL);
                d->nick = g_key_file_get_string(kf, "auto-away", "nick", NULL);
                if (g_key_file_has_key(kf, "auto-away", "client_limit", NULL)) {
@@ -1042,29 +1080,23 @@ static void config_load_auto_away(struct ctrlproxy_config *config)
                if (g_key_file_has_key(kf, "auto-away", "time", NULL))
                        d->max_idle_time = g_key_file_get_integer(kf, "auto-away", "time", NULL);
                else
-                       d->max_idle_time = AUTO_AWAY_DEFAULT_TIME;
+                       d->max_idle_time = -1;
 
                g_key_file_remove_group(kf, "auto-away", NULL);
-       } else if (g_key_file_has_key(kf, "global", "auto-away-enable", NULL) &&
-                          g_key_file_get_boolean(kf, "global", "auto-away-enable", NULL)) {
-               d = g_new0(struct auto_away_config, 1);
-               
+       } else {
+               if (g_key_file_has_key(kf, "global", "auto-away-enable", NULL))
+                       d->enabled = g_key_file_get_boolean(kf, "global", "auto-away-enable", NULL);
                d->message = g_key_file_get_string(kf, "global", "auto-away-message", NULL);
                d->nick = g_key_file_get_string(kf, "global", "auto-away-nick", NULL);
                if (g_key_file_has_key(kf, "global", "auto-away-client-limit", NULL)) {
                        d->client_limit = g_key_file_get_integer(kf, "global", "auto-away-client-limit", NULL);
-               }
-               else
+               } else
                        d->client_limit = -1;
                if (g_key_file_has_key(kf, "global", "auto-away-time", NULL))
                        d->max_idle_time = g_key_file_get_integer(kf, "global", "auto-away-time", NULL);
                else
-                       d->max_idle_time = AUTO_AWAY_DEFAULT_TIME;
-       } else {
-               return;
+                       d->max_idle_time = -1;
        }
-
-       config->auto_away = d;
 }
 
 struct ctrlproxy_config *init_configuration(void)
@@ -1198,7 +1230,7 @@ struct ctrlproxy_config *load_configuration(const char *dir)
        config_load_listeners(cfg);
        config_load_listeners_socks(cfg);
        config_load_log(cfg);
-       config_load_auto_away(cfg);
+       config_load_auto_away(&cfg->auto_away, cfg->keyfile);
 
        keyfile_filename = g_build_filename(cfg->config_dir, "keys", 
                                                                          NULL);
@@ -1252,7 +1284,7 @@ struct network_config *network_config_init(struct ctrlproxy_config *cfg)
                g_free(s->fullname);
                s->fullname = g_strdup(s->username);
        }
-       s->reconnect_interval = DEFAULT_RECONNECT_INTERVAL;
+       s->reconnect_interval = -1;
 
        if (cfg) 
                cfg->networks = g_list_append(cfg->networks, s);
@@ -1353,13 +1385,16 @@ gboolean create_configuration(const char *config_dir)
        l = g_new0(struct listener_config, 1);
        pass = getpass("Please specify a password for the administration interface: "); 
        l->port = port;
+       l->is_default = TRUE;
        if (!strcmp(pass, "")) {
                fprintf(stderr, "Warning: no password specified. Authentication disabled!\n");
        } else {
-               l->password = pass;
+               l->password = g_strdup(pass);
        }
 
        global->config->listeners = g_list_append(global->config->listeners, l);
 
+       save_configuration(global->config, config_dir);
+
        return TRUE;
 }