Merged default into xdg-dirs
[pidgin-git.git] / libpurple / smiley-custom.c
blob610bfa2bd02e3cc812b50961389addbade8fc416
1 /* purple
3 * Purple is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
5 * source distribution.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
22 #include "smiley-custom.h"
24 #include "debug.h"
25 #include "util.h"
27 #include <glib/gstdio.h>
28 #include <errno.h>
30 #define SMILEYS_DEFAULT_FOLDER "custom_smiley"
31 #define SMILEYS_INDEX_FILE "smileys.xml"
33 static gchar *smileys_dir;
34 static gchar *smileys_index;
36 static PurpleSmileyList *smileys_list;
37 static gboolean disable_write = FALSE;
39 /*******************************************************************************
40 * XML storage
41 ******************************************************************************/
43 static void
44 purple_smiley_custom_load(void)
46 PurpleXmlNode *root_node, *profile_node, *smileyset_node, *smiley_node;
47 gchar *basename;
48 gchar *dirname;
49 int got_smileys = 0;
51 if (!g_file_test(smileys_index, G_FILE_TEST_EXISTS))
52 return;
54 basename = g_path_get_basename(smileys_index);
55 dirname = g_path_get_dirname(smileys_index);
56 root_node = purple_xmlnode_from_file(dirname, basename,
57 "custom smileys index", "smiley-custom");
58 g_free(dirname);
59 g_free(basename);
61 g_return_if_fail(root_node);
63 profile_node = purple_xmlnode_get_child(root_node, "profile");
64 if (!profile_node) {
65 purple_xmlnode_free(root_node);
66 g_return_if_fail(profile_node);
69 smileyset_node = purple_xmlnode_get_child(profile_node, "smiley_set");
70 if (!smileyset_node) {
71 purple_xmlnode_free(root_node);
72 g_return_if_fail(smileyset_node);
75 smiley_node = purple_xmlnode_get_child(smileyset_node, "smiley");
76 while (smiley_node) {
77 const gchar *shortcut, *file_name;
79 shortcut = purple_xmlnode_get_attrib(smiley_node, "shortcut");
80 file_name = purple_xmlnode_get_attrib(smiley_node, "filename");
82 if (shortcut && file_name) {
83 PurpleSmiley *smiley;
84 gchar *file_path = g_build_filename(
85 smileys_dir, file_name, NULL);
87 smiley = purple_smiley_new(shortcut, file_path);
88 g_free(file_path);
90 if (purple_smiley_list_add(smileys_list, smiley)) {
91 got_smileys++;
92 } else {
93 purple_debug_warning("smiley-custom",
94 "Couldn't add '%s' smiley", shortcut);
96 g_object_unref(smiley);
99 smiley_node = purple_xmlnode_get_next_twin(smiley_node);
102 purple_xmlnode_free(root_node);
104 purple_debug_info("smiley-custom", "Loaded %d custom smiley(s)",
105 got_smileys);
108 static PurpleXmlNode *
109 smileys_to_xmlnode(void)
111 PurpleXmlNode *root_node, *profile_node, *smileyset_node;
112 GList *smileys, *it;
113 gchar *basename;
115 root_node = purple_xmlnode_new("smileys");
116 purple_xmlnode_set_attrib(root_node, "version", "1.0");
118 profile_node = purple_xmlnode_new("profile");
119 purple_xmlnode_insert_child(root_node, profile_node);
120 purple_xmlnode_set_attrib(profile_node, "name", "Default");
122 smileyset_node = purple_xmlnode_new("smiley_set");
123 purple_xmlnode_insert_child(profile_node, smileyset_node);
125 smileys = purple_smiley_list_get_all(smileys_list);
127 for (it = smileys; it; it = g_list_next(it)) {
128 PurpleSmiley *smiley = PURPLE_SMILEY(it->data);
129 PurpleXmlNode *smiley_node;
131 smiley_node = purple_xmlnode_new("smiley");
132 purple_xmlnode_insert_child(smileyset_node, smiley_node);
133 purple_xmlnode_set_attrib(smiley_node, "shortcut",
134 purple_smiley_get_shortcut(smiley));
135 basename = g_path_get_basename(purple_image_get_path(
136 PURPLE_IMAGE(smiley)));
137 purple_xmlnode_set_attrib(smiley_node, "filename", basename);
138 g_free(basename);
141 return root_node;
144 static void
145 purple_smiley_custom_save(void)
147 PurpleXmlNode *root_node;
148 gchar *data;
149 GError *error = NULL;
151 if (disable_write)
152 return;
154 root_node = smileys_to_xmlnode();
155 g_return_if_fail(root_node != NULL);
157 data = purple_xmlnode_to_formatted_str(root_node, NULL);
158 g_return_if_fail(data != NULL);
160 g_file_set_contents(smileys_index, data, -1, &error);
162 g_free(data);
163 purple_xmlnode_free(root_node);
165 if (error) {
166 purple_debug_error("smiley-custom",
167 "Error writting custom smileys xml file");
171 static gchar *
172 purple_smiley_custom_img_checksum(PurpleImage *img)
174 g_return_val_if_fail(PURPLE_IS_IMAGE(img), NULL);
176 return g_compute_checksum_for_data(G_CHECKSUM_SHA1,
177 purple_image_get_data(img),
178 purple_image_get_data_size(img));
182 /*******************************************************************************
183 * API implementation
184 ******************************************************************************/
186 PurpleSmiley *
187 purple_smiley_custom_add(PurpleImage *img, const gchar *shortcut)
189 PurpleSmiley *existing_smiley, *smiley;
190 gchar *checksum, *file_path;
191 gchar file_name[256];
192 const gchar *file_ext;
193 gboolean succ;
195 g_return_val_if_fail(PURPLE_IS_IMAGE(img), NULL);
197 existing_smiley = purple_smiley_list_get_by_shortcut(
198 smileys_list, shortcut);
200 g_object_ref(img);
202 if (existing_smiley) {
203 disable_write = TRUE;
204 purple_smiley_custom_remove(existing_smiley);
205 disable_write = FALSE;
208 checksum = purple_smiley_custom_img_checksum(img);
209 file_ext = purple_image_get_extension(img);
210 if (file_ext == NULL || g_strcmp0("icon", file_ext) == 0) {
211 purple_debug_warning("smiley-custom", "Invalid image type");
212 return NULL;
215 g_snprintf(file_name, sizeof(file_name), "%s.%s", checksum, file_ext);
216 g_free(checksum);
218 file_path = g_build_filename(smileys_dir, file_name, NULL);
220 if (!purple_image_save(img, file_path)) {
221 purple_debug_error("smiley-custom", "Failed writing smiley "
222 "file %s", file_path);
223 g_free(file_path);
224 g_object_unref(img);
225 return NULL;
227 g_object_unref(img);
229 smiley = purple_smiley_new(shortcut, file_path);
230 g_free(file_path);
231 succ = purple_smiley_list_add(smileys_list, smiley);
232 g_object_unref(smiley);
234 if (!succ)
235 purple_debug_error("smiley-custom", "Failed adding a smiley");
237 purple_smiley_custom_save();
239 return smiley;
242 void
243 purple_smiley_custom_remove(PurpleSmiley *smiley)
245 PurpleSmiley *existing_smiley;
246 const gchar *smiley_shortcut, *path;
247 GList *other_smileys, *it;
248 gboolean is_unique;
250 g_return_if_fail(PURPLE_IS_SMILEY(smiley));
252 smiley_shortcut = purple_smiley_get_shortcut(smiley);
253 existing_smiley = purple_smiley_list_get_by_shortcut(
254 smileys_list, smiley_shortcut);
255 if (existing_smiley == NULL)
256 return;
257 if (existing_smiley != smiley) {
258 purple_debug_warning("smiley-custom", "Smiley is not in store");
259 return;
262 g_object_ref(smiley);
263 purple_smiley_list_remove(smileys_list, smiley);
265 path = purple_image_get_path(PURPLE_IMAGE(smiley));
267 other_smileys = purple_smiley_list_get_unique(smileys_list);
268 is_unique = TRUE;
269 for (it = other_smileys; it; it = g_list_next(it)) {
270 PurpleSmiley *other = it->data;
271 const gchar *other_path = purple_image_get_path(PURPLE_IMAGE(other));
272 if (g_strcmp0(other_path, path) == 0) {
273 is_unique = FALSE;
274 break;
277 g_list_free(other_smileys);
279 if (is_unique)
280 g_unlink(path);
282 g_object_unref(smiley);
284 purple_smiley_custom_save();
287 PurpleSmileyList *
288 purple_smiley_custom_get_list(void)
290 return smileys_list;
294 /*******************************************************************************
295 * Custom smiley subsystem
296 ******************************************************************************/
298 void
299 _purple_smiley_custom_init(void)
301 gint ret;
303 smileys_dir = g_build_filename(purple_user_dir(),
304 SMILEYS_DEFAULT_FOLDER, NULL);
305 smileys_index = g_build_filename(purple_user_dir(),
306 SMILEYS_INDEX_FILE, NULL);
307 smileys_list = purple_smiley_list_new();
309 ret = g_mkdir(smileys_dir, S_IRUSR | S_IWUSR | S_IXUSR);
310 if (ret != 0 && errno != EEXIST) {
311 purple_debug_error("smiley-custom", "Failed creating custom "
312 "smileys directory: %s (%d)", g_strerror(errno), errno);
315 purple_smiley_custom_load();
318 void
319 _purple_smiley_custom_uninit(void)
321 g_free(smileys_dir);
322 g_free(smileys_index);
323 g_object_unref(smileys_list);