* 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
* 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"
#define SMILEYS_DEFAULT_FOLDER "custom_smiley"
#define SMILEYS_INDEX_FILE "smileys.xml"
static gchar *smileys_dir;
static gchar *smileys_index;
static PurpleSmileyList *smileys_list;
static gboolean disable_write = FALSE;
/*******************************************************************************
******************************************************************************/
purple_smiley_custom_load(void)
PurpleXmlNode *root_node, *profile_node, *smileyset_node, *smiley_node;
if (!g_file_test(smileys_index, G_FILE_TEST_EXISTS))
basename = g_path_get_basename(smileys_index);
dirname = g_path_get_dirname(smileys_index);
root_node = purple_xmlnode_from_file(dirname, basename,
"custom smileys index", "smiley-custom");
g_return_if_fail(root_node);
profile_node = purple_xmlnode_get_child(root_node, "profile");
purple_xmlnode_free(root_node);
g_return_if_fail(profile_node);
smileyset_node = purple_xmlnode_get_child(profile_node, "smiley_set");
purple_xmlnode_free(root_node);
g_return_if_fail(smileyset_node);
smiley_node = purple_xmlnode_get_child(smileyset_node, "smiley");
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) {
gchar *file_path = g_build_filename(
smileys_dir, file_name, NULL);
smiley = purple_smiley_new(shortcut, file_path);
if (purple_smiley_list_add(smileys_list, smiley)) {
purple_debug_warning("smiley-custom",
"Couldn't add '%s' smiley", shortcut);
smiley_node = purple_xmlnode_get_next_twin(smiley_node);
purple_xmlnode_free(root_node);
purple_debug_info("smiley-custom", "Loaded %d custom smiley(s)",
PurpleXmlNode *root_node, *profile_node, *smileyset_node;
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);
smileys = purple_smiley_list_get_all(smileys_list);
for (it = smileys; it; it = g_list_next(it)) {
PurpleSmiley *smiley = PURPLE_SMILEY(it->data);
PurpleXmlNode *smiley_node;
smiley_node = purple_xmlnode_new("smiley");
purple_xmlnode_insert_child(smileyset_node, smiley_node);
purple_xmlnode_set_attrib(smiley_node, "shortcut",
purple_smiley_get_shortcut(smiley));
basename = g_path_get_basename(purple_image_get_path(
purple_xmlnode_set_attrib(smiley_node, "filename", basename);
purple_smiley_custom_save(void)
PurpleXmlNode *root_node;
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);
purple_xmlnode_free(root_node);
purple_debug_error("smiley-custom",
"Error writting custom smileys xml file");
purple_smiley_custom_img_checksum(PurpleImage *img)
g_return_val_if_fail(PURPLE_IS_IMAGE(img), NULL);
return g_compute_checksum_for_data(G_CHECKSUM_SHA1,
purple_image_get_data(img),
purple_image_get_data_size(img));
/*******************************************************************************
******************************************************************************/
purple_smiley_custom_add(PurpleImage *img, const gchar *shortcut)
PurpleSmiley *existing_smiley, *smiley;
gchar *checksum, *file_path;
g_return_val_if_fail(PURPLE_IS_IMAGE(img), NULL);
existing_smiley = purple_smiley_list_get_by_shortcut(
purple_smiley_custom_remove(existing_smiley);
checksum = purple_smiley_custom_img_checksum(img);
file_ext = purple_image_get_extension(img);
if (file_ext == NULL || g_strcmp0("icon", file_ext) == 0) {
purple_debug_warning("smiley-custom", "Invalid image type");
g_snprintf(file_name, sizeof(file_name), "%s.%s", checksum, file_ext);
file_path = g_build_filename(smileys_dir, file_name, NULL);
if (!purple_image_save(img, file_path)) {
purple_debug_error("smiley-custom", "Failed writing smiley "
smiley = purple_smiley_new(shortcut, file_path);
succ = purple_smiley_list_add(smileys_list, smiley);
purple_debug_error("smiley-custom", "Failed adding a smiley");
purple_smiley_custom_save();
purple_smiley_custom_remove(PurpleSmiley *smiley)
PurpleSmiley *existing_smiley;
const gchar *smiley_shortcut, *path;
GList *other_smileys, *it;
g_return_if_fail(PURPLE_IS_SMILEY(smiley));
smiley_shortcut = purple_smiley_get_shortcut(smiley);
existing_smiley = purple_smiley_list_get_by_shortcut(
smileys_list, smiley_shortcut);
if (existing_smiley == NULL)
if (existing_smiley != smiley) {
purple_debug_warning("smiley-custom", "Smiley is not in store");
purple_smiley_list_remove(smileys_list, smiley);
path = purple_image_get_path(PURPLE_IMAGE(smiley));
other_smileys = purple_smiley_list_get_unique(smileys_list);
for (it = other_smileys; it; it = g_list_next(it)) {
PurpleSmiley *other = it->data;
const gchar *other_path = purple_image_get_path(PURPLE_IMAGE(other));
if (g_strcmp0(other_path, path) == 0) {
g_list_free(other_smileys);
purple_smiley_custom_save();
purple_smiley_custom_get_list(void)
/*******************************************************************************
* Custom smiley subsystem
******************************************************************************/
_purple_smiley_custom_init(void)
smileys_dir = g_build_filename(purple_data_dir(),
SMILEYS_DEFAULT_FOLDER, NULL);
smileys_index = g_build_filename(purple_config_dir(),
SMILEYS_INDEX_FILE, NULL);
smileys_list = purple_smiley_list_new();
ret = g_mkdir(smileys_dir, S_IRUSR | S_IWUSR | S_IXUSR);
if (ret != 0 && errno != EEXIST) {
purple_debug_error("smiley-custom", "Failed creating custom "
"smileys directory: %s (%d)", g_strerror(errno), errno);
purple_smiley_custom_load();
_purple_smiley_custom_uninit(void)
g_object_unref(smileys_list);