/dev/tomkiewicz/new-smileys: 2aa79f05247e: Custom smileys storage

Tomasz Wasilczyk twasilczyk at pidgin.im
Tue Apr 1 19:08:26 EDT 2014


Changeset: 2aa79f05247ea0369bc638ceff423e720b147993
Author:	 Tomasz Wasilczyk <twasilczyk at pidgin.im>
Date:	 2014-04-02 01:08 +0200
Branch:	 default
URL: https://hg.pidgin.im/dev/tomkiewicz/new-smileys/rev/2aa79f05247e

Description:

Custom smileys storage

diffstat:

 libpurple/Makefile.am     |    2 +
 libpurple/core.c          |    7 +-
 libpurple/imgstore.h      |    3 +-
 libpurple/smiley-custom.c |  284 ++++++++++++++++++++++++++++++++++++++++++++++
 libpurple/smiley-custom.h |   46 +++++++
 5 files changed, 338 insertions(+), 4 deletions(-)

diffs (truncated from 403 to 300 lines):

diff --git a/libpurple/Makefile.am b/libpurple/Makefile.am
--- a/libpurple/Makefile.am
+++ b/libpurple/Makefile.am
@@ -101,6 +101,7 @@ purple_coresources = \
 	savedstatuses.c \
 	server.c \
 	signals.c \
+	smiley-custom.c \
 	smiley-list.c \
 	smiley-parser.c \
 	smiley-theme.c \
@@ -179,6 +180,7 @@ purple_coreheaders = \
 	savedstatuses.h \
 	server.h \
 	signals.h \
+	smiley-custom.h \
 	smiley-list.h \
 	smiley-parser.h \
 	smiley-theme.h \
diff --git a/libpurple/core.c b/libpurple/core.c
--- a/libpurple/core.c
+++ b/libpurple/core.c
@@ -41,6 +41,7 @@
 #include "proxy.h"
 #include "savedstatuses.h"
 #include "signals.h"
+#include "smiley-custom.h"
 #include "smiley-theme.h"
 #include "sound.h"
 #include "sound-theme-loader.h"
@@ -202,9 +203,8 @@ purple_core_init(const char *ui)
 	purple_xfers_init();
 	purple_idle_init();
 	purple_http_init();
-#if 0
-	purple_smileys_init();
-#endif
+	purple_smiley_custom_init();
+
 	/*
 	 * Call this early on to try to auto-detect our IP address and
 	 * hopefully save some time later.
@@ -257,6 +257,7 @@ purple_core_quit(void)
 
 	/* Save .xml files, remove signals, etc. */
 	purple_smiley_theme_uninit();
+	purple_smiley_custom_uninit();
 	purple_http_uninit();
 	purple_idle_uninit();
 	purple_pounces_uninit();
diff --git a/libpurple/imgstore.h b/libpurple/imgstore.h
--- a/libpurple/imgstore.h
+++ b/libpurple/imgstore.h
@@ -45,7 +45,8 @@
  */
 typedef struct _PurpleStoredImage PurpleStoredImage;
 
-#define PURPLE_TYPE_STORED_IMAGE  (purple_imgstore_get_type())
+#define PURPLE_TYPE_STORED_IMAGE (purple_imgstore_get_type())
+#define PURPLE_IS_STORED_IMAGE(image) (G_TYPE_CHECK_INSTANCE_TYPE((image), PURPLE_TYPE_STORED_IMAGE))
 
 G_BEGIN_DECLS
 
diff --git a/libpurple/smiley-custom.c b/libpurple/smiley-custom.c
new file mode 100644
--- /dev/null
+++ b/libpurple/smiley-custom.c
@@ -0,0 +1,284 @@
+/* purpleOB
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+
+#include "smiley-custom.h"
+
+#include "debug.h"
+
+#include <glib/gstdio.h>
+
+#define SMILEYS_DEFAULT_FOLDER "custom_smiley"
+#define SMILEYS_INDEX_FILE "smileys.xml"
+
+static gchar *smileys_dir;
+static gchar *smileys_index;
+
+static PurpleTrie *smileys_trie;
+static GHashTable *smileys_table;
+static gboolean disable_write = FALSE;
+
+/*******************************************************************************
+ * XML storage
+ ******************************************************************************/
+
+static void
+purple_smiley_custom_load(void)
+{
+	PurpleXmlNode *root_node, *profile_node, *smileyset_node, *smiley_node;
+	int got_smileys = 0;
+
+	if (!g_file_test(smileys_index, G_FILE_TEST_EXISTS))
+		return;
+
+	root_node = purple_xmlnode_from_file(g_path_get_dirname(smileys_index),
+		g_path_get_basename(smileys_index),
+		"custom smileys index", "smiley-custom");
+	g_return_if_fail(root_node);
+
+	profile_node = purple_xmlnode_get_child(root_node, "profile");
+	if (!profile_node) {
+		purple_xmlnode_free(root_node);
+		g_return_if_fail(profile_node);
+	}
+
+	smileyset_node = purple_xmlnode_get_child(profile_node, "smiley_set");
+	if (!smileyset_node) {
+		purple_xmlnode_free(root_node);
+		g_return_if_fail(smileyset_node);
+	}
+
+	smiley_node = purple_xmlnode_get_child(smileyset_node, "smiley");
+	while (smiley_node) {
+		const gchar *shortcut, *file_name;
+
+		shortcut = purple_xmlnode_get_attrib(smiley_node, "shortcut");
+		file_name = purple_xmlnode_get_attrib(smiley_node, "filename");
+
+		if (shortcut && file_name) {
+			PurpleSmiley *smiley;
+			gchar *file_path = g_build_filename(
+				smileys_dir, file_name, NULL);
+
+			got_smileys++;
+			smiley = purple_smiley_new(shortcut, file_path);
+			g_free(file_path);
+
+			g_hash_table_insert(smileys_table,
+				g_strdup(shortcut), smiley);
+		}
+
+		smiley_node = purple_xmlnode_get_next_twin(smiley_node);
+	}
+
+	purple_xmlnode_free(root_node);
+
+	purple_debug_info("smiley-custom", "Loaded %d custom smiley(s)",
+		got_smileys);
+}
+
+static PurpleXmlNode *
+smileys_to_xmlnode(void)
+{
+	PurpleXmlNode *root_node, *profile_node, *smileyset_node;
+	GHashTableIter it;
+	gpointer value;
+
+	root_node = purple_xmlnode_new("smileys");
+	purple_xmlnode_set_attrib(root_node, "version", "1.0");
+
+	profile_node = purple_xmlnode_new("profile");
+	purple_xmlnode_insert_child(root_node, profile_node);
+	purple_xmlnode_set_attrib(profile_node, "name", "Default");
+
+	smileyset_node = purple_xmlnode_new("smiley_set");
+	purple_xmlnode_insert_child(profile_node, smileyset_node);
+
+	g_hash_table_iter_init(&it, smileys_table);
+	while (g_hash_table_iter_next(&it, NULL, &value)) {
+		PurpleSmiley *smiley = PURPLE_SMILEY(value);
+		PurpleXmlNode *smiley_node;
+
+		smiley_node = purple_xmlnode_new("smiley");
+		purple_xmlnode_set_attrib(smiley_node, "shortcut",
+			purple_smiley_get_shortcut(smiley));
+		purple_xmlnode_set_attrib(smiley_node, "filename",
+			g_path_get_basename(purple_smiley_get_path(smiley)));
+	}
+
+	return root_node;
+}
+
+static void
+purple_smiley_custom_save(void)
+{
+	PurpleXmlNode *root_node;
+	gchar *data;
+	GError *error = NULL;
+
+	if (disable_write)
+		return;
+
+	root_node = smileys_to_xmlnode();
+	g_return_if_fail(root_node != NULL);
+
+	data = purple_xmlnode_to_formatted_str(root_node, NULL);
+	g_return_if_fail(data != NULL);
+
+	g_file_set_contents(smileys_index, data, -1, &error);
+
+	g_free(data);
+	purple_xmlnode_free(root_node);
+
+	if (error) {
+		purple_debug_error("smiley-custom",
+			"Error writting custom smileys xml file");
+	}
+}
+
+static gchar *
+purple_smiley_custom_img_checksum(PurpleStoredImage *img)
+{
+	g_return_val_if_fail(PURPLE_IS_STORED_IMAGE(img), NULL);
+
+	return g_compute_checksum_for_data(G_CHECKSUM_SHA1,
+		purple_imgstore_get_data(img),
+		purple_imgstore_get_size(img));
+}
+
+
+/*******************************************************************************
+ * API implementation
+ ******************************************************************************/
+
+PurpleSmiley *
+purple_smiley_custom_add(PurpleStoredImage *img, const gchar *shortcut)
+{
+	PurpleSmiley *existing_smiley, *smiley;
+	gchar *checksum, *file_path;
+	gchar file_name[256];
+	const gchar *file_ext;
+	GError *error = NULL;
+
+	g_return_val_if_fail(PURPLE_IS_STORED_IMAGE(img), NULL);
+
+	existing_smiley = g_hash_table_lookup(smileys_table, shortcut);
+
+	g_object_ref(img);
+
+	if (existing_smiley) {
+		disable_write = TRUE;
+		purple_smiley_custom_remove(existing_smiley);
+		disable_write = FALSE;
+	}
+
+	checksum = purple_smiley_custom_img_checksum(img);
+	file_ext = purple_imgstore_get_extension(img);
+	if (file_ext == NULL || g_strcmp0("icon", file_ext) == 0) {
+		purple_debug_warning("smiley-custom", "Invalid image type");
+		return NULL;
+	}
+
+	g_snprintf(file_name, sizeof(file_name), "%s.%s", checksum, file_ext);
+	file_path = g_build_filename(smileys_dir, file_name, NULL);
+
+	g_file_set_contents(file_path, purple_imgstore_get_data(img),
+		purple_imgstore_get_size(img), &error);
+
+	g_free(checksum);
+	g_object_unref(img);
+
+	if (error) {
+		purple_debug_error("smiley-custom", "Failed writing smiley "
+			"file %s: %s", file_path, error->message);
+		g_free(file_path);
+		return NULL;
+	}
+
+	smiley = purple_smiley_new(shortcut, file_path);
+	g_free(file_path);
+
+	g_hash_table_insert(smileys_table, g_strdup(shortcut), smiley);
+	purple_smiley_custom_save();
+
+	return smiley;
+}
+
+void
+purple_smiley_custom_remove(PurpleSmiley *smiley)
+{
+	PurpleSmiley *existing_smiley;
+	const gchar *smiley_shortcut;
+
+	g_return_if_fail(PURPLE_IS_SMILEY(smiley));
+
+	smiley_shortcut = purple_smiley_get_shortcut(smiley);



More information about the Commits mailing list