diff --git a/libs/libdingaling/src/libdingaling.c b/libs/libdingaling/src/libdingaling.c index 2b4746560f..a418a3cf72 100644 --- a/libs/libdingaling/src/libdingaling.c +++ b/libs/libdingaling/src/libdingaling.c @@ -461,6 +461,19 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from, const char *marker = "TRUE"; +static int on_vcard(void *user_data, ikspak *pak) +{ + ldl_handle_t *handle = user_data; + char *from = iks_find_attrib(pak->x, "from"); + char *to = iks_find_attrib(pak->x, "to"); + + if (handle->session_callback) { + handle->session_callback(handle, NULL, LDL_SIGNAL_VCARD, to, from, pak->id, NULL); + } + + return IKS_FILTER_EAT; +} + static int on_disco_info(void *user_data, ikspak *pak) { ldl_handle_t *handle = user_data; @@ -1240,6 +1253,8 @@ static void j_setup_filter(ldl_handle_t *handle) IKS_RULE_SUBTYPE, IKS_TYPE_GET, IKS_RULE_NS, "jabber:iq:register", IKS_RULE_DONE); iks_filter_add_rule(handle->filter, on_disco_reg_out, handle, IKS_RULE_SUBTYPE, IKS_TYPE_SET, IKS_RULE_NS, "jabber:iq:register", IKS_RULE_DONE); + iks_filter_add_rule(handle->filter, on_vcard, handle, + IKS_RULE_SUBTYPE, IKS_TYPE_GET, IKS_RULE_NS, "vcard-temp", IKS_RULE_DONE); } else { iks_filter_add_rule(handle->filter, on_disco_info, handle, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); @@ -1571,6 +1586,34 @@ void ldl_handle_send_presence(ldl_handle_t *handle, char *from, char *to, char * do_presence(handle, from, to, type, rpid, message); } +void ldl_handle_send_vcard(ldl_handle_t *handle, char *from, char *to, char *id, char *vcard) +{ + iks *vxml, *iq; + int e = 0; + + if (!(vxml = iks_tree(vcard, 0, &e))) { + globals.logger(DL_LOG_ERR, "Parse returned error [%d]\n", e); + return; + } + + if (!(iq = iks_new("iq"))) { + globals.logger(DL_LOG_ERR, "Memory Error\n"); + return; + } + + iks_insert_attrib(iq, "to", to); + iks_insert_attrib(iq, "xmlns", "jabber:client"); + iks_insert_attrib(iq,"from", from); + iks_insert_attrib(iq, "type", "result"); + iks_insert_attrib(iq, "id", id); + iks_insert_node(iq, vxml); + + apr_queue_push(handle->queue, iq); + + iks_free(vxml); + +} + void ldl_handle_send_msg(ldl_handle_t *handle, char *from, char *to, char *subject, char *body) { iks *msg; diff --git a/libs/libdingaling/src/libdingaling.h b/libs/libdingaling/src/libdingaling.h index 88b9ec9303..72fcd553c3 100644 --- a/libs/libdingaling/src/libdingaling.h +++ b/libs/libdingaling/src/libdingaling.h @@ -126,6 +126,7 @@ typedef enum { LDL_SIGNAL_ROSTER, LDL_SIGNAL_SUBSCRIBE, LDL_SIGNAL_UNSUBSCRIBE, + LDL_SIGNAL_VCARD, LDL_SIGNAL_TERMINATE, LDL_SIGNAL_ERROR, LDL_SIGNAL_LOGIN_SUCCESS, @@ -374,6 +375,16 @@ void ldl_session_send_msg(ldl_session_t *session, char *subject, char *body); */ void ldl_handle_send_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *rpid, char *message); +/*! + \brief Send a vcard + \param handle the handle to send with + \param from the from address + \param to the to address + \param id the request id + \param vcard the text xml of the vcard +*/ +void ldl_handle_send_vcard(ldl_handle_t *handle, char *from, char *to, char *id, char *vcard); + /*! \brief Send a message \param handle the conection handle diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 70948b0397..7f04a3b0b3 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -3341,7 +3341,6 @@ static conference_obj_t *conference_new(char *name, switch_xml_t profile, switch SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename) { switch_status_t status = SWITCH_STATUS_SUCCESS; - switch_xml_t cfg, xml, param, ads; memset(&globals, 0, sizeof(globals)); @@ -3359,28 +3358,6 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_mod return SWITCH_STATUS_TERM; } - if ((xml = switch_xml_open_cfg(global_cf_name, &cfg, NULL))) { - if ((ads = switch_xml_child(cfg, "advertise"))) { - switch_event_t *event; - - for (param = switch_xml_child(ads, "room"); param; param = param->next) { - char *status = (char *) switch_xml_attr_soft(param, "status"); - char *name = (char *) switch_xml_attr_soft(param, "name"); - - if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", CONF_CHAT_PROTO); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", name); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", name); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", status ? status : "Inactive"); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "idle"); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); - - switch_event_fire(&event); - } - } - } - } - /* Setup a hash to store conferences by name */ switch_core_hash_init(&globals.conference_hash, globals.conference_pool); diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index c2f598aaa0..31ada3a65c 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -465,6 +465,29 @@ static int so_callback(void *pArg, int argc, char **argv, char **columnNames) return 0; } + +static int sin_callback(void *pArg, int argc, char **argv, char **columnNames) +{ + struct mdl_profile *profile = (struct mdl_profile *) pArg; + switch_event_t *event; + + //char *sub_from = argv[0]; + char *sub_to = argv[1]; + + if (strstr(sub_to, "ext+") || strstr(sub_to, "user+") || strstr(sub_to, "conf+")) { + if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_PROTO); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->login); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", sub_to); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "available"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "Online"); + switch_event_fire(&event); + } + } + + return 0; +} + static void sign_off(void) { struct mdl_profile *profile = NULL; @@ -505,6 +528,25 @@ static void sign_off(void) } +static void sign_on(struct mdl_profile *profile) +{ + char *sql; + switch_core_db_t *db; + char *errmsg; + + if ((sql = switch_mprintf("select * from subscriptions where sub_to like 'ext+%%' or sub_to like 'user+%%' or sub_to like 'conf+%%'"))) { + if (!(db = switch_core_db_open_file(profile->dbname))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname); + return; + } + switch_mutex_lock(profile->mutex); + switch_core_db_exec(db, sql, sin_callback, profile, &errmsg); + switch_mutex_unlock(profile->mutex); + switch_core_db_close(db); + switch_safe_free(sql); + } +} + static void terminate_session(switch_core_session_t **session, int line, switch_call_cause_t cause) { if (*session) { @@ -1482,7 +1524,7 @@ static switch_status_t channel_outgoing_channel(switch_core_session_t *session, if (outbound_profile) { char name[128]; - snprintf(name, sizeof(name), "DingaLing/%s-%04x", outbound_profile->destination_number, rand() & 0xffff); + snprintf(name, sizeof(name), "DingaLing/%s", outbound_profile->destination_number); switch_channel_set_name(channel, name); caller_profile = switch_caller_profile_clone(*new_session, outbound_profile); @@ -1930,6 +1972,72 @@ static void execute_sql(char *dbname, char *sql, switch_mutex_t *mutex) } } +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, user, vcard; + + if (!strncasecmp(to, "user+", 5)) { + real_to = to + 5; + } else { + real_to = to; + } + + + if ((to_user = strdup(real_to))) { + if ((to_host = strchr(to_user, '@'))) { + *to_host++ = '\0'; + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); + goto end; + } + + if (!to_host) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Missing Host!\n"); + goto end; + } + + if (!(params = switch_mprintf("to=%s@%s&from=%s&object=vcard", + to_user, + to_host, + from + ))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); + goto end; + } + + + 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); + 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); + 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); + goto end; + } + + switch_xml_set_attr(vcard, "xmlns", "vcard-tmp"); + + if ((xmlstr = switch_xml_toxml(vcard))) { + ldl_handle_send_vcard(handle, to, from, id, xmlstr); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); + } + + end: + if (xml) switch_xml_free(xml); + switch_safe_free(to_user); + switch_safe_free(params); + switch_safe_free(xmlstr); +} + static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsession, ldl_signal_t signal, char *to, char *from, char *subject, char *msg) { struct mdl_profile *profile = NULL; @@ -1951,6 +2059,9 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi if (!dlsession) { if (profile->user_flags & LDL_FLAG_COMPONENT) { switch(signal) { + case LDL_SIGNAL_VCARD: + do_vcard(handle, to, from, subject); + break; case LDL_SIGNAL_UNSUBSCRIBE: if ((sql = switch_mprintf("delete from subscriptions where sub_from='%q' and sub_to='%q';", from, to))) { @@ -1966,7 +2077,16 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi execute_sql(profile->dbname, sql, profile->mutex); switch_core_db_free(sql); } - + if (strstr(to, "ext+") || strstr(to, "user+") || strstr(to, "conf+") ) { + if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_PROTO); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->login); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", to); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "unknown"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "Click To Call"); + switch_event_fire(&event); + } + } break; case LDL_SIGNAL_ROSTER: if (switch_event_create(&event, SWITCH_EVENT_ROSTER) == SWITCH_STATUS_SUCCESS) { @@ -1991,6 +2111,16 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi switch_event_fire(&event); } + if (strstr(to, "ext+") || strstr(to, "user+") || strstr(to, "conf+")) { + if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_PROTO); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->login); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", to); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "unknown"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "Click To Call"); + switch_event_fire(&event); + } + } break; case LDL_SIGNAL_PRESENCE_OUT: @@ -2054,6 +2184,10 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->login); switch_event_fire(&event); } + if (profile->user_flags & LDL_FLAG_COMPONENT) { + sign_on(profile); + } + break; case LDL_SIGNAL_LOGIN_FAILURE: if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, DL_EVENT_LOGIN_FAILURE) == SWITCH_STATUS_SUCCESS) { @@ -2309,6 +2443,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi if (!(exten = ldl_session_get_value(dlsession, "dnis"))) { exten = profile->exten; + /* if it's _auto_ set the extension to match the username portion of the called address */ if (!strcmp(exten, "_auto_")) { if ((t = ldl_session_get_callee(dlsession))) { if ((them = strdup(t))) { @@ -2318,14 +2453,18 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi } if ((a = strchr(them, '+')) && (b = strrchr(them, '+')) && a != b) { - *b = '@'; + *b++ = '\0'; + switch_channel_set_variable(channel, "dl_user", them); + switch_channel_set_variable(channel, "dl_host", b); } exten = them; } } } } - + + + if (!(context = ldl_session_get_value(dlsession, "context"))) { context = profile->context; } @@ -2337,6 +2476,11 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi if (!(cid_num = ldl_session_get_value(dlsession, "caller_id_number"))) { cid_num = tech_pvt->recip; } + + /* context of "_auto_" means set it to the domain */ + if (profile->context && !strcmp(profile->context, "_auto_")) { + context = profile->name; + } if (!tech_pvt->caller_profile) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Creating an identity for %s %s <%s> %s\n", @@ -2355,7 +2499,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi context, exten)) != 0) { char name[128]; - snprintf(name, sizeof(name), "DingaLing/%s-%04x", tech_pvt->caller_profile->destination_number, rand() & 0xffff); + snprintf(name, sizeof(name), "DingaLing/%s", tech_pvt->caller_profile->destination_number); switch_channel_set_name(channel, name); switch_channel_set_caller_profile(channel, tech_pvt->caller_profile); } diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 25ec7dc16b..d7472fe3e8 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -2614,7 +2614,7 @@ static uint8_t handle_register(nua_t *nua, sip_expires_t const *expires = sip->sip_expires; sip_authorization_t const *authorization = sip->sip_authorization; sip_contact_t const *contact = sip->sip_contact; - switch_xml_t domain, xml, user, param; + switch_xml_t domain, xml, user, param, xparams; char params[1024] = ""; char *sql; switch_event_t *s_event; @@ -2695,9 +2695,16 @@ static uint8_t handle_register(nua_t *nua, switch_xml_free(xml); return 1; } + + if ((xparams = switch_xml_child(user, "params"))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "can't find params for user [%s@%s]\n", from_user, from_host); + nua_respond(nh, SIP_401_UNAUTHORIZED, SIPTAG_CONTACT(contact), TAG_END()); + switch_xml_free(xml); + return 1; + } - for (param = switch_xml_child(user, "param"); param; param = param->next) { + for (param = switch_xml_child(xparams, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); char *val = (char *) switch_xml_attr_soft(param, "value"); @@ -2889,10 +2896,15 @@ static int resub_callback(void *pArg, int argc, char **argv, char **columnNames) char *host = argv[1]; char *status = argv[2]; char *rpid = argv[3]; + char *proto = argv[4]; switch_event_t *event; + if (switch_strlen_zero(proto)) { + proto = NULL; + } + if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", proto ? proto : SOFIA_CHAT_PROTO); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->url); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", user, host); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "%s", status); @@ -3015,6 +3027,7 @@ static void sip_i_subscribe(int status, switch_core_db_t *db; char *errmsg; char *sstr; + switch_event_t *sevent; if (from) { from_user = (char *) from->a_url->url_user; @@ -3047,6 +3060,26 @@ static void sip_i_subscribe(int status, to_host = (char *) to->a_url->url_host; } + + if (strstr(to_user, "ext+") || strstr(to_user, "user+") || strstr(to_user, "conf+")) { + char proto[80]; + char *p; + + switch_copy_string(proto, to_user, sizeof(proto)); + if ((p = strchr(proto, '+'))) { + *p = '\0'; + } + + if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); + switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "login", "%s", profile->name); + switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, to_host); + switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "rpid", "unknown"); + switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "status", "Click To Call"); + switch_event_fire(&sevent); + } + } + if (strchr(to_user, '+')) { char *h; if ((proto = (d_user = strdup(to_user)))) { @@ -3123,7 +3156,7 @@ static void sip_i_subscribe(int status, } switch_core_db_close(db); end: - + if (event) { su_free(profile->home, event); } @@ -4629,7 +4662,15 @@ static void establish_presence(sofia_profile_t *profile) return; } - if ((sql = switch_mprintf("select user,host,'Registered','unavailable' from sip_registrations"))) { + if ((sql = switch_mprintf("select user,host,'Registered','unknown','' from sip_registrations"))) { + switch_mutex_lock(profile->ireg_mutex); + switch_core_db_exec(db, sql, resub_callback, profile, &errmsg); + switch_mutex_unlock(profile->ireg_mutex); + switch_safe_free(sql); + } + + if ((sql = switch_mprintf("select sub_to_user,sub_to_host,'Online','unknown',proto from sip_subscriptions " + "where proto='ext' or proto='user' or proto='conf'"))) { switch_mutex_lock(profile->ireg_mutex); switch_core_db_exec(db, sql, resub_callback, profile, &errmsg); switch_mutex_unlock(profile->ireg_mutex); @@ -4753,7 +4794,11 @@ static void pres_event_handler(switch_event_t *event) if ((user = strdup(from))) { if ((host = strchr(user, '@'))) { + char *p; *host++ = '\0'; + if ((p = strchr(host, '/'))) { + *p = '\0'; + } } else { switch_safe_free(user); return;