configuration.c

Go to the documentation of this file.
00001 /*
00002  Copyright (C) 2005-2007 Erik van Pienbroek
00003 
00004  This program is free software; you can redistribute it and/or modify
00005  it under the terms of the GNU General Public License as published by
00006  the Free Software Foundation; either version 2 of the License, or
00007  (at your option) any later version.
00008 
00009  This program is distributed in the hope that it will be useful,
00010  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00012  GNU General Public License for more details.
00013 
00014  You should have received a copy of the GNU General Public License
00015  along with this program; if not, write to the Free Software
00016  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00017 */
00018 
00019 #include 
00020 #include 
00021 #include 
00022 #include 
00023 #ifdef WIN32
00024 #include 
00025 #include 
00026 #include 
00027 #endif
00028 
00029 #include "configuration.h"
00030 #include "nntpgrab_internal.h"
00031 
00032 typedef struct ConfigurationClass ConfigurationClass;
00033 
00034 Configuration *configuration_get_object(void);
00035 GType configuration_get_type (void);
00036 
00037 typedef struct _config_server_details
00038 {
00039     GList *groups;                  // containing ConfigGroupInfo's
00040 } ConfigServerDetails;
00041 
00042 struct Configuration
00043 {
00044     GObject parent;
00045 
00046     GStaticRWLock rwlock;
00047     GList *servers;                 // containing ConfigServer's
00048     GHashTable *group_details;      // containing ConfigGroupInfo's
00049 
00050     ConfigOpts opts;
00051 };
00052 
00053 struct ConfigurationClass
00054 {
00055     GObjectClass parent;
00056 };
00057 
00058 enum
00059 {
00060     CONFIG_CHANGED_SIGNAL,
00061     LAST_SIGNAL
00062 };
00063 
00064 static guint signals[LAST_SIGNAL] = { 0 };
00065 
00066 G_DEFINE_TYPE(Configuration, configuration, G_TYPE_OBJECT)
00067 
00068 static void
00069 group_details_free_func(gpointer data)
00070 {
00071     g_slice_free(ConfigGroupInfo, data);
00072 }
00073 
00074 static void
00075 configuration_init (Configuration *obj)
00076 {
00077     g_static_rw_lock_init(&obj->rwlock);
00078 
00079     obj->servers = NULL;
00080     obj->group_details = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, group_details_free_func);
00081 }
00082 
00083 static void
00084 configuration_finalize (GObject *obj)
00085 {
00086     char *errmsg;
00087     Configuration *config = CONFIGURATION(obj);
00088     GList *list;
00089 
00090     if (!(configuration_save(config, &errmsg))) {
00091         nntpgrab_core_emit_warning(errmsg);
00092         g_free(errmsg);
00093     }
00094 
00095     g_static_rw_lock_writer_lock(&config->rwlock);
00096 
00097     list = config->servers;
00098     while (list) {
00099         g_slice_free(ConfigServer, list->data);
00100         list = g_list_next(list);
00101     }
00102     g_list_free(config->servers);
00103 
00104     g_hash_table_destroy(config->group_details);
00105 
00106     g_static_rw_lock_writer_unlock(&config->rwlock);
00107     g_static_rw_lock_free(&config->rwlock);
00108 }
00109 
00110 static void
00111 configuration_class_init (ConfigurationClass *klass)
00112 {
00113     GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
00114 
00115     gobject_class->finalize = configuration_finalize;
00116 
00117     signals[CONFIG_CHANGED_SIGNAL] = g_signal_new  ("config_changed",
00118                                                     G_OBJECT_CLASS_TYPE (klass),
00119                                                     G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
00120                                                     0,
00121                                                     NULL, NULL,
00122                                                     g_cclosure_marshal_VOID__INT,
00123                                                     G_TYPE_NONE, 1, G_TYPE_INT);
00124 }
00125 
00126 Configuration *
00127 configuration_new(char **errmsg, char **warnings)
00128 {
00129     Configuration *config = g_object_new(CONFIGURATION_TYPE_OBJECT, NULL);
00130 
00131     if (!configuration_load(config, errmsg)) {
00132         // Load of configuration failed..probably no configuration file created yet.
00133         // Create a default configuration file
00134         g_free(*errmsg);
00135         *errmsg = NULL;
00136 
00137         if (warnings) {
00138             *warnings = g_strdup(_("Configuration file for the NNTPGrab backend could not be loaded. Default configuration file is now created"));
00139         }
00140     }
00141 
00142     return config;
00143 }
00144 
00145 void
00146 configuration_destroy(Configuration *obj)
00147 {
00148     g_object_unref(obj);
00149 }
00150 
00151 
00159 GList *
00160 configuration_get_avail_servers(Configuration *obj)
00161 {
00162     Configuration *config = CONFIGURATION(obj);
00163     GList *list;
00164     GList *ret = NULL;
00165 
00166     g_static_rw_lock_reader_lock(&config->rwlock);
00167 
00168     list = config->servers;
00169     while (list) {
00170         ConfigServer *server = list->data;
00171 
00172         ret = g_list_append(ret, g_strdup(server->servername));
00173 
00174         list = g_list_next(list);
00175     }
00176 
00177     g_static_rw_lock_reader_unlock(&config->rwlock);
00178 
00179     return ret;
00180 }
00181 
00188 void
00189 configuration_free_avail_servers(Configuration *obj, GList *servers)
00190 {
00191     GList *list;
00192 
00193     list = servers;
00194     while (list) {
00195         g_free(list->data);
00196         list = g_list_next(list);
00197     }
00198 
00199     g_list_free(servers);
00200 }
00201 
00209 ConfigServer *
00210 configuration_get_server_info(Configuration *obj, const char *servername)
00211 {
00212     Configuration *config = CONFIGURATION(obj);
00213     GList *list;
00214 
00215     g_static_rw_lock_reader_lock(&config->rwlock);
00216 
00217     list = config->servers;
00218     while (list) {
00219         ConfigServer *server = list->data;
00220 
00221         if (!strcmp(server->servername, servername)) {
00222             ConfigServer *ret = g_slice_new0(ConfigServer);
00223 
00224             memcpy(ret, server, sizeof(ConfigServer));
00225 
00226             g_static_rw_lock_reader_unlock(&config->rwlock);
00227 
00228             return ret;
00229         }
00230 
00231         list = g_list_next(list);
00232     }
00233 
00234     g_static_rw_lock_reader_unlock(&config->rwlock);
00235 
00236     return NULL;
00237 }
00238 
00246 gboolean
00247 configuration_add_server(Configuration *obj, ConfigServer new_server)
00248 {
00249     Configuration *config = CONFIGURATION(obj);
00250     ConfigServer *server;
00251     GList *list;
00252 
00253     // Check is the new_server contains sane data
00254     g_assert(new_server.port > 0 && new_server.port 00255     g_assert(new_server.max_threads > 0);
00256 
00257     if (!strcmp(new_server.servername, "options")) {
00258         return FALSE;
00259     }
00260 
00261     // Check if the servername of the new_server is already known
00262     g_static_rw_lock_reader_lock(&config->rwlock);
00263 
00264     list = config->servers;
00265     while (list) {
00266         server = list->data;
00267 
00268         if (!strcmp(new_server.servername, server->servername)) {
00269             // servername already exists, refuse the addition of a new server
00270             g_static_rw_lock_reader_unlock(&config->rwlock);
00271             return FALSE;
00272         }
00273 
00274         list = g_list_next(list);
00275     }
00276 
00277     g_static_rw_lock_reader_unlock(&config->rwlock);
00278 
00279     // servername not found, it is safe to add the new configuration
00280     g_static_rw_lock_writer_lock(&config->rwlock);
00281 
00282     server = g_slice_new0(ConfigServer);
00283     memcpy(server, &new_server, sizeof(ConfigServer));
00284     config->servers = g_list_append(config->servers, server);
00285 
00286     g_static_rw_lock_writer_unlock(&config->rwlock);
00287 
00288     // Notify listeners that the configuration has changed
00289     g_signal_emit (config, signals[CONFIG_CHANGED_SIGNAL], 0, CONFIG_CHANGED_SERVER_ADDED);
00290 
00291     return TRUE;
00292 }
00293 
00301 gboolean
00302 configuration_del_server(Configuration *obj, const char *servername)
00303 {
00304     Configuration *config = CONFIGURATION(obj);
00305     ConfigServer *server;
00306     GList *list;
00307 
00308     // Check if the servername is known
00309     g_static_rw_lock_reader_lock(&config->rwlock);
00310 
00311     list = config->servers;
00312     while (list) {
00313         server = list->data;
00314 
00315         if (!strcmp(servername, server->servername)) {
00316             // servername exists, remove it from the list
00317             g_static_rw_lock_reader_unlock(&config->rwlock);
00318 
00319             g_static_rw_lock_writer_lock(&config->rwlock);
00320 
00321             g_slice_free(ConfigServer, server);
00322             config->servers = g_list_remove(config->servers, server);
00323 
00324             g_static_rw_lock_writer_unlock(&config->rwlock);
00325 
00326             // Notify listeners that the configuration has changed
00327             g_signal_emit (config, signals[CONFIG_CHANGED_SIGNAL], 0, CONFIG_CHANGED_SERVER_DELETED);
00328 
00329             return TRUE;
00330         }
00331 
00332         list = g_list_next(list);
00333     }
00334 
00335     g_static_rw_lock_reader_unlock(&config->rwlock);
00336 
00337     return FALSE;
00338 }
00339 
00348 gboolean
00349 configuration_edit_server(Configuration *obj, const char *servername, ConfigServer new_server)
00350 {
00351     Configuration *config = CONFIGURATION(obj);
00352     ConfigServer *server;
00353     GList *list;
00354 
00355     if (!strcmp(new_server.servername, "options")) {
00356         return FALSE;
00357     }
00358 
00359     // Check if the servername of the new_server is already known
00360     g_static_rw_lock_reader_lock(&config->rwlock);
00361 
00362     list = config->servers;
00363     while (list) {
00364         server = list->data;
00365 
00366         if (!strcmp(servername, server->servername)) {
00367             // servername exists, edit the settings
00368             g_static_rw_lock_reader_unlock(&config->rwlock);
00369 
00370             g_static_rw_lock_writer_lock(&config->rwlock);
00371 
00372             // apply the new settings
00373             memcpy(server, &new_server, sizeof(ConfigServer));
00374 
00375             g_static_rw_lock_writer_unlock(&config->rwlock);
00376 
00377             // Notify listeners that the configuration has changed
00378             g_signal_emit (config, signals[CONFIG_CHANGED_SIGNAL], 0, CONFIG_CHANGED_SERVER_ADDED);
00379 
00380 
00381             return TRUE;
00382         }
00383 
00384         list = g_list_next(list);
00385     }
00386 
00387     g_static_rw_lock_reader_unlock(&config->rwlock);
00388 
00389     return FALSE;
00390 }
00391 
00398 ConfigOpts
00399 configuration_get_opts(Configuration *obj)
00400 {
00401     Configuration *config = CONFIGURATION(obj);
00402     ConfigOpts ret;
00403 
00404     g_static_rw_lock_reader_lock(&config->rwlock);
00405 
00406     ret = config->opts;
00407 
00408     g_static_rw_lock_reader_unlock(&config->rwlock);
00409 
00410     return ret;
00411 }
00412 
00419 void
00420 configuration_set_opts(Configuration *obj, ConfigOpts opts)
00421 {
00422     Configuration *config = CONFIGURATION(obj);
00423 
00424     g_static_rw_lock_writer_lock(&config->rwlock);
00425 
00426     // Hack for Win32, if the download folder or temp folder is the root of a drive, append an extra \ to it
00427 #ifdef WIN32
00428     if (strlen(opts.download_directory) == 2 && opts.download_directory[1] == ':') {
00429         opts.download_directory[2] = '\\';
00430         opts.download_directory[3] = '\0';
00431     }
00432 
00433     if (strlen(opts.temp_directory) == 2 && opts.temp_directory[1] == ':') {
00434         opts.temp_directory[2] = '\\';
00435         opts.temp_directory[3] = '\0';
00436     }
00437 #endif
00438 
00439     config->opts = opts;
00440 
00441     g_static_rw_lock_writer_unlock(&config->rwlock);
00442 
00443     // Notify listeners that the configuration has changed
00444     g_signal_emit (config, signals[CONFIG_CHANGED_SIGNAL], 0, CONFIG_CHANGED_OPTS_CHANGED);
00445 }
00446 
00456 ConfigGroupInfo
00457 configuration_get_newsgroup_info(Configuration *obj, const char *servername, const char *newsgroup)
00458 {
00459     ConfigGroupInfo ret;
00460     ConfigGroupInfo *info;
00461     Configuration *config = CONFIGURATION(obj);
00462     char *hash;
00463 
00464     g_static_rw_lock_reader_lock(&config->rwlock);
00465 
00466     hash = g_strdup_printf("%s_%s", servername, newsgroup);
00467     info = g_hash_table_lookup(config->group_details, hash);
00468     g_free(hash);
00469 
00470     if (info) {
00471         memcpy(&ret, info, sizeof(ConfigGroupInfo));
00472     } else {
00473         memset(&ret, 0, sizeof(ConfigGroupInfo));
00474         strncpy((char *) ret.newsgroup, newsgroup, sizeof(ret.newsgroup));
00475     }
00476 
00477     g_static_rw_lock_reader_unlock(&config->rwlock);
00478 
00479     return ret;
00480 }
00481 
00490 void
00491 configuration_set_newsgroup_info(Configuration *obj, const char *servername, const char *newsgroup, ConfigGroupInfo info)
00492 {
00493     Configuration *config = CONFIGURATION(obj);
00494     ConfigGroupInfo *info_new;
00495     char *hash;
00496 
00497     g_static_rw_lock_writer_lock(&config->rwlock);
00498 
00499     info_new = g_slice_new(ConfigGroupInfo);
00500     memcpy(info_new, &info, sizeof(ConfigGroupInfo));
00501 
00502     hash = g_strdup_printf("%s_%s", servername, newsgroup);
00503     g_hash_table_replace(config->group_details, hash, info_new);
00504     g_free(hash);
00505 
00506     g_static_rw_lock_writer_unlock(&config->rwlock);
00507 }
00508 
00516 gboolean
00517 configuration_load(Configuration *obj, char **errmsg)
00518 {
00519     Configuration *config = CONFIGURATION(obj);
00520     GKeyFile *keyfile;
00521     GError *err = NULL;
00522     char *filename;
00523     char **groups;
00524     int i;
00525     GList *list;
00526 
00527     g_static_rw_lock_writer_lock(&config->rwlock);
00528 
00529     // Free the already known settings
00530     list = config->servers;
00531     while (list) {
00532         ConfigServer *server = list->data;
00533 
00534         g_free(server);
00535 
00536         list = g_list_next(list);
00537     }
00538 
00539     g_list_free(config->servers);
00540     config->servers = NULL;
00541 
00542     // Try to load the config file
00543     filename = g_build_filename(g_get_user_config_dir(), "NNTPGrab", "nntpgrab.conf", NULL);
00544     keyfile = g_key_file_new();
00545     if (!g_key_file_load_from_file(keyfile, filename, G_KEY_FILE_NONE, &err)) {
00546         char *tmp;
00547 
00548         if (errmsg) {
00549             *errmsg = g_strdup_printf(_("configuration_load(): Error while opening file '%s'\n%s"), filename, err->message);
00550         }
00551 
00552         g_free(filename);
00553         g_error_free(err);
00554         g_key_file_free(keyfile);
00555 
00556         // Set up sane defaults
00557 #ifdef WIN32
00558         tmp = g_build_path(G_DIR_SEPARATOR_S, g_get_user_special_dir(G_USER_DIRECTORY_DOCUMENTS), "NNTPGrab", "Downloads", NULL);
00559 #else
00560         tmp = g_build_path(G_DIR_SEPARATOR_S, g_get_home_dir(), "NNTPGrab", "Downloads", NULL);
00561 #endif
00562         strncpy(config->opts.download_directory, tmp, sizeof(config->opts.download_directory));
00563         g_mkdir_with_parents(tmp, 0700);
00564         g_free(tmp);
00565 
00566 #ifdef WIN32
00567         tmp = g_build_path(G_DIR_SEPARATOR_S, g_get_user_special_dir(G_USER_DIRECTORY_DOCUMENTS), "NNTPGrab", "Temp", NULL);
00568 #else
00569         tmp = g_build_path(G_DIR_SEPARATOR_S, g_get_home_dir(), "NNTPGrab", "Temp", NULL);
00570 #endif
00571         strncpy(config->opts.temp_directory, tmp, sizeof(config->opts.temp_directory));
00572         g_mkdir_with_parents(tmp, 0700);
00573         g_free(tmp);
00574 
00575         g_static_rw_lock_writer_unlock(&config->rwlock);
00576 
00577         return FALSE;
00578     }
00579 
00580     g_free(filename);
00581 
00582     groups = g_key_file_get_groups(keyfile, NULL);
00583     i = 0;
00584     while (groups[i]) {
00585         char *value;
00586         ConfigServer *server;
00587 
00588         if (!strcmp(groups[i], "options")) {
00589             char *tmp;
00590 
00591             tmp = g_key_file_get_string(keyfile, groups[i], "download_directory", NULL);
00592             if (tmp) {
00593                 strncpy(config->opts.download_directory, tmp, sizeof(config->opts.download_directory));
00594                 g_free(tmp);
00595             }
00596 
00597             tmp = g_key_file_get_string(keyfile, groups[i], "temp_directory", NULL);
00598             if (tmp) {
00599                 strncpy(config->opts.temp_directory, tmp, sizeof(config->opts.temp_directory));
00600                 g_free(tmp);
00601             }
00602 
00603             config->opts.enable_intelligent_par2_downloading = g_key_file_get_boolean(keyfile, groups[i], "enable_intelligent_par2_downloading", NULL);
00604 
00605             i++;
00606             continue;
00607         }
00608 
00609         server = g_slice_new(ConfigServer);
00610 
00611         strncpy(server->servername, groups[i], sizeof(server->servername));
00612 
00613         value = g_key_file_get_string(keyfile, groups[i], "hostname", NULL);
00614         if (!value) {
00615             g_print(_("No hostname could be found for servername '%s'. Ignoring server\n"), groups[i]);
00616             i++;
00617             continue;
00618         }
00619 
00620         strncpy(server->hostname, value, sizeof(server->hostname));
00621         g_free(value);
00622 
00623         server->port = g_key_file_get_integer(keyfile, groups[i], "port", NULL);
00624 
00625         value = g_key_file_get_string(keyfile, groups[i], "username", NULL);
00626         if (value) {
00627             strncpy(server->username, value, sizeof(server->username));
00628             g_free(value);
00629         }
00630 
00631         value = g_key_file_get_string(keyfile, groups[i], "password", NULL);
00632         if (value) {
00633             strncpy(server->password, value, sizeof(server->password));
00634             g_free(value);
00635         }
00636 
00637         server->max_threads = g_key_file_get_integer(keyfile, groups[i], "max_threads", NULL);
00638         server->use_ssl = g_key_file_get_boolean(keyfile, groups[i], "use_ssl", NULL);
00639 
00640         // backwards compatibility
00641         if (!g_key_file_has_key(keyfile, groups[i], "priority", NULL)) {
00642             server->priority = SERVER_PRIORITY_NORMAL;
00643         } else {
00644             server->priority = g_key_file_get_integer(keyfile, groups[i], "priority", NULL);
00645         }
00646 
00647         if (!g_key_file_has_key(keyfile, groups[i], "enabled", NULL)) {
00648             server->enabled = TRUE;
00649         } else {
00650             server->enabled = g_key_file_get_boolean(keyfile, groups[i], "enabled", NULL);
00651         }
00652 
00653         config->servers = g_list_append(config->servers, server);
00654 
00655         i++;
00656     }
00657 
00658     g_strfreev(groups);
00659 
00660     g_key_file_free(keyfile);
00661 
00662     // Do we have sane values for the download and temp directory ?
00663 #ifdef WIN32
00664     if (strlen(config->opts.download_directory) == 2) {
00665         config->opts.download_directory[2] = '\\';
00666         config->opts.download_directory[3] = '\0';
00667     }
00668 
00669     if (strlen(config->opts.temp_directory) == 2) {
00670         config->opts.temp_directory[2] = '\\';
00671         config->opts.temp_directory[3] = '\0';
00672     }
00673 #endif
00674 
00675     if (!g_file_test(config->opts.download_directory, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
00676         char *tmp;
00677 
00678 #ifdef WIN32
00679         tmp = g_build_path(G_DIR_SEPARATOR_S, g_get_user_special_dir(G_USER_DIRECTORY_DOCUMENTS), "NNTPGrab", "Downloads", NULL);
00680 #else
00681         tmp = g_build_path(G_DIR_SEPARATOR_S, g_get_home_dir(), "NNTPGrab", "Downloads", NULL);
00682 #endif
00683         strncpy(config->opts.download_directory, tmp, sizeof(config->opts.download_directory));
00684         g_mkdir_with_parents(tmp, 0700);
00685         g_free(tmp);
00686     }
00687 
00688     if (!g_file_test(config->opts.temp_directory, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
00689         char *tmp;
00690 
00691 #ifdef WIN32
00692         tmp = g_build_path(G_DIR_SEPARATOR_S, g_get_user_special_dir(G_USER_DIRECTORY_DOCUMENTS), "NNTPGrab", "Temp", NULL);
00693 #else
00694         tmp = g_build_path(G_DIR_SEPARATOR_S, g_get_home_dir(), "NNTPGrab", "Temp", NULL);
00695 #endif
00696         strncpy(config->opts.temp_directory, tmp, sizeof(config->opts.temp_directory));
00697         g_mkdir_with_parents(tmp, 0700);
00698         g_free(tmp);
00699     }
00700 
00701     g_static_rw_lock_writer_unlock(&config->rwlock);
00702 
00703     // Notify listeners that the configuration has changed
00704     g_signal_emit (config, signals[CONFIG_CHANGED_SIGNAL], 0, CONFIG_CHANGED_SERVER_ADDED | CONFIG_CHANGED_SERVER_DELETED);
00705 
00706     return TRUE;
00707 }
00708 
00716 gboolean
00717 configuration_save(Configuration *obj, char **errmsg)
00718 {
00719     Configuration *config = CONFIGURATION(obj);
00720     GKeyFile *keyfile;
00721     GError *err = NULL;
00722     char *filename;
00723     char *dirname;
00724     char *contents;
00725     GList *list;
00726 
00727     g_static_rw_lock_reader_lock(&config->rwlock);
00728 
00729     keyfile = g_key_file_new();
00730 
00731     g_key_file_set_string(keyfile, "options", "download_directory", config->opts.download_directory);
00732     g_key_file_set_string(keyfile, "options", "temp_directory", config->opts.temp_directory);
00733     g_key_file_set_boolean(keyfile, "options", "enable_intelligent_par2_downloading", config->opts.enable_intelligent_par2_downloading);
00734 
00735     list = config->servers;
00736     while (list) {
00737         ConfigServer *server = list->data;
00738 
00739         g_key_file_set_string(keyfile, server->servername, "hostname", server->hostname);
00740         g_key_file_set_integer(keyfile, server->servername, "port", server->port);
00741         g_key_file_set_string(keyfile, server->servername, "username", server->username);
00742         g_key_file_set_string(keyfile, server->servername, "password", server->password);
00743         g_key_file_set_integer(keyfile, server->servername, "max_threads", server->max_threads);
00744         g_key_file_set_boolean(keyfile, server->servername, "use_ssl", server->use_ssl);
00745         g_key_file_set_integer(keyfile, server->servername, "priority", server->priority);
00746         g_key_file_set_boolean(keyfile, server->servername, "enabled", server->enabled);
00747 
00748         list = g_list_next(list);
00749     }
00750 
00751     contents = g_key_file_to_data(keyfile, NULL, &err);
00752     if (!contents) {
00753         if (errmsg) {
00754             *errmsg = g_strdup(err->message);
00755         }
00756 
00757         g_error_free(err);
00758         g_free(contents);
00759         g_key_file_free(keyfile);
00760         g_static_rw_lock_reader_unlock(&config->rwlock);
00761 
00762         return FALSE;
00763     }
00764 
00765     // Create the folder ~/.config/NNTPGrab if it didn't exist already
00766     dirname = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), "NNTPGrab", NULL);
00767     g_mkdir_with_parents(dirname, 0700);
00768     g_free(dirname);
00769 
00770     filename = g_build_filename(g_get_user_config_dir(), "NNTPGrab", "nntpgrab.conf", NULL);
00771 
00772     if (!g_file_set_contents(filename, contents, -1, &err)) {
00773         if (errmsg) {
00774             *errmsg = g_strdup_printf(_("configuration_save(): Error while opening file '%s'\n%s"), filename, err->message);
00775         }
00776 
00777         g_error_free(err);
00778         g_free(contents);
00779         g_free(filename);
00780         g_key_file_free(keyfile);
00781         g_static_rw_lock_reader_unlock(&config->rwlock);
00782 
00783         return FALSE;
00784     }
00785 
00786     g_free(contents);
00787     g_free(filename);
00788     g_key_file_free(keyfile);
00789     g_static_rw_lock_reader_unlock(&config->rwlock);
00790 
00791     return TRUE;
00792 }
00793 
00794 static gint
00795 sort_folders_func(gconstpointer a, gconstpointer b)
00796 {
00797     const ConfigFolder *folderA = a;
00798     const ConfigFolder *folderB = b;
00799 
00800     if (a == NULL) {
00801         return 1;
00802     }
00803 
00804     if (b == NULL) {
00805         return 1;
00806     }
00807 
00808     return g_strcasecmp(folderA->folder, folderB->folder);
00809 }
00810 
00820 gboolean
00821 configuration_get_folder_listing(Configuration *obj, const char *parent, GList **folders)
00822 {
00823     GDir *dir;
00824     const char *filename;
00825 #ifdef WIN32
00826     char *tmp;
00827 #endif
00828 
00829     g_assert(folders);
00830 
00831     *folders = NULL;
00832 
00833     if (!parent) {
00834 #ifdef WIN32
00835         DWORD logicalDrives = GetLogicalDrives() 00836         int i = 1;
00837         char driveLetter = 'A';
00838 
00839         while(driveLetter 'Z') {
00840             char *path;
00841 
00842             if(logicalDrives & (int)pow(2,i)) {
00843                 GDir *dir;
00844                 ConfigFolder *folder = g_slice_new0(ConfigFolder);
00845 
00846                 path = g_strdup_printf("%c:\\", driveLetter);
00847 
00848 #ifdef WIN32
00849                 // Prevent the message 'No disk in drive' by checking via another method if
00850                 // the given path is reachable
00851                 if (!PathFileExistsA(path)) {
00852                     i++;
00853                     driveLetter++;
00854                     g_free(folder);
00855                     g_free(path);
00856                     continue;
00857                 }
00858 #endif
00859 
00860                 dir = g_dir_open(path, 0, NULL);
00861 
00862                 folder->has_subfolders = FALSE;
00863 
00864                 if (dir) {
00865                     const char *filename;
00866                     while ((filename = g_dir_read_name(dir))) {
00867                         char *path2 = g_build_filename(path, filename, NULL);
00868                         if (g_file_test(path2, G_FILE_TEST_IS_DIR)) {
00869                             folder->has_subfolders = TRUE;
00870                         }
00871                         g_free(path2);
00872                     }
00873                     g_dir_close(dir);
00874                 }
00875 
00876                 // Strip the \ character from the path
00877                 path[strlen(path) - 1] = '\0';
00878                 strncpy(folder->folder, path, sizeof(folder->folder) - 1);
00879 
00880                 *folders = g_list_append(*folders, folder);
00881 
00882                 g_free(path);
00883             }
00884 
00885             i++;
00886             driveLetter++;
00887         }
00888 
00889         return TRUE;
00890 #else
00891         ConfigFolder *folder = g_slice_new0(ConfigFolder);
00892         folder->has_subfolders = TRUE;      // There's no need to test this as there is always a root directory containing subdirectories
00893         folder->folder[0] = '/';
00894         folder->folder[1] = '\0';
00895         *folders = g_list_append(*folders, folder);
00896         return TRUE;
00897 #endif
00898     }
00899 
00900 #ifdef WIN32
00901     if (strlen(parent) == 2) {
00902         tmp = g_strdup_printf("%s\\", parent);
00903     } else {
00904         tmp = g_strdup(parent);
00905     }
00906     dir = g_dir_open(tmp, 0, NULL);
00907     g_free(tmp);
00908 #else
00909     dir = g_dir_open(parent, 0, NULL);
00910 #endif
00911     if (!dir) {
00912         return FALSE;
00913     }
00914 
00915     while ((filename = g_dir_read_name(dir))) {
00916         // Is this a directory ?
00917         char *path = g_build_filename(parent, filename, NULL);
00918         if (g_file_test(path, G_FILE_TEST_IS_DIR)) {
00919             GDir *dir2 = g_dir_open(path, 0, NULL);
00920             if (dir2) {
00921                 ConfigFolder *folder = g_slice_new0(ConfigFolder);
00922                 const char *filename2;
00923 
00924                 folder->has_subfolders = FALSE;
00925                 while ((filename2 = g_dir_read_name(dir2))) {
00926                     char *path2 = g_build_filename(parent, filename, filename2, NULL);
00927                     if (g_file_test(path2, G_FILE_TEST_IS_DIR)) {
00928                         folder->has_subfolders = TRUE;
00929                         g_free(path2);
00930                         break;
00931                     }
00932                     g_free(path2);
00933                 }
00934                 g_dir_close(dir2);
00935 
00936                 strncpy(folder->folder, filename, sizeof(folder->folder) - 1);
00937 
00938                 *folders = g_list_append(*folders, folder);
00939             }
00940         }
00941         g_free(path);
00942     }
00943 
00944     g_dir_close(dir);
00945 
00946     *folders = g_list_sort(*folders, sort_folders_func);
00947 
00948     return TRUE;
00949 }
00950 
00951 void
00952 configuration_free_folder_listing(Configuration *obj, GList *folders)
00953 {
00954     GList *list = folders;
00955     while (list) {
00956         g_slice_free(ConfigFolder, list->data);
00957         list = g_list_next(list);
00958     }
00959     g_list_free(folders);
00960 }

Generated on Sun Oct 12 01:45:29 2008 for NNTPGrab by  1.5.4