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
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
23 #include "glibcompat.h"
33 const gchar
*extension
;
36 gchar
*friendly_filename
;
47 static GParamSpec
*properties
[PROP_LAST
];
49 G_DEFINE_TYPE_WITH_PRIVATE(PurpleImage
, purple_image
, G_TYPE_OBJECT
);
51 /******************************************************************************
53 ******************************************************************************/
55 _purple_image_set_path(PurpleImage
*image
, const gchar
*path
) {
56 PurpleImagePrivate
*priv
= purple_image_get_instance_private(image
);
60 priv
->path
= g_strdup(path
);
64 _purple_image_set_contents(PurpleImage
*image
, GBytes
*bytes
) {
65 PurpleImagePrivate
*priv
= purple_image_get_instance_private(image
);
68 g_bytes_unref(priv
->contents
);
70 priv
->contents
= (bytes
) ? g_bytes_ref(bytes
) : NULL
;
73 /******************************************************************************
75 ******************************************************************************/
77 purple_image_init(PurpleImage
*image
) {
81 purple_image_finalize(GObject
*obj
) {
82 PurpleImage
*image
= PURPLE_IMAGE(obj
);
83 PurpleImagePrivate
*priv
= purple_image_get_instance_private(image
);
86 g_bytes_unref(priv
->contents
);
89 g_free(priv
->gen_filename
);
90 g_free(priv
->friendly_filename
);
92 G_OBJECT_CLASS(purple_image_parent_class
)->finalize(obj
);
96 purple_image_set_property(GObject
*obj
, guint param_id
,
97 const GValue
*value
, GParamSpec
*pspec
)
99 PurpleImage
*image
= PURPLE_IMAGE(obj
);
103 _purple_image_set_path(image
, g_value_get_string(value
));
106 _purple_image_set_contents(image
, g_value_get_boxed(value
));
109 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj
, param_id
, pspec
);
115 purple_image_get_property(GObject
*obj
, guint param_id
, GValue
*value
,
118 PurpleImage
*image
= PURPLE_IMAGE(obj
);
122 g_value_set_string(value
, purple_image_get_path(image
));
125 g_value_set_boxed(value
, purple_image_get_contents(image
));
128 g_value_set_uint64(value
, purple_image_get_data_size(image
));
131 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj
, param_id
, pspec
);
137 purple_image_class_init(PurpleImageClass
*klass
) {
138 GObjectClass
*gobj_class
= G_OBJECT_CLASS(klass
);
140 gobj_class
->finalize
= purple_image_finalize
;
141 gobj_class
->get_property
= purple_image_get_property
;
142 gobj_class
->set_property
= purple_image_set_property
;
144 properties
[PROP_PATH
] = g_param_spec_string(
147 "The filepath for the image if one was provided",
149 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
| G_PARAM_STATIC_STRINGS
152 properties
[PROP_CONTENTS
] = g_param_spec_boxed(
155 "The contents of the image stored in a GBytes",
157 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
| G_PARAM_STATIC_STRINGS
160 properties
[PROP_SIZE
] = g_param_spec_uint64(
163 "The size of the image in bytes",
167 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
170 g_object_class_install_properties(gobj_class
, PROP_LAST
, properties
);
173 /******************************************************************************
175 ******************************************************************************/
177 purple_image_new_from_bytes(GBytes
*bytes
) {
186 purple_image_new_from_file(const gchar
*path
, GError
**error
) {
187 PurpleImage
*image
= NULL
;
188 GBytes
*bytes
= NULL
;
189 gchar
*contents
= NULL
;
192 if(!g_file_get_contents(path
, &contents
, &length
, error
)) {
196 bytes
= g_bytes_new_take(contents
, length
);
198 image
= g_object_new(
205 g_bytes_unref(bytes
);
211 purple_image_new_from_data(const guint8
*data
, gsize length
) {
213 GBytes
*bytes
= NULL
;
215 bytes
= g_bytes_new(data
, length
);
217 image
= purple_image_new_from_bytes(bytes
);
219 g_bytes_unref(bytes
);
225 purple_image_new_take_data(guint8
*data
, gsize length
) {
227 GBytes
*bytes
= NULL
;
229 bytes
= g_bytes_new_take(data
, length
);
231 image
= purple_image_new_from_bytes(bytes
);
233 g_bytes_unref(bytes
);
239 purple_image_save(PurpleImage
*image
, const gchar
*path
) {
240 PurpleImagePrivate
*priv
= NULL
;
245 g_return_val_if_fail(PURPLE_IS_IMAGE(image
), FALSE
);
246 g_return_val_if_fail(path
!= NULL
, FALSE
);
247 g_return_val_if_fail(path
[0] != '\0', FALSE
);
249 priv
= purple_image_get_instance_private(image
);
250 data
= purple_image_get_data(image
);
251 len
= purple_image_get_data_size(image
);
253 g_return_val_if_fail(data
!= NULL
, FALSE
);
254 g_return_val_if_fail(len
> 0, FALSE
);
256 succ
= purple_util_write_data_to_file_absolute(path
, data
, len
);
257 if (succ
&& priv
->path
== NULL
)
258 priv
->path
= g_strdup(path
);
264 purple_image_get_contents(PurpleImage
*image
)
266 PurpleImagePrivate
*priv
= NULL
;
268 g_return_val_if_fail(PURPLE_IS_IMAGE(image
), NULL
);
270 priv
= purple_image_get_instance_private(image
);
273 return g_bytes_ref(priv
->contents
);
279 purple_image_get_path(PurpleImage
*image
) {
280 PurpleImagePrivate
*priv
= NULL
;
282 g_return_val_if_fail(PURPLE_IS_IMAGE(image
), NULL
);
284 priv
= purple_image_get_instance_private(image
);
286 return priv
->path
? priv
->path
: purple_image_generate_filename(image
);
290 purple_image_get_data_size(PurpleImage
*image
) {
291 PurpleImagePrivate
*priv
;
293 g_return_val_if_fail(PURPLE_IS_IMAGE(image
), 0);
295 priv
= purple_image_get_instance_private(image
);
298 return g_bytes_get_size(priv
->contents
);
304 purple_image_get_data(PurpleImage
*image
) {
305 PurpleImagePrivate
*priv
= NULL
;
307 g_return_val_if_fail(PURPLE_IS_IMAGE(image
), NULL
);
309 priv
= purple_image_get_instance_private(image
);
312 return g_bytes_get_data(priv
->contents
, NULL
);
318 purple_image_get_extension(PurpleImage
*image
) {
319 PurpleImagePrivate
*priv
= NULL
;
322 g_return_val_if_fail(PURPLE_IS_IMAGE(image
), NULL
);
324 priv
= purple_image_get_instance_private(image
);
327 return priv
->extension
;
329 if (purple_image_get_data_size(image
) < 4)
332 data
= purple_image_get_data(image
);
333 g_assert(data
!= NULL
);
335 if (memcmp(data
, "GIF8", 4) == 0)
336 return priv
->extension
= "gif";
337 if (memcmp(data
, "\xff\xd8\xff", 3) == 0) /* 4th may be e0 through ef */
338 return priv
->extension
= "jpg";
339 if (memcmp(data
, "\x89PNG", 4) == 0)
340 return priv
->extension
= "png";
341 if (memcmp(data
, "MM", 2) == 0)
342 return priv
->extension
= "tif";
343 if (memcmp(data
, "II", 2) == 0)
344 return priv
->extension
= "tif";
345 if (memcmp(data
, "BM", 2) == 0)
346 return priv
->extension
= "bmp";
347 if (memcmp(data
, "\x00\x00\x01\x00", 4) == 0)
348 return priv
->extension
= "ico";
354 purple_image_get_mimetype(PurpleImage
*image
) {
355 PurpleImagePrivate
*priv
= NULL
;
356 const gchar
*ext
= purple_image_get_extension(image
);
358 g_return_val_if_fail(PURPLE_IS_IMAGE(image
), NULL
);
360 priv
= purple_image_get_instance_private(image
);
365 g_return_val_if_fail(ext
!= NULL
, NULL
);
367 if (g_strcmp0(ext
, "gif") == 0)
368 return priv
->mime
= "image/gif";
369 if (g_strcmp0(ext
, "jpg") == 0)
370 return priv
->mime
= "image/jpeg";
371 if (g_strcmp0(ext
, "png") == 0)
372 return priv
->mime
= "image/png";
373 if (g_strcmp0(ext
, "tif") == 0)
374 return priv
->mime
= "image/tiff";
375 if (g_strcmp0(ext
, "bmp") == 0)
376 return priv
->mime
= "image/bmp";
377 if (g_strcmp0(ext
, "ico") == 0)
378 return priv
->mime
= "image/vnd.microsoft.icon";
384 purple_image_generate_filename(PurpleImage
*image
) {
385 PurpleImagePrivate
*priv
= NULL
;
388 const gchar
*ext
= NULL
;
391 g_return_val_if_fail(PURPLE_IS_IMAGE(image
), NULL
);
393 priv
= purple_image_get_instance_private(image
);
395 if (priv
->gen_filename
)
396 return priv
->gen_filename
;
398 /* grab the image's data and size of that data */
399 data
= purple_image_get_data(image
);
400 len
= purple_image_get_data_size(image
);
402 /* create a checksum of it and use it as the start of our filename */
403 checksum
= g_compute_checksum_for_data(G_CHECKSUM_SHA1
, data
, len
);
405 /* if the image has a known format, set the extension appropriately */
406 ext
= purple_image_get_extension(image
);
408 priv
->gen_filename
= g_strdup_printf("%s.%s", checksum
, ext
);
411 priv
->gen_filename
= checksum
;
414 return priv
->gen_filename
;
418 purple_image_set_friendly_filename(PurpleImage
*image
, const gchar
*filename
) {
419 PurpleImagePrivate
*priv
= NULL
;
421 const gchar
*escaped
;
423 g_return_if_fail(PURPLE_IS_IMAGE(image
));
425 priv
= purple_image_get_instance_private(image
);
427 newname
= g_path_get_basename(filename
);
428 escaped
= purple_escape_filename(newname
);
432 if (g_strcmp0(escaped
, "") == 0 || g_strcmp0(escaped
, ".") == 0 ||
433 g_strcmp0(escaped
, G_DIR_SEPARATOR_S
) == 0 ||
434 g_strcmp0(escaped
, "/") == 0 || g_strcmp0(escaped
, "\\") == 0)
439 g_free(priv
->friendly_filename
);
440 priv
->friendly_filename
= g_strdup(escaped
);
444 purple_image_get_friendly_filename(PurpleImage
*image
) {
445 PurpleImagePrivate
*priv
= NULL
;
447 g_return_val_if_fail(PURPLE_IS_IMAGE(image
), NULL
);
449 priv
= purple_image_get_instance_private(image
);
451 if(priv
->friendly_filename
) {
452 return priv
->friendly_filename
;
455 return purple_image_generate_filename(image
);