mirror of
https://github.com/strophe/libstrophe.git
synced 2026-07-18 20:06:21 +00:00
It has been pointed out that the wording of the license of this library is not entirely clear. The term "dual licensing" usually refers to a licence choice of two licenses "LICENSE1 _or_ LICENSE2. Instead the license of this library claimed "LICENSE1 _and_ LICENSE2". After an internal discussion with @metajack and @pasis it was made clear that the initial idea was to dual license the library in the usual way. This was also made clear by jack on the ML in the past [0]. As of jack, these licensing terms originated from jquery, which also used the 'and' version in the past and has since been corrected [1]. This patch changes the license terms to 'MIT or GPLv3' and also adds SPDX headers [2]. [0] https://groups.google.com/g/libstrophe/c/JkFgr601JQc [1] https://stackoverflow.com/q/2758409 [2] https://spdx.org Signed-off-by: Steffen Jaeckel <jaeckel-floss@eyet-services.de>
283 lines
7.2 KiB
C
283 lines
7.2 KiB
C
/* SPDX-License-Identifier: MIT OR GPL-3.0-only */
|
|
/* 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 or 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;
|
|
size_t written;
|
|
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);
|
|
written = fwrite(img, 1, img_size, fd);
|
|
if (written < img_size)
|
|
printf("Saving photo failed\n");
|
|
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;
|
|
size_t 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 *conn, void *userdata)
|
|
{
|
|
(void)userdata;
|
|
|
|
fprintf(stderr, "Timeout reached.\n");
|
|
xmpp_disconnect(conn);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int recv_vcard(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *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 *conn,
|
|
xmpp_conn_event_t status,
|
|
int error,
|
|
xmpp_stream_error_t *stream_error,
|
|
void *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;
|
|
}
|