diff options
Diffstat (limited to 'src/xmpp')
-rw-r--r-- | src/xmpp/avatar.c | 58 | ||||
-rw-r--r-- | src/xmpp/avatar.h | 3 | ||||
-rw-r--r-- | src/xmpp/stanza.c | 101 | ||||
-rw-r--r-- | src/xmpp/stanza.h | 4 |
4 files changed, 166 insertions, 0 deletions
diff --git a/src/xmpp/avatar.c b/src/xmpp/avatar.c index b962fcef..9345ba3a 100644 --- a/src/xmpp/avatar.c +++ b/src/xmpp/avatar.c @@ -36,6 +36,9 @@ #include "config.h" #include <glib.h> +#ifdef HAVE_PIXBUF +#include <gdk-pixbuf-2.0/gdk-pixbuf/gdk-pixbuf.h> +#endif #include <string.h> #include <stdio.h> #include <stdlib.h> @@ -59,6 +62,7 @@ typedef struct avatar_metadata static GHashTable* looking_for = NULL; // contains nicks/barejids from who we want to get the avatar static GHashTable* shall_open = NULL; // contains a list of nicks that shall not just downloaded but also opened +const int MAX_PIXEL = 192; // max pixel width/height for an avatar static void _avatar_request_item_by_id(const char* jid, avatar_metadata* data); static int _avatar_metadata_handler(xmpp_stanza_t* const stanza, void* const userdata); @@ -92,6 +96,60 @@ avatar_pep_subscribe(void) shall_open = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); } +#ifdef HAVE_PIXBUF +gboolean +avatar_set(const char* path) +{ + char* expanded_path = get_expanded_path(path); + + GError* err = NULL; + GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file(expanded_path, &err); + + if (pixbuf == NULL) { + cons_show_error("An error occurred while opening %s: %s.", expanded_path, err ? err->message : "No error message given"); + return FALSE; + } + free(expanded_path); + + // Scale img + int w = gdk_pixbuf_get_width(pixbuf); + int h = gdk_pixbuf_get_height(pixbuf); + + if (w >= h && w > MAX_PIXEL) { + int dest_height = (int)((float)MAX_PIXEL / w * h); + GdkPixbuf* new_pixbuf = gdk_pixbuf_scale_simple(pixbuf, MAX_PIXEL, dest_height, GDK_INTERP_BILINEAR); + g_object_unref(pixbuf); + pixbuf = new_pixbuf; + } else if (h > w && w > MAX_PIXEL) { + int dest_width = (int)((float)MAX_PIXEL / h * w); + GdkPixbuf* new_pixbuf = gdk_pixbuf_scale_simple(pixbuf, dest_width, MAX_PIXEL, GDK_INTERP_BILINEAR); + g_object_unref(pixbuf); + pixbuf = new_pixbuf; + } + + gchar* img_data; + gsize len = -1; + + if (!gdk_pixbuf_save_to_buffer(pixbuf, &img_data, &len, "png", &err, NULL)) { + cons_show_error("Unable to scale and convert avatar."); + return FALSE; + } + + xmpp_ctx_t* const ctx = connection_get_ctx(); + xmpp_stanza_t* iq = stanza_create_avatar_data_publish_iq(ctx, img_data, len); + iq_send_stanza(iq); + xmpp_stanza_release(iq); + + iq = stanza_create_avatar_metadata_publish_iq(ctx, img_data, len, gdk_pixbuf_get_height(pixbuf), gdk_pixbuf_get_width(pixbuf)); + free(img_data); + g_object_unref(pixbuf); + iq_send_stanza(iq); + xmpp_stanza_release(iq); + + return TRUE; +} +#endif + gboolean avatar_get_by_nick(const char* nick, gboolean open) { diff --git a/src/xmpp/avatar.h b/src/xmpp/avatar.h index 98532917..c65328ad 100644 --- a/src/xmpp/avatar.h +++ b/src/xmpp/avatar.h @@ -40,5 +40,8 @@ void avatar_pep_subscribe(void); gboolean avatar_get_by_nick(const char* nick, gboolean open); +#ifdef HAVE_PIXBUF +gboolean avatar_set(const char* path); +#endif #endif diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index bfb782da..8dcad982 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -2587,6 +2587,107 @@ stanza_create_avatar_retrieve_data_request(xmpp_ctx_t* ctx, const char* stanza_i } xmpp_stanza_t* +stanza_create_avatar_data_publish_iq(xmpp_ctx_t* ctx, const char* img_data, gsize len) +{ + char* id = connection_create_stanza_id(); + xmpp_stanza_t* iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); + free(id); + xmpp_stanza_set_attribute(iq, STANZA_ATTR_FROM, connection_get_fulljid()); + + xmpp_stanza_t* pubsub = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(pubsub, STANZA_NAME_PUBSUB); + xmpp_stanza_set_ns(pubsub, STANZA_NS_PUBSUB); + + xmpp_stanza_t* publish = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(publish, STANZA_NAME_PUBLISH); + xmpp_stanza_set_attribute(publish, STANZA_ATTR_NODE, STANZA_NS_USER_AVATAR_DATA); + + xmpp_stanza_t* item = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(item, STANZA_NAME_ITEM); + char* sha1 = xmpp_sha1(ctx, (guchar*)img_data, len); + xmpp_stanza_set_attribute(item, "id", sha1); + xmpp_free(ctx, sha1); + + xmpp_stanza_t* data = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(data, STANZA_NAME_DATA); + xmpp_stanza_set_ns(data, STANZA_NS_USER_AVATAR_DATA); + + xmpp_stanza_t* text = xmpp_stanza_new(ctx); + gchar* base64 = g_base64_encode((guchar*)img_data, len); + xmpp_stanza_set_text(text, base64); + free(base64); + + xmpp_stanza_add_child(data, text); + xmpp_stanza_add_child(item, data); + xmpp_stanza_add_child(publish, item); + xmpp_stanza_add_child(pubsub, publish); + xmpp_stanza_add_child(iq, pubsub); + + xmpp_stanza_release(text); + xmpp_stanza_release(data); + xmpp_stanza_release(item); + xmpp_stanza_release(publish); + xmpp_stanza_release(pubsub); + + return iq; +} + +xmpp_stanza_t* +stanza_create_avatar_metadata_publish_iq(xmpp_ctx_t* ctx, const char* img_data, gsize len, int height, int width) +{ + char* id = id = connection_create_stanza_id(); + xmpp_stanza_t* iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); + free(id); + xmpp_stanza_set_attribute(iq, STANZA_ATTR_FROM, connection_get_fulljid()); + + xmpp_stanza_t* pubsub = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(pubsub, STANZA_NAME_PUBSUB); + xmpp_stanza_set_ns(pubsub, STANZA_NS_PUBSUB); + + xmpp_stanza_t* publish = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(publish, STANZA_NAME_PUBLISH); + xmpp_stanza_set_attribute(publish, STANZA_ATTR_NODE, STANZA_NS_USER_AVATAR_METADATA); + + xmpp_stanza_t* item = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(item, STANZA_NAME_ITEM); + char* sha1 = xmpp_sha1(ctx, (guchar*)img_data, len); + xmpp_stanza_set_attribute(item, "id", sha1); + + xmpp_stanza_t* metadata = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(metadata, STANZA_NAME_METADATA); + xmpp_stanza_set_ns(metadata, STANZA_NS_USER_AVATAR_METADATA); + + xmpp_stanza_t* info = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(info, STANZA_NAME_INFO); + xmpp_stanza_set_attribute(info, "id", sha1); + xmpp_free(ctx, sha1); + char* bytes = g_strdup_printf("%lu", len); + char* h = g_strdup_printf("%d", height); + char* w = g_strdup_printf("%d", width); + xmpp_stanza_set_attribute(info, "bytes", bytes); + xmpp_stanza_set_attribute(info, "type", "img/png"); + xmpp_stanza_set_attribute(info, "height", h); + xmpp_stanza_set_attribute(info, "width", w); + g_free(bytes); + g_free(h); + g_free(w); + + xmpp_stanza_add_child(metadata, info); + xmpp_stanza_add_child(item, metadata); + xmpp_stanza_add_child(publish, item); + xmpp_stanza_add_child(pubsub, publish); + xmpp_stanza_add_child(iq, pubsub); + + xmpp_stanza_release(info); + xmpp_stanza_release(metadata); + xmpp_stanza_release(item); + xmpp_stanza_release(publish); + xmpp_stanza_release(pubsub); + + return iq; +} + +xmpp_stanza_t* stanza_attach_correction(xmpp_ctx_t* ctx, xmpp_stanza_t* stanza, const char* const replace_id) { xmpp_stanza_t* replace_stanza = xmpp_stanza_new(ctx); diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index 6e201497..12c9a5ee 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -62,6 +62,8 @@ #define STANZA_NAME_PUBLIC_KEYS_LIST "public-keys-list" #define STANZA_NAME_PUBKEY_METADATA "pubkey-metadata" #define STANZA_NAME_DATA "data" +#define STANZA_NAME_METADATA "metadata" +#define STANZA_NAME_INFO "info" #define STANZA_NAME_SHOW "show" #define STANZA_NAME_STATUS "status" #define STANZA_NAME_IQ "iq" @@ -409,6 +411,8 @@ XMPPCaps* stanza_parse_caps(xmpp_stanza_t* const stanza); void stanza_free_caps(XMPPCaps* caps); xmpp_stanza_t* stanza_create_avatar_retrieve_data_request(xmpp_ctx_t* ctx, const char* stanza_id, const char* const item_id, const char* const jid); +xmpp_stanza_t* stanza_create_avatar_data_publish_iq(xmpp_ctx_t* ctx, const char* img_data, gsize len); +xmpp_stanza_t* stanza_create_avatar_metadata_publish_iq(xmpp_ctx_t* ctx, const char* img_data, gsize len, int height, int width); xmpp_stanza_t* stanza_create_mam_iq(xmpp_ctx_t* ctx, const char* const jid, const char* const startdate, const char* const lastid); xmpp_stanza_t* stanza_change_password(xmpp_ctx_t* ctx, const char* const user, const char* const password); xmpp_stanza_t* stanza_register_new_account(xmpp_ctx_t* ctx, const char* const user, const char* const password); |