pidgin/pidgin

Merged default into xdg-dirs
xdg-dirs
2016-10-02, Arkadiy Illarionov
d92586bbada9
Merged default into xdg-dirs
--- a/libpurple/buddyicon.c Thu Sep 22 22:24:27 2016 +0000
+++ b/libpurple/buddyicon.c Sun Oct 02 07:01:19 2016 +0300
@@ -1094,8 +1094,8 @@
g_free, NULL);
pointer_icon_cache = g_hash_table_new(g_direct_hash, g_direct_equal);
- if (!cache_dir)
- cache_dir = g_build_filename(purple_user_dir(), "icons", NULL);
+ if (!cache_dir)
+ cache_dir = g_build_filename(purple_cache_dir(), "icons", NULL);
}
void
--- a/libpurple/log.c Thu Sep 22 22:24:27 2016 +0000
+++ b/libpurple/log.c Sun Oct 02 07:01:19 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);
g_free(acct_name);
@@ -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);
const gchar *protocol;
@@ -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);
GStatBuf st;
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);
int size;
GStatBuf st;
@@ -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);
gchar *name;
PurpleBlistNode *gnode, *cnode, *bnode;
--- a/libpurple/status.h Thu Sep 22 22:24:27 2016 +0000
+++ b/libpurple/status.h Sun Oct 02 07:01:19 2016 +0300
@@ -100,7 +100,7 @@
PURPLE_STATUS_MOOD,
/*< private >*/
- PURPLE_STATUS_NUM_PRIMITIVES,
+ PURPLE_STATUS_NUM_PRIMITIVES, /*< skip >*/
} PurpleStatusPrimitive;
#include "presence.h"
--- a/libpurple/theme-manager.c Thu Sep 22 22:24:27 2016 +0000
+++ b/libpurple/theme-manager.c Sun Oct 02 07:01:19 2016 +0300
@@ -147,7 +147,7 @@
purple_theme_manager_refresh(void)
{
gchar *path;
- const gchar *xdg;
+ const gchar *const *xdg_dirs;
gint i;
GSList *loaders = NULL;
@@ -159,27 +159,19 @@
purple_theme_manager_build_dir(loaders, path);
g_free(path);
- /* look for XDG_DATA_HOME. If we don't have it use ~/.local, and add it */
- if ((xdg = g_getenv("XDG_DATA_HOME")) != NULL)
- path = g_build_filename(xdg, "themes", NULL);
- else
- path = g_build_filename(purple_home_dir(), ".local", "themes", NULL);
-
+ /* look for XDG_DATA_HOME */
+ /* NOTE: will work on Windows, see g_get_user_data_dir() documentation */
+ path = g_build_filename(g_get_user_data_dir(), "themes", NULL);
purple_theme_manager_build_dir(loaders, path);
g_free(path);
/* now dig through XDG_DATA_DIRS and add those too */
- xdg = g_getenv("XDG_DATA_DIRS");
- if (xdg) {
- gchar **xdg_dirs = g_strsplit(xdg, G_SEARCHPATH_SEPARATOR_S, 0);
-
- for (i = 0; xdg_dirs[i]; i++) {
- path = g_build_filename(xdg_dirs[i], "themes", NULL);
- purple_theme_manager_build_dir(loaders, path);
- g_free(path);
- }
-
- g_strfreev(xdg_dirs);
+ /* NOTE: will work on Windows, see g_get_system_data_dirs() documentation */
+ xdg_dirs = g_get_system_data_dirs();
+ for (i = 0; xdg_dirs[i] != NULL; i++) {
+ path = g_build_filename(xdg_dirs[i], "themes", NULL);
+ purple_theme_manager_build_dir(loaders, path);
+ g_free(path);
}
g_slist_free(loaders);
--- a/libpurple/tls-certificate.c Thu Sep 22 22:24:27 2016 +0000
+++ b/libpurple/tls-certificate.c Sun Oct 02 07:01:19 2016 +0300
@@ -32,7 +32,7 @@
static gchar *
make_certificate_path(const gchar *id)
{
- return g_build_filename(purple_user_dir(),
+ return g_build_filename(purple_data_dir(),
"certificates", "tls",
id != NULL ? purple_escape_filename(id) : NULL,
NULL);
--- a/libpurple/util.c Thu Sep 22 22:24:27 2016 +0000
+++ b/libpurple/util.c Sun Oct 02 07:01:19 2016 +0300
@@ -41,10 +41,74 @@
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;
+static void
+move_to_xdg_base_dir(const char *purple_xdg_dir, char *subdir)
+{
+ char *xdg_dir;
+ gboolean xdg_dir_exists;
+
+ xdg_dir_exists = g_file_test(purple_xdg_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR);
+ if (!xdg_dir_exists) {
+ gint mkdir_res;
+
+ mkdir_res = purple_build_dir(purple_xdg_dir, (S_IRUSR | S_IWUSR | S_IXUSR));
+ if (mkdir_res == -1) {
+ purple_debug_error("util", "Error creating xdg directory %s: %s; failed migration\n",
+ purple_xdg_dir, g_strerror(errno));
+ return;
+ }
+ }
+
+ 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);
+ if (!xdg_dir_exists) {
+ char *old_dir;
+ gboolean old_dir_exists;
+
+ old_dir = g_build_filename(purple_user_dir(), subdir, NULL);
+ old_dir_exists = g_file_test(old_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR);
+
+ if (old_dir_exists) {
+ g_rename(old_dir, xdg_dir);
+ }
+
+ g_free(old_dir);
+ old_dir = NULL;
+ }
+
+ g_free(xdg_dir);
+ xdg_dir = NULL;
+
+ return;
+}
+
+/* If legacy directory for libpurple exists, move it to location following
+ * xdg base dir spec. https://developer.pidgin.im/ticket/10029
+ */
+static void
+migrate_to_xdg_base_dirs(void)
+{
+ const char *legacy_purple_dir;
+ gboolean dir_exists;
+
+ legacy_purple_dir = purple_user_dir();
+ dir_exists = g_file_test(legacy_purple_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR);
+ if (dir_exists) {
+ 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");
+ }
+
+ return;
+}
+
PurpleMenuAction *
purple_menu_action_new(const char *label, PurpleCallback callback, gpointer data,
GList *children)
@@ -144,6 +208,8 @@
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();
}
void
@@ -157,6 +223,15 @@
g_free(user_dir);
user_dir = NULL;
+ g_free(cache_dir);
+ cache_dir = NULL;
+
+ g_free(config_dir);
+ config_dir = NULL;
+
+ g_free(data_dir);
+ data_dir = NULL;
+
json_node_free(escape_js_node);
escape_js_node = NULL;
@@ -2924,6 +2999,48 @@
return user_dir;
}
+const char *
+purple_cache_dir(void)
+{
+ if (!cache_dir) {
+ if (!custom_user_dir) {
+ cache_dir = g_build_filename(g_get_user_cache_dir(), "purple", NULL);
+ } else {
+ cache_dir = g_build_filename(custom_user_dir, "cache", NULL);
+ }
+ }
+
+ return cache_dir;
+}
+
+const char *
+purple_config_dir(void)
+{
+ if (!config_dir) {
+ if (!custom_user_dir) {
+ config_dir = g_build_filename(g_get_user_config_dir(), "purple", NULL);
+ } else {
+ config_dir = g_build_filename(custom_user_dir, "config", NULL);
+ }
+ }
+
+ return config_dir;
+}
+
+const char *
+purple_data_dir(void)
+{
+ if (!data_dir) {
+ if (!custom_user_dir) {
+ data_dir = g_build_filename(g_get_user_data_dir(), "purple", NULL);
+ } else {
+ data_dir = g_build_filename(custom_user_dir, "data", NULL);
+ }
+ }
+
+ return data_dir;
+}
+
void purple_util_set_user_dir(const char *dir)
{
g_free(custom_user_dir);
@@ -2934,48 +3051,83 @@
custom_user_dir = NULL;
}
-int purple_build_dir (const char *path, int mode)
+int purple_build_dir(const char *path, int mode)
{
return g_mkdir_with_parents(path, mode);
}
+static gboolean
+purple_util_write_data_to_file_common(const char *dir, const char *filename, const char *data, gssize size)
+{
+ gchar *filename_full;
+ gboolean ret = FALSE;
+
+ g_return_val_if_fail(dir != NULL, FALSE);
+
+ purple_debug_misc("util", "Writing file %s to directory %s",
+ filename, dir);
+
+ /* Ensure the 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));
+ return FALSE;
+ }
+ }
+
+ 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);
+
+ g_free(filename_full);
+ return ret;
+}
+
+gboolean
+purple_util_write_data_to_file(const char *filename, const char *data, gssize size)
+{
+ const char *user_dir = purple_user_dir();
+ gboolean ret = purple_util_write_data_to_file_common(user_dir, filename, data, size);
+
+ return ret;
+}
+
+gboolean
+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);
+
+ return ret;
+}
+
+gboolean
+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);
+
+ return ret;
+}
+
+gboolean
+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);
+
+ return ret;
+}
+
/*
* This function is long and beautiful, like my--um, yeah. Anyway,
* it includes lots of error checking so as we don't overwrite
* people's settings if there is a problem writing the new values.
*/
gboolean
-purple_util_write_data_to_file(const char *filename, const char *data, gssize size)
-{
- const char *user_dir = purple_user_dir();
- gchar *filename_full;
- gboolean ret = FALSE;
-
- g_return_val_if_fail(user_dir != NULL, FALSE);
-
- purple_debug_misc("util", "Writing file %s to directory %s",
- filename, user_dir);
-
- /* 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));
- return FALSE;
- }
- }
-
- 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);
-
- g_free(filename_full);
- return ret;
-}
-
-gboolean
purple_util_write_data_to_file_absolute(const char *filename_full, const char *data, gssize size)
{
gchar *filename_temp;
--- a/libpurple/util.h Thu Sep 22 22:24:27 2016 +0000
+++ b/libpurple/util.h Sun Oct 02 07:01:19 2016 +0300
@@ -788,6 +788,42 @@
const char *purple_user_dir(void);
/**
+ * purple_cache_dir:
+ *
+ * Returns the purple cache directory according to XDG Base Directory Specification.
+ * This is usually ~/.cache/purple.
+ * If custom user dir was specified then this is cache
+ * sub-directory of DIR argument passed to -c option.
+ *
+ * Returns: The purple cache directory.
+ */
+const char *purple_cache_dir(void);
+
+/**
+ * purple_config_dir:
+ *
+ * Returns the purple configuration directory according to XDG Base Directory Specification.
+ * This is usually ~/.config/purple.
+ * If custom user dir was specified then this is config
+ * sub-directory of DIR argument passed to -c option.
+ *
+ * Returns: The purple configuration directory.
+ */
+const char *purple_config_dir(void);
+
+/**
+ * purple_data_dir:
+ *
+ * Returns the purple data directory according to XDG Base Directory Specification.
+ * This is usually ~/.local/share/purple.
+ * If custom user dir was specified then this is data
+ * sub-directory of DIR argument passed to -c option.
+ *
+ * Returns: The purple data directory.
+ */
+const char *purple_data_dir(void);
+
+/**
* purple_util_set_user_dir:
* @dir: The custom settings directory
*
@@ -828,6 +864,57 @@
gssize size);
/**
+ * purple_util_write_data_to_cache_file:
+ * @filename: The basename of the file to write in the purple_cache_dir.
+ * @data: A null-terminated string of data to write.
+ * @size: The size of the data to save. If data is
+ * null-terminated you can pass in -1.
+ *
+ * Write a string of data to a file of the given name in the Purple
+ * cache directory ($HOME/.cache/purple by default).
+ *
+ * See purple_util_write_data_to_file()
+ *
+ * Returns: TRUE if the file was written successfully. FALSE otherwise.
+ */
+gboolean
+purple_util_write_data_to_cache_file(const char *filename, const char *data, gssize size);
+
+/**
+ * purple_util_write_data_to_config_file:
+ * @filename: The basename of the file to write in the purple_config_dir.
+ * @data: A null-terminated string of data to write.
+ * @size: The size of the data to save. If data is
+ * null-terminated you can pass in -1.
+ *
+ * Write a string of data to a file of the given name in the Purple
+ * config directory ($HOME/.config/purple by default).
+ *
+ * See purple_util_write_data_to_file()
+ *
+ * Returns: TRUE if the file was written successfully. FALSE otherwise.
+ */
+gboolean
+purple_util_write_data_to_config_file(const char *filename, const char *data, gssize size);
+
+/**
+ * purple_util_write_data_to_data_file:
+ * @filename: The basename of the file to write in the purple_data_dir.
+ * @data: A null-terminated string of data to write.
+ * @size: The size of the data to save. If data is
+ * null-terminated you can pass in -1.
+ *
+ * Write a string of data to a file of the given name in the Purple
+ * data directory ($HOME/.local/share/purple by default).
+ *
+ * See purple_util_write_data_to_file()
+ *
+ * Returns: TRUE if the file was written successfully. FALSE otherwise.
+ */
+gboolean
+purple_util_write_data_to_data_file(const char *filename, const char *data, gssize size);
+
+/**
* purple_util_write_data_to_file_absolute:
* @filename_full: Filename to write to
* @data: A null-terminated string of data to write.
--- a/libpurple/xmlnode.c Thu Sep 22 22:24:27 2016 +0000
+++ b/libpurple/xmlnode.c Sun Oct 02 07:01:19 2016 +0300
@@ -821,7 +821,7 @@
}
PurpleXmlNode *
-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)
{
gchar *filename_full;
GError *error = NULL;
--- a/pidgin/gtklog.c Thu Sep 22 22:24:27 2016 +0000
+++ b/pidgin/gtklog.c Sun Oct 02 07:01:19 2016 +0300
@@ -192,7 +192,7 @@
if (log == NULL)
- logdir = g_build_filename(purple_user_dir(), "logs", NULL);
+ logdir = g_build_filename(purple_data_dir(), "logs", NULL);
else
logdir = purple_log_get_log_dir(log->type, log->name, log->account);