Newer
Older
xmpp-bot / src / bot / context.c
@lagfra lagfra 11 days ago 3 KB avatar
/* bot/context.c
 */

#include "context.h"

void bot_free_user_data(struct BotUserInfo user, GString *filename, bool freeSegment)
{
    g_string_free(filename, freeSegment);
    g_string_free(user.jid, freeSegment);
    g_string_free(user.pass, freeSegment);
}

int bot_xmpp_set_avatar(struct BotXmppCtx * const bctx, const GString *avatarFile)
{
    gchar *avatar;
    gsize avatarLenght;
    xmpp_stanza_t *iq, *vcard, *photo, *type, *binval;

    /* 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, "vcard_set_1");

    /* Create <vCard xmlns='vcard-temp' */
    vcard = xmpp_stanza_new(bctx->ctx);
    xmpp_stanza_set_name(vcard, "vCard");
    xmpp_stanza_set_ns(vcard, "vcard-temp");

    /* Create <PHOTO> element */
    photo = xmpp_stanza_new(bctx->ctx);
    xmpp_stanza_set_name(photo, "PHOTO");

    /* Add <TYPE> (e.g., image/jpeg) */
    type = xmpp_stanza_new(bctx->ctx);
    xmpp_stanza_set_name(type, "TYPE");
    xmpp_stanza_set_text(type, "image/jpeg");
    xmpp_stanza_add_child(photo, type);

    /* Add <BINVAL> with base64 data */
    binval = xmpp_stanza_new(bctx->ctx);
    xmpp_stanza_set_name(binval, "BINVAL");

    if(g_file_get_contents(avatarFile->str, &avatar, &avatarLenght, NULL)) {
        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;
}

int bot_xmpp_startup(struct BotUserInfo user, GString *avatarFile, struct BotXmppCtx * const bctx)
{
    xmpp_log_t* newLog;
    xmpp_ctx_t* newCtx;
    xmpp_conn_t* newCon;
    int connectStatus;

    /* init library */
    xmpp_initialize();

    /* create a context */
    newLog = xmpp_get_default_logger(XMPP_LEVEL_DEBUG); /* pass NULL instead to silence output */
    newCtx = xmpp_ctx_new(NULL, newLog);

    if (!(newLog && newCtx)) {
        fprintf(stderr, "Unable to startup. Context creation failed.");
        return 1;
    }

    /* create a connection */
    newCon = xmpp_conn_new(newCtx);

    if (!newCon) {
        fprintf(stderr, "Unable to startup. Connection failed.");
        return 1;
    }

    /* setup authentication information */
    xmpp_conn_set_jid(newCon, user.jid->str);
    xmpp_conn_set_pass(newCon, user.pass->str);

    /* initiate connection */
    connectStatus = xmpp_connect_client(newCon, NULL, 0, conn_handler, newCtx);
    if(connectStatus != 0) {
        /* connecting went wrong */
        return connectStatus;
    }

    (*bctx).log = newLog;
    (*bctx).ctx = newCtx;
    (*bctx).conn = newCon;

    bot_xmpp_set_avatar(bctx, avatarFile);

    return 0;
}

void bot_xmpp_shutdown(struct BotXmppCtx * const bctx)
{
    /* enter the event loop - 
       our connect handler will trigger an exit */
    xmpp_run((*bctx).ctx);

    /* release our connection and context */
    xmpp_conn_release((*bctx).conn);
    xmpp_ctx_free((*bctx).ctx);

    /* final shutdown of the library */
    xmpp_shutdown();
}