From 098d7274a06139a4d799b8a8a7b88619350955db Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 4 Apr 2007 22:22:55 +0000 Subject: [PATCH] add avatars for dingalaing git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@4850 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- libs/libdingaling/src/libdingaling.c | 140 +++++++++++++++++- libs/libdingaling/src/libdingaling.h | 3 +- .../endpoints/mod_dingaling/mod_dingaling.c | 37 +++-- src/mod/endpoints/mod_sofia/mod_sofia.h | 5 + 4 files changed, 168 insertions(+), 17 deletions(-) diff --git a/libs/libdingaling/src/libdingaling.c b/libs/libdingaling/src/libdingaling.c index c26df29807..23fa21c29f 100644 --- a/libs/libdingaling/src/libdingaling.c +++ b/libs/libdingaling/src/libdingaling.c @@ -31,6 +31,11 @@ #ifndef _MSC_VER #include +#include +#include +#include +#include + #endif #include @@ -74,6 +79,8 @@ static int opt_timeout = 30; +static void sha1_hash(char *out, char *in); +static int b64encode(unsigned char *in, uint32_t ilen, unsigned char *out, uint32_t olen); static struct { unsigned int flags; @@ -82,6 +89,7 @@ static struct { apr_pool_t *memory_pool; unsigned int id; ldl_logger_t logger; + apr_hash_t *avatar_hash; apr_thread_mutex_t *flag_mutex; } globals; @@ -152,6 +160,15 @@ struct ldl_session { void *private_data; }; +struct ldl_avatar { + char *path; + char *from; + char *base64; + char hash[256]; +}; + +typedef struct ldl_avatar ldl_avatar_t; + static void lowercase(char *str) { @@ -750,7 +767,54 @@ static int on_presence(void *user_data, ikspak *pak) return IKS_FILTER_EAT; } -static void do_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *rpid, char *message) +static ldl_avatar_t *ldl_get_avatar(char *path, char *from) +{ + ldl_avatar_t *ap; + uint8_t image[8192]; + unsigned char base64[9216] = ""; + int fd = -1; + size_t bytes; + char *p; + + if (path && (ap = (ldl_avatar_t *) apr_hash_get(globals.avatar_hash, path, APR_HASH_KEY_STRING))) { + return ap; + } + + if (from && (ap = (ldl_avatar_t *) apr_hash_get(globals.avatar_hash, from, APR_HASH_KEY_STRING))) { + return ap; + } + + if (!(path && from)) { + return NULL; + } + + if ((fd = open(path, O_RDONLY, 0)) < 0) { + globals.logger(DL_LOG_ERR, "File %s does not exist!\n", path); + return NULL; + } + + bytes = read(fd, image, sizeof(image)); + close(fd); + fd = -1; + + ap = malloc(sizeof(*ap)); + assert(ap != NULL); + memset(ap, 0, sizeof(*ap)); + sha1_hash(ap->hash, (char *)image); + ap->path = strdup(path); + ap->from = strdup(from); + if ((p = strchr(ap->from, '/'))) { + *p = '\0'; + } + b64encode((unsigned char *)image, bytes, base64, sizeof(base64)); + ap->base64 = strdup(base64); + apr_hash_set(globals.avatar_hash, ap->path, APR_HASH_KEY_STRING, ap); + apr_hash_set(globals.avatar_hash, ap->from, APR_HASH_KEY_STRING, ap); + return ap; +} + + +static void do_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *rpid, char *message, char *avatar) { iks *pres; char buf[512]; @@ -791,6 +855,20 @@ static void do_presence(ldl_handle_t *handle, char *from, char *to, char *type, } if (message || rpid) { + ldl_avatar_t *ap; + + if (avatar) { + if ((ap = ldl_get_avatar(avatar, from))) { + if ((tag = iks_insert(pres, "x"))) { + iks *hash; + iks_insert_attrib(tag, "xmlns", "vcard-temp:x:update"); + if ((hash = iks_insert(tag, "photo"))) { + iks_insert_cdata(hash, ap->hash, 0); + } + } + } + } + if ((tag = iks_insert(pres, "c"))) { iks_insert_attrib(tag, "node", "http://www.freeswitch.org/xmpp/client/caps"); iks_insert_attrib(tag, "ver", "1.0.0.1"); @@ -975,7 +1053,8 @@ static int on_result(void *user_data, ikspak *pak) static const char c64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; #define B64BUFFLEN 1024 -static int b64encode(unsigned char *in, uint32_t ilen, unsigned char *out, uint32_t olen) { +static int b64encode(unsigned char *in, uint32_t ilen, unsigned char *out, uint32_t olen) +{ int y=0,bytes=0; uint32_t x=0; unsigned int b=0,l=0; @@ -988,7 +1067,7 @@ static int b64encode(unsigned char *in, uint32_t ilen, unsigned char *out, uint3 if(++y!=72) { continue; } - out[bytes++] = '\n'; + //out[bytes++] = '\n'; y=0; } } @@ -1629,15 +1708,65 @@ char *ldl_handle_get_login(ldl_handle_t *handle) return handle->login; } -void ldl_handle_send_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *rpid, char *message) +void ldl_handle_send_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *rpid, char *message, char *avatar) { - do_presence(handle, from, to, type, rpid, message); + do_presence(handle, from, to, type, rpid, message, avatar); } +static void ldl_random_string(char *buf, uint16_t len, char *set) +{ + char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + int max; + uint16_t x; + + if (!set) { + set = chars; + } + + max = (int) strlen(set); + + srand((unsigned int) time(NULL)); + + for (x = 0; x < len; x++) { + int j = (int) (max * 1.0 * rand() / (RAND_MAX + 1.0)); + buf[x] = set[j]; + } +} + + void ldl_handle_send_vcard(ldl_handle_t *handle, char *from, char *to, char *id, char *vcard) { iks *vxml, *iq; int e = 0; + ldl_avatar_t *ap; + + ap = ldl_get_avatar(NULL, from); + + if (!vcard) { + char text[8192]; + char *ext; + if (!ap) { + return; + } + + if ((ext = strrchr(ap->path, '.'))) { + ext++; + } else { + ext = "png"; + } + + snprintf(text, sizeof(text), + "image/%s%s", + ext, + ap->base64 + ); + vcard = text; + } else { + if (ap && (strstr(vcard, "photo") || strstr(vcard, "PHOTO"))) { + ldl_random_string(ap->hash, sizeof(ap->hash), NULL); + } + } + if (!(vxml = iks_tree(vcard, 0, &e))) { globals.logger(DL_LOG_ERR, "Parse returned error [%d]\n", e); @@ -2016,6 +2145,7 @@ ldl_status ldl_global_init(int debug) globals.debug = debug; globals.id = 300; globals.logger = default_logger; + globals.avatar_hash = apr_hash_make(globals.memory_pool); ldl_set_flag_locked((&globals), LDL_FLAG_INIT); return LDL_STATUS_SUCCESS; diff --git a/libs/libdingaling/src/libdingaling.h b/libs/libdingaling/src/libdingaling.h index 37317fe99d..67f841d19a 100644 --- a/libs/libdingaling/src/libdingaling.h +++ b/libs/libdingaling/src/libdingaling.h @@ -439,8 +439,9 @@ void ldl_session_send_msg(ldl_session_t *session, char *subject, char *body); \param type the type of presence \param rpid data for the icon \param message a status message + \param avatar the path to an avatar image */ -void ldl_handle_send_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *rpid, char *message); +void ldl_handle_send_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *rpid, char *message, char *avatar); /*! \brief Send a vcard diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index 4db8879246..a9e0c93732 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -118,11 +118,17 @@ struct mdl_profile { char *context; char *timer_name; char *dbname; + char *avatar; #ifdef SWITCH_HAVE_ODBC char *odbc_dsn; char *odbc_user; char *odbc_pass; switch_odbc_handle_t *master_odbc; +#else + void *filler1; + void *filler2; + void *filler3; + void *filler4; #endif switch_mutex_t *mutex; ldl_handle_t *handle; @@ -361,7 +367,7 @@ static int sub_callback(void *pArg, int argc, char **argv, char **columnNames) rpid = translate_rpid(rpid, status); //ldl_handle_send_presence(profile->handle, sub_to, sub_from, "probe", rpid, status); - ldl_handle_send_presence(profile->handle, sub_to, sub_from, type, rpid, status); + ldl_handle_send_presence(profile->handle, sub_to, sub_from, type, rpid, status, profile->avatar); return 0; @@ -384,7 +390,7 @@ static int rost_callback(void *pArg, int argc, char **argv, char **columnNames) } } - ldl_handle_send_presence(profile->handle, sub_to, sub_from, NULL, show, status); + ldl_handle_send_presence(profile->handle, sub_to, sub_from, NULL, show, status, profile->avatar); return 0; } @@ -588,7 +594,7 @@ static int so_callback(void *pArg, int argc, char **argv, char **columnNames) char *sub_to = argv[1]; - ldl_handle_send_presence(profile->handle, sub_to, sub_from, "unavailable", "dnd", "Bub-Bye"); + ldl_handle_send_presence(profile->handle, sub_to, sub_from, "unavailable", "dnd", "Bub-Bye", profile->avatar); return 0; } @@ -1180,7 +1186,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) We should find out why..... */ if ((tech_pvt->profile->user_flags & LDL_FLAG_COMPONENT) && is_special(tech_pvt->them)) { - ldl_handle_send_presence(tech_pvt->profile->handle, tech_pvt->them, tech_pvt->us, NULL, NULL, "Click To Call"); + ldl_handle_send_presence(tech_pvt->profile->handle, tech_pvt->them, tech_pvt->us, NULL, NULL, "Click To Call", tech_pvt->profile->avatar); } if (tech_pvt->dlsession) { if (!switch_test_flag(tech_pvt, TFLAG_TERM)) { @@ -1881,6 +1887,8 @@ static void set_profile_val(mdl_profile_t *profile, char *var, char *val) profile->login = switch_core_strdup(module_pool, val); } else if (!strcasecmp(var, "password")) { profile->password = switch_core_strdup(module_pool, val); + } else if (!strcasecmp(var, "avatar")) { + profile->avatar = switch_core_strdup(module_pool, val); } else if (!strcasecmp(var, "odbc-dsn")) { #ifdef SWITCH_HAVE_ODBC profile->odbc_dsn = switch_core_strdup(module_pool, val); @@ -2164,10 +2172,11 @@ static switch_status_t load_config(void) } -static void do_vcard(ldl_handle_t * handle, char *to, char *from, char *id) +static void do_vcard(ldl_handle_t *handle, char *to, char *from, char *id) { char *params = NULL, *real_to, *to_user, *xmlstr = NULL, *to_host = NULL; switch_xml_t domain, xml = NULL, user, vcard; + int sent = 0; if (!strncasecmp(to, "user+", 5)) { real_to = to + 5; @@ -2197,17 +2206,17 @@ static void do_vcard(ldl_handle_t * handle, char *to, char *from, char *id) if (switch_xml_locate("directory", "domain", "name", to_host, &xml, &domain, params) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "can't find domain for [%s@%s]\n", to_user, to_host); + //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "can't find domain for [%s@%s]\n", to_user, to_host); goto end; } if (!(user = switch_xml_find_child(domain, "user", "id", to_user))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "can't find user [%s@%s]\n", to_user, to_host); + //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "can't find user [%s@%s]\n", to_user, to_host); goto end; } if (!(vcard = switch_xml_child(user, "vcard"))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "can't find tag for user [%s@%s]\n", to_user, to_host); + //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "can't find tag for user [%s@%s]\n", to_user, to_host); goto end; } @@ -2215,11 +2224,17 @@ static void do_vcard(ldl_handle_t * handle, char *to, char *from, char *id) if ((xmlstr = switch_xml_toxml(vcard))) { ldl_handle_send_vcard(handle, to, from, id, xmlstr); + sent = 1; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); } end: + + if (!sent) { + ldl_handle_send_vcard(handle, to, from, id, NULL); + } + if (xml) switch_xml_free(xml); switch_safe_free(to_user); @@ -2280,7 +2295,7 @@ static ldl_status handle_signalling(ldl_handle_t * handle, ldl_session_t * dlses } switch_mutex_unlock(profile->mutex); if (is_special(to)) { - ldl_handle_send_presence(profile->handle, to, from, NULL, NULL, "Click To Call"); + ldl_handle_send_presence(profile->handle, to, from, NULL, NULL, "Click To Call", profile->avatar); } #if 0 if (is_special(to)) { @@ -2305,7 +2320,7 @@ static ldl_status handle_signalling(ldl_handle_t * handle, ldl_session_t * dlses break; case LDL_SIGNAL_PRESENCE_PROBE: if (is_special(to)) { - ldl_handle_send_presence(profile->handle, to, from, NULL, NULL, "Click To Call"); + ldl_handle_send_presence(profile->handle, to, from, NULL, NULL, "Click To Call", profile->avatar); } else { if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_PROTO); @@ -2335,7 +2350,7 @@ static ldl_status handle_signalling(ldl_handle_t * handle, ldl_session_t * dlses if (is_special(to)) { - ldl_handle_send_presence(profile->handle, to, from, NULL, NULL, "Click To Call"); + ldl_handle_send_presence(profile->handle, to, from, NULL, NULL, "Click To Call", profile->avatar); } #if 0 if (is_special(to)) { diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 05a17e08e6..7253e820bf 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -230,6 +230,11 @@ struct sofia_profile { char *odbc_user; char *odbc_pass; switch_odbc_handle_t *master_odbc; +#else + void *filler1; + void *filler2; + void *filler3; + void *filler4; #endif };