--- a/libpurple/buddyicon.c Fri Sep 23 09:23:25 2016 -0500
+++ b/libpurple/buddyicon.c Sun Sep 25 21:06:42 2016 +0300
@@ -1094,8 +1094,8 @@
pointer_icon_cache = g_hash_table_new(g_direct_hash, g_direct_equal);
- cache_dir = g_build_filename(purple_user_dir(), "icons", NULL);
+ cache_dir = g_build_filename(purple_cache_dir(), "icons", NULL); --- a/libpurple/log.c Fri Sep 23 09:23:25 2016 -0500
+++ b/libpurple/log.c Sun Sep 25 21:06:42 2016 +0300
@@ -360,7 +360,7 @@
target = purple_escape_filename(purple_normalize(account, name));
- dir = g_build_filename(purple_user_dir(), "logs", protocol_name, acct_name, target, NULL);
+ dir = g_build_filename(purple_data_dir(), "logs", protocol_name, acct_name, target, NULL); @@ -1078,7 +1078,7 @@
* functions because they use the same directory structure. */
static void log_get_log_sets_common(GHashTable *sets)
- gchar *log_path = g_build_filename(purple_user_dir(), "logs", NULL);
+ gchar *log_path = g_build_filename(purple_data_dir(), "logs", NULL); GDir *log_dir = g_dir_open(log_path, 0, NULL);
@@ -1585,7 +1585,7 @@
static GList *old_logger_list(PurpleLogType type, const char *sn, PurpleAccount *account)
char *logfile = g_strdup_printf("%s.log", purple_normalize(account, sn));
- char *pathstr = g_build_filename(purple_user_dir(), "logs", logfile, NULL);
+ char *pathstr = g_build_filename(purple_data_dir(), "logs", logfile, NULL); PurpleStringref *pathref = purple_stringref_new(pathstr);
time_t log_last_modified;
@@ -1846,7 +1846,7 @@
static int old_logger_total_size(PurpleLogType type, const char *name, PurpleAccount *account)
char *logfile = g_strdup_printf("%s.log", purple_normalize(account, name));
- char *pathstr = g_build_filename(purple_user_dir(), "logs", logfile, NULL);
+ char *pathstr = g_build_filename(purple_data_dir(), "logs", logfile, NULL); @@ -1898,7 +1898,7 @@
static void old_logger_get_log_sets(PurpleLogSetCallback cb, GHashTable *sets)
- char *log_path = g_build_filename(purple_user_dir(), "logs", NULL);
+ char *log_path = g_build_filename(purple_data_dir(), "logs", NULL); GDir *log_dir = g_dir_open(log_path, 0, NULL);
PurpleBlistNode *gnode, *cnode, *bnode;
--- a/libpurple/theme-manager.c Fri Sep 23 09:23:25 2016 -0500
+++ b/libpurple/theme-manager.c Sun Sep 25 21:06:42 2016 +0300
@@ -160,7 +160,7 @@
/* look for XDG_DATA_HOME. If we don't have it use ~/.local, and add it */
- if ((xdg = g_getenv("XDG_DATA_HOME")) != NULL)
+ if ((xdg = g_getenv("XDG_DATA_HOME")) != NULL) /* XXX: change to g_get_user_data_dir() ? */ path = g_build_filename(xdg, "themes", NULL);
path = g_build_filename(purple_home_dir(), ".local", "themes", NULL);
@@ -169,7 +169,7 @@
/* now dig through XDG_DATA_DIRS and add those too */
- xdg = g_getenv("XDG_DATA_DIRS");
+ xdg = g_getenv("XDG_DATA_DIRS"); /* XXX: change to g_get_system_data_dir() ? */ gchar **xdg_dirs = g_strsplit(xdg, G_SEARCHPATH_SEPARATOR_S, 0);
--- a/libpurple/tls-certificate.c Fri Sep 23 09:23:25 2016 -0500
+++ b/libpurple/tls-certificate.c Sun Sep 25 21:06:42 2016 +0300
@@ -32,7 +32,7 @@
make_certificate_path(const gchar *id)
- return g_build_filename(purple_user_dir(),
+ return g_build_filename(purple_data_dir(), id != NULL ? purple_escape_filename(id) : NULL,
--- a/libpurple/util.c Fri Sep 23 09:23:25 2016 -0500
+++ b/libpurple/util.c Sun Sep 25 21:06:42 2016 +0300
@@ -41,10 +41,76 @@
static char *custom_user_dir = NULL;
static char *user_dir = NULL;
+static char *cache_dir = NULL; +static char *config_dir = NULL; +static char *data_dir = NULL; static JsonNode *escape_js_node = NULL;
static JsonGenerator *escape_js_gen = NULL;
+/* If legacy directory for libpurple exists, move it to location following +* xdg base dir spec. https://developer.pidgin.im/ticket/10029 */ +move_to_xdg_base_dir(const char *purple_xdg_dir, char *subdir) + gboolean xdg_dir_exists; + xdg_dir_exists = g_file_test(purple_xdg_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR); + mkdir_res = g_mkdir_with_parents(purple_xdg_dir, (S_IRUSR | S_IWUSR | S_IXUSR)); + purple_debug_error("util", "Error creating xdg directory %s: %s; failed migration\n", + purple_xdg_dir, g_strerror(errno)); + xdg_dir = g_build_filename(purple_xdg_dir, subdir, NULL); + xdg_dir_exists = g_file_test(xdg_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR); + gboolean old_dir_exists; + old_dir = g_build_filename(purple_home_dir(), ".purple", subdir, NULL); + old_dir_exists = g_file_test(old_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR); + g_rename(old_dir, xdg_dir); +migrate_to_xdg_base_dirs(void) + char *legacy_purple_dir; + legacy_purple_dir = g_build_filename(purple_home_dir(), ".purple", NULL); + dir_exists = g_file_test(legacy_purple_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR); + move_to_xdg_base_dir(purple_data_dir(), "certificates"); + move_to_xdg_base_dir(purple_cache_dir(), "icons"); + move_to_xdg_base_dir(purple_data_dir(), "logs"); + g_free(legacy_purple_dir); + legacy_purple_dir = NULL; purple_menu_action_new(const char *label, PurpleCallback callback, gpointer data,
@@ -144,6 +210,7 @@
escape_js_node = json_node_new(JSON_NODE_VALUE);
escape_js_gen = json_generator_new();
json_node_set_boolean(escape_js_node, FALSE);
+ migrate_to_xdg_base_dirs(); @@ -157,6 +224,15 @@
json_node_free(escape_js_node);
@@ -2924,6 +3000,36 @@
+ cache_dir = g_build_filename(g_get_user_cache_dir(), "purple", NULL); + config_dir = g_build_filename(g_get_user_config_dir(), "purple", NULL); + data_dir = g_build_filename(g_get_user_data_dir(), "purple", NULL); void purple_util_set_user_dir(const char *dir)
@@ -2939,6 +3045,36 @@
return g_mkdir_with_parents(path, mode);
+purple_util_write_data_to_file_common(const char *dir, const char *filename, const char *data, gssize size) + g_return_val_if_fail(dir != NULL, FALSE); + purple_debug_misc("util", "Writing file %s to directory %s", + /* Ensure the user directory exists */ + if (!g_file_test(dir, G_FILE_TEST_IS_DIR)) + if (g_mkdir(dir, S_IRUSR | S_IWUSR | S_IXUSR) == -1) + purple_debug_error("util", "Error creating directory %s: %s\n", + dir, g_strerror(errno)); + filename_full = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dir, filename); + ret = purple_util_write_data_to_file_absolute(filename_full, data, size); * This function is long and beautiful, like my--um, yeah. Anyway,
* it includes lots of error checking so as we don't overwrite
@@ -2948,30 +3084,35 @@
purple_util_write_data_to_file(const char *filename, const char *data, gssize size)
const char *user_dir = purple_user_dir();
- g_return_val_if_fail(user_dir != NULL, FALSE);
- purple_debug_misc("util", "Writing file %s to directory %s",
- /* Ensure the user directory exists */
- if (!g_file_test(user_dir, G_FILE_TEST_IS_DIR))
- if (g_mkdir(user_dir, S_IRUSR | S_IWUSR | S_IXUSR) == -1)
- purple_debug_error("util", "Error creating directory %s: %s\n",
- user_dir, g_strerror(errno));
- filename_full = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", user_dir, filename);
- ret = purple_util_write_data_to_file_absolute(filename_full, data, size);
+ gboolean ret = purple_util_write_data_to_file_common(user_dir, filename, data, size); +purple_util_write_data_to_cache_file(const char *filename, const char *data, gssize size) + const char *cache_dir = purple_cache_dir(); + gboolean ret = purple_util_write_data_to_file_common(cache_dir, filename, data, size); +purple_util_write_data_to_config_file(const char *filename, const char *data, gssize size) + const char *config_dir = purple_cache_dir(); + gboolean ret = purple_util_write_data_to_file_common(config_dir, filename, data, size); +purple_util_write_data_to_data_file(const char *filename, const char *data, gssize size) + const char *data_dir = purple_cache_dir(); + gboolean ret = purple_util_write_data_to_file_common(data_dir, filename, data, size); --- a/libpurple/util.h Fri Sep 23 09:23:25 2016 -0500
+++ b/libpurple/util.h Sun Sep 25 21:06:42 2016 +0300
@@ -788,6 +788,42 @@
const char *purple_user_dir(void);
+ * Returns the purple cache directory according to XDG Base Directory Specification. + * This is usually ~/.cache/purple + * See purple_home_dir() + * Returns: The purple cache directory. +const char *purple_cache_dir(void); + * Returns the purple configuration directory according to XDG Base Directory Specification. + * This is usually ~/.config/purple + * See purple_home_dir() + * Returns: The purple configuration directory. +const char *purple_config_dir(void); + * Returns the purple data directory according to XDG Base Directory Specification. + * This is usually ~/.local/share/purple + * See purple_home_dir() + * Returns: The purple data directory. +const char *purple_data_dir(void); * purple_util_set_user_dir:
* @dir: The custom settings directory
--- a/libpurple/xmlnode.c Fri Sep 23 09:23:25 2016 -0500
+++ b/libpurple/xmlnode.c Sun Sep 25 21:06:42 2016 +0300
@@ -821,7 +821,7 @@
-purple_xmlnode_from_file(const char *dir,const char *filename, const char *description, const char *process)
+purple_xmlnode_from_file(const char *dir, const char *filename, const char *description, const char *process) --- a/pidgin/gtklog.c Fri Sep 23 09:23:25 2016 -0500
+++ b/pidgin/gtklog.c Sun Sep 25 21:06:42 2016 +0300
@@ -192,7 +192,7 @@
- logdir = g_build_filename(purple_user_dir(), "logs", NULL);
+ logdir = g_build_filename(purple_data_dir(), "logs", NULL); logdir = purple_log_get_log_dir(log->type, log->name, log->account);