examples: add vcard example
New exmaple shows how to request vCard and handle result. See XEP-0054 for details. PHOTO element is stored to an image file.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -36,6 +36,7 @@ examples/bot
|
||||
examples/component
|
||||
examples/roster
|
||||
examples/uuid
|
||||
examples/vcard
|
||||
test_stamp
|
||||
test-suite.log
|
||||
tests/*.o
|
||||
|
||||
@@ -99,7 +99,8 @@ noinst_PROGRAMS = \
|
||||
examples/bot \
|
||||
examples/component \
|
||||
examples/roster \
|
||||
examples/uuid
|
||||
examples/uuid \
|
||||
examples/vcard
|
||||
|
||||
examples_active_SOURCES = examples/active.c
|
||||
examples_active_CFLAGS = $(STROPHE_FLAGS)
|
||||
@@ -119,6 +120,9 @@ examples_roster_LDADD = $(STROPHE_LIBS)
|
||||
examples_uuid_SOURCES = examples/uuid.c
|
||||
examples_uuid_CFLAGS = $(STROPHE_FLAGS)
|
||||
examples_uuid_LDADD = $(STROPHE_LIBS)
|
||||
examples_vcard_SOURCES = examples/vcard.c
|
||||
examples_vcard_CFLAGS = $(STROPHE_FLAGS)
|
||||
examples_vcard_LDADD = $(STROPHE_LIBS)
|
||||
|
||||
|
||||
## Tests
|
||||
|
||||
281
examples/vcard.c
Normal file
281
examples/vcard.c
Normal file
@@ -0,0 +1,281 @@
|
||||
/* vcard.c
|
||||
* strophe XMPP client library -- vCard example
|
||||
*
|
||||
* Copyright (C) 2016 Dmitry Podgorny <pasis.ua@gmail.com>
|
||||
*
|
||||
* This software is provided AS-IS with no warranty, either express
|
||||
* or implied.
|
||||
*
|
||||
* This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <libgen.h> /* basename */
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strophe.h>
|
||||
|
||||
typedef struct {
|
||||
xmpp_ctx_t *ctx;
|
||||
const char *recipient;
|
||||
const char *img_path;
|
||||
} vcard_t;
|
||||
|
||||
typedef void (*vcard_cb_t)(vcard_t *, xmpp_stanza_t *);
|
||||
|
||||
#define REQ_TIMEOUT 5000
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
|
||||
static void vcard_photo(vcard_t *vc, xmpp_stanza_t *stanza)
|
||||
{
|
||||
xmpp_stanza_t *tmp;
|
||||
char *s;
|
||||
char *tok;
|
||||
char *saveptr = NULL;
|
||||
char *copy;
|
||||
unsigned char *img;
|
||||
size_t img_size;
|
||||
FILE *fd;
|
||||
|
||||
tmp = xmpp_stanza_get_child_by_name(stanza, "TYPE");
|
||||
assert(tmp != NULL);
|
||||
s = xmpp_stanza_get_text(tmp);
|
||||
assert(s != NULL);
|
||||
printf("PHOTO: %s, saving to file %s\n", s, vc->img_path);
|
||||
xmpp_free(vc->ctx, s);
|
||||
|
||||
tmp = xmpp_stanza_get_child_by_name(stanza, "BINVAL");
|
||||
assert(tmp != NULL);
|
||||
s = xmpp_stanza_get_text(tmp);
|
||||
assert(s != NULL);
|
||||
|
||||
/* remove \n and \r */
|
||||
copy = (char *)malloc(strlen(s) + 1);
|
||||
assert(copy != NULL);
|
||||
copy[0] = '\0';
|
||||
tok = strtok_r(s, "\n\r", &saveptr);
|
||||
while (tok != NULL) {
|
||||
strcat(copy, tok);
|
||||
tok = strtok_r(NULL, "\n\r", &saveptr);
|
||||
}
|
||||
|
||||
xmpp_base64_decode_bin(vc->ctx, copy, strlen(copy), &img, &img_size);
|
||||
assert(img != NULL);
|
||||
|
||||
fd = fopen(vc->img_path, "w");
|
||||
assert(fd != NULL);
|
||||
fwrite(img, 1, img_size, fd);
|
||||
fclose(fd);
|
||||
|
||||
free(copy);
|
||||
xmpp_free(vc->ctx, s);
|
||||
xmpp_free(vc->ctx, img);
|
||||
}
|
||||
|
||||
static void vcard_print_string(vcard_t *vc, xmpp_stanza_t *stanza,
|
||||
const char *info)
|
||||
{
|
||||
char *s = xmpp_stanza_get_text(stanza);
|
||||
|
||||
assert(s != NULL);
|
||||
printf("%s: %s\n", info, s);
|
||||
xmpp_free(vc->ctx, s);
|
||||
}
|
||||
|
||||
static void vcard_bday(vcard_t *vc, xmpp_stanza_t *stanza)
|
||||
{
|
||||
vcard_print_string(vc, stanza, "Birthday");
|
||||
}
|
||||
|
||||
static void vcard_desc(vcard_t *vc, xmpp_stanza_t *stanza)
|
||||
{
|
||||
vcard_print_string(vc, stanza, "Description");
|
||||
}
|
||||
|
||||
static void vcard_email(vcard_t *vc, xmpp_stanza_t *stanza)
|
||||
{
|
||||
xmpp_stanza_t *userid = xmpp_stanza_get_child_by_name(stanza, "USERID");
|
||||
|
||||
if (userid != NULL)
|
||||
vcard_print_string(vc, userid, "E-mail");
|
||||
}
|
||||
|
||||
static void vcard_fn(vcard_t *vc, xmpp_stanza_t *stanza)
|
||||
{
|
||||
vcard_print_string(vc, stanza, "Full name");
|
||||
}
|
||||
|
||||
static void vcard_name(vcard_t *vc, xmpp_stanza_t *stanza)
|
||||
{
|
||||
xmpp_stanza_t *name = xmpp_stanza_get_child_by_name(stanza, "GIVEN");
|
||||
xmpp_stanza_t *family = xmpp_stanza_get_child_by_name(stanza, "FAMILY");
|
||||
|
||||
if (name != NULL)
|
||||
vcard_print_string(vc, name, "Given name");
|
||||
if (family != NULL)
|
||||
vcard_print_string(vc, family, "Family name");
|
||||
}
|
||||
|
||||
static void vcard_nick(vcard_t *vc, xmpp_stanza_t *stanza)
|
||||
{
|
||||
vcard_print_string(vc, stanza, "Nickname");
|
||||
}
|
||||
|
||||
static void vcard_url(vcard_t *vc, xmpp_stanza_t *stanza)
|
||||
{
|
||||
vcard_print_string(vc, stanza, "URL");
|
||||
}
|
||||
|
||||
static vcard_cb_t vcard_cb_get(xmpp_stanza_t *stanza)
|
||||
{
|
||||
vcard_cb_t cb = NULL;
|
||||
const char *tag;
|
||||
int i;
|
||||
|
||||
static struct {
|
||||
const char *tag;
|
||||
vcard_cb_t cb;
|
||||
} vcard_tbl[] = {
|
||||
{ "PHOTO", vcard_photo },
|
||||
{ "BDAY", vcard_bday },
|
||||
{ "DESC", vcard_desc },
|
||||
{ "EMAIL", vcard_email },
|
||||
{ "FN", vcard_fn },
|
||||
{ "N", vcard_name },
|
||||
{ "NICKNAME", vcard_nick },
|
||||
{ "URL", vcard_url },
|
||||
};
|
||||
|
||||
tag = xmpp_stanza_get_name(stanza);
|
||||
if (tag == NULL)
|
||||
goto exit;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(vcard_tbl); ++i) {
|
||||
if (strcmp(tag, vcard_tbl[i].tag) == 0) {
|
||||
cb = vcard_tbl[i].cb;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return cb;
|
||||
}
|
||||
|
||||
static int timedout(xmpp_conn_t * const conn, void * const userdata)
|
||||
{
|
||||
fprintf(stderr, "Timeout reached.\n");
|
||||
xmpp_disconnect(conn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int recv_vcard(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
{
|
||||
vcard_t *vc = userdata;
|
||||
vcard_cb_t cb;
|
||||
xmpp_stanza_t *child;
|
||||
char *s;
|
||||
size_t s_size;
|
||||
int rc;
|
||||
|
||||
printf("Received vCard.\n\n");
|
||||
|
||||
child = xmpp_stanza_get_child_by_name(stanza, "error");
|
||||
if (child != NULL) {
|
||||
rc = xmpp_stanza_to_text(child, &s, &s_size);
|
||||
assert(rc == XMPP_EOK);
|
||||
printf("Error returned: %s.\n", s);
|
||||
xmpp_free(vc->ctx, s);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
child = xmpp_stanza_get_child_by_name(stanza, "vCard");
|
||||
assert(child != NULL);
|
||||
child = xmpp_stanza_get_children(child);
|
||||
while (child != NULL) {
|
||||
cb = vcard_cb_get(child);
|
||||
if (cb != NULL)
|
||||
cb(vc, child);
|
||||
child = xmpp_stanza_get_next(child);
|
||||
}
|
||||
|
||||
exit:
|
||||
xmpp_disconnect(conn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void send_vcard_req(xmpp_conn_t *conn, const char *to, const char *id)
|
||||
{
|
||||
printf("Requesting vCard from %s.\n", to);
|
||||
xmpp_send_raw_string(conn, "<iq from='%s' to='%s' type='get' id='%s'>"
|
||||
"<vCard xmlns='vcard-temp'/></iq>",
|
||||
xmpp_conn_get_bound_jid(conn), to, id);
|
||||
}
|
||||
|
||||
static void conn_handler(xmpp_conn_t * const conn,
|
||||
const xmpp_conn_event_t status,
|
||||
const int error,
|
||||
xmpp_stream_error_t * const stream_error,
|
||||
void * const userdata)
|
||||
{
|
||||
vcard_t *vc = userdata;
|
||||
|
||||
if (status == XMPP_CONN_CONNECT) {
|
||||
send_vcard_req(conn, vc->recipient, "vc1");
|
||||
xmpp_id_handler_add(conn, recv_vcard, "vc1", vc);
|
||||
xmpp_timed_handler_add(conn, timedout, REQ_TIMEOUT, NULL);
|
||||
} else {
|
||||
if (error != 0)
|
||||
fprintf(stderr, "Disconnected with error=%d.\n", error);
|
||||
if (stream_error != NULL)
|
||||
fprintf(stderr, "Stream error type=%d text=%s.\n",
|
||||
stream_error->type, stream_error->text);
|
||||
xmpp_stop(vc->ctx);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
xmpp_log_t *log;
|
||||
xmpp_ctx_t *ctx;
|
||||
xmpp_conn_t *conn;
|
||||
const char *jid;
|
||||
const char *pass;
|
||||
char *prog;
|
||||
vcard_t vcard;
|
||||
|
||||
if (argc < 4 || argc > 5) {
|
||||
prog = argc > 0 ? strdup(argv[0]) : NULL;
|
||||
printf("Usage: %s <login-jid> <password> <recipient-jid> "
|
||||
"[image-file]\n\n", prog == NULL ? "vcard" : basename(prog));
|
||||
printf("If vCard contains a photo it will be stored to "
|
||||
"image-file. If you don't provide the image-file "
|
||||
"default filename will be generated.\n");
|
||||
free(prog);
|
||||
return 1;
|
||||
}
|
||||
|
||||
jid = argv[1];
|
||||
pass = argv[2];
|
||||
vcard.recipient = argv[3];
|
||||
vcard.img_path = argc > 4 ? argv[4] : "vcard.jpg";
|
||||
|
||||
xmpp_initialize();
|
||||
log = xmpp_get_default_logger(XMPP_LEVEL_INFO);
|
||||
ctx = xmpp_ctx_new(NULL, log);
|
||||
conn = xmpp_conn_new(ctx);
|
||||
xmpp_conn_set_jid(conn, jid);
|
||||
xmpp_conn_set_pass(conn, pass);
|
||||
vcard.ctx = ctx;
|
||||
xmpp_connect_client(conn, NULL, 0, conn_handler, &vcard);
|
||||
xmpp_run(ctx);
|
||||
xmpp_conn_release(conn);
|
||||
xmpp_ctx_free(ctx);
|
||||
xmpp_shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user