diff --git a/makefile b/makefile index 0c94d89..61a883a 100644 --- a/makefile +++ b/makefile @@ -6,7 +6,7 @@ SRC = src/grammar/types.c $(BUILDPATH)/$(GRAMMAR)/expenses.yy.c $(BUILDPATH)/$(GRAMMAR)/expenses.tab.c src/bot/handlers.c src/bot/context.c src/main.c INSTALLPATH = /usr/local CFLAGS = `pkg-config --cflags glib-2.0` -LFLAGS = -lstrophe `pkg-config --libs glib-2.0` +LFLAGS = -lstrophe -lssl -lcrypto `pkg-config --libs glib-2.0` DEBFLAGS = -g -Wall OFLAGS = -O2 NAME = xmpp-bot diff --git a/src/bot/context.c b/src/bot/context.c index 014380a..220f5c7 100644 --- a/src/bot/context.c +++ b/src/bot/context.c @@ -10,10 +10,65 @@ g_string_free(user.pass, freeSegment); } -int bot_xmpp_set_avatar(struct BotXmppCtx * const bctx, const GString *avatarFile) +/* Implement https://xmpp.org/extensions/xep-0084.html */ +/* TODO need to understand the format for data stanza encoding (bytes? base64?) */ +/* int bot_xmpp_set_avatar_user(struct BotXmppCtx * const bctx, const GString *avatarFile) */ +/* { */ +/* gchar *avatar; */ +/* gsize avatarLenght; */ +/* xmpp_stanza_t *iq, *pubsub, *publish, *item, *data; */ + +/* /\* 1. Create IQ 'set' stanza *\/ */ +/* iq = xmpp_stanza_new(bctx->ctx); */ +/* xmpp_stanza_set_name(iq, "iq"); */ +/* xmpp_stanza_set_type(iq, "set"); */ +/* xmpp_stanza_set_id(iq, "publish1"); */ + +/* /\* Create protocol element*\/ */ +/* pubsub = xmpp_stanza_new(bctx->ctx); */ +/* xmpp_stanza_set_name(pubsub, "pubsub"); */ +/* xmpp_stanza_set_ns(pubsub, "http://jabber.org/protocol/pubsub"); */ +/* xmpp_stanza_add_child(iq, pubsub); */ + +/* /\* Create element *\/ */ +/* publish = xmpp_stanza_new(bctx->ctx); */ +/* xmpp_stanza_set_name(publish, "publish"); */ +/* xmpp_stanza_set_attribute(publish, "node", "urn:xmpp:avatar:data"); */ +/* xmpp_stanza_add_child(pubsub, publish); */ + +/* /\* Add where id should be the sha1sum of the image *\/ */ +/* item = xmpp_stanza_new(bctx->ctx); */ +/* xmpp_stanza_set_name(item, "item"); */ +/* xmpp_stanza_set_id(item, "SHA1SUM"); */ +/* xmpp_stanza_add_child(publish, item); */ + +/* /\* Add with base64 data *\/ */ +/* data = xmpp_stanza_new(bctx->ctx); */ +/* xmpp_stanza_set_name(data, "data"); */ +/* xmpp_stanza_set_ns(data, "urn:xmpp:avatar:data"); */ +/* if(g_file_get_contents(avatarFile->str, &avatar, &avatarLenght, NULL)) { */ +/* xmpp_stanza_set_text(data, avatar); */ +/* } else { */ +/* fprintf(stderr, "Unable to read png avatar.\n"); */ +/* } */ +/* xmpp_stanza_set_text(data, "DATA"); */ +/* xmpp_stanza_add_child(item, data); */ + +/* /\* 6. Send stanza and release it + all children *\/ */ +/* xmpp_send(bctx->conn, iq); */ +/* xmpp_stanza_release(iq); */ + +/* return 0; */ +/* } */ + + +/* implement https://xmpp.org/extensions/xep-0153.html */ +GString *bot_xmpp_set_avatar(struct BotXmppCtx * const bctx, const GString *avatarFile) { gchar *avatar; gsize avatarLenght; + GString *avatarID; + unsigned char hash[SHA_DIGEST_LENGTH]; /* == 20 */ xmpp_stanza_t *iq, *vcard, *photo, *type, *binval; /* 1. Create IQ 'set' stanza */ @@ -26,10 +81,12 @@ vcard = xmpp_stanza_new(bctx->ctx); xmpp_stanza_set_name(vcard, "vCard"); xmpp_stanza_set_ns(vcard, "vcard-temp"); + xmpp_stanza_add_child(iq, vcard); /* Create element */ photo = xmpp_stanza_new(bctx->ctx); xmpp_stanza_set_name(photo, "PHOTO"); + xmpp_stanza_add_child(vcard, photo); /* Add (e.g., image/jpeg) */ type = xmpp_stanza_new(bctx->ctx); @@ -42,22 +99,18 @@ xmpp_stanza_set_name(binval, "BINVAL"); if(g_file_get_contents(avatarFile->str, &avatar, &avatarLenght, NULL)) { + SHA1(avatarFile->str, sizeof(avatarFile->str)-1, hash); xmpp_stanza_set_text(binval, avatar); } else { fprintf(stderr, "Unable to read BASE64-encoded avatar.\n"); } - xmpp_stanza_add_child(photo, binval); - /* Assemble tree */ - xmpp_stanza_add_child(vcard, photo); - xmpp_stanza_add_child(iq, vcard); - /* 6. Send stanza and release it + all children */ xmpp_send(bctx->conn, iq); xmpp_stanza_release(iq); - return 0; + return g_string_new(hash); } int bot_xmpp_startup(struct BotUserInfo user, GString *avatarFile, struct BotXmppCtx * const bctx) @@ -65,6 +118,7 @@ xmpp_log_t* newLog; xmpp_ctx_t* newCtx; xmpp_conn_t* newCon; + GString *avatarID; int connectStatus; /* init library */ @@ -91,6 +145,9 @@ xmpp_conn_set_jid(newCon, user.jid->str); xmpp_conn_set_pass(newCon, user.pass->str); + /* TODO properly set avatarID in presence stanza */ + avatarID = bot_xmpp_set_avatar(bctx, avatarFile); + /* initiate connection */ connectStatus = xmpp_connect_client(newCon, NULL, 0, conn_handler, newCtx); if(connectStatus != 0) { @@ -102,8 +159,6 @@ (*bctx).ctx = newCtx; (*bctx).conn = newCon; - bot_xmpp_set_avatar(bctx, avatarFile); - return 0; } diff --git a/src/bot/context.h b/src/bot/context.h index 2c0fbc1..8a49dc2 100644 --- a/src/bot/context.h +++ b/src/bot/context.h @@ -12,6 +12,7 @@ #include #include #include +#include /* For SHA1 */ #include "handlers.h" struct BotUserInfo { @@ -28,7 +29,7 @@ void bot_free_user_data(struct BotUserInfo user, GString *filename, bool freeSegment); /* sets the given avatar file (base64 encoded) */ -int bot_xmpp_set_avatar(struct BotXmppCtx * const bctx, const GString *avatarFile); +GString *bot_xmpp_set_avatar(struct BotXmppCtx * const bctx, const GString *avatarFile); /* perform xmpp startup, store in bctx if completed successfully */ int bot_xmpp_startup(struct BotUserInfo user, GString *avatarFile, struct BotXmppCtx * const bctx);