char *p;
sofia_profile_t *profile = NULL;
const char *exclude_contact = NULL;
+ const char *user_replacement = NULL;
char *reply = "error/facility_not_subscribed";
+ switch_stream_handle_t mystream = { 0 };
if (!cmd) {
stream->write_function(stream, "%s", "");
}
}
- if (!profile_name && domain) {
- profile_name = domain;
+ if (zstr(domain)) {
+ domain = switch_core_get_variable("domain");
}
- if (user && profile_name) {
- char *sql;
+ if (!user) goto end;
- if (!(profile = sofia_glue_find_profile(profile_name))) {
- profile_name = domain;
- domain = NULL;
- }
-
- if (!profile && profile_name) {
+ if (zstr(profile_name) || strcmp(profile_name, "*") || zstr(domain)) {
+ if (!zstr(profile_name)) {
profile = sofia_glue_find_profile(profile_name);
}
+
+ if (!profile) {
+ profile = sofia_glue_find_profile(domain);
+ }
+ }
- if (profile) {
- struct cb_helper cb;
- switch_stream_handle_t mystream = { 0 };
-
- cb.row_process = 0;
-
- if (!domain || (!strchr(domain, '.') && strcmp(profile_name, domain))) {
- domain = profile->name;
- }
-
- SWITCH_STANDARD_STREAM(mystream);
- switch_assert(mystream.data);
- cb.profile = profile;
- cb.stream = &mystream;
-
- if (exclude_contact) {
- sql = switch_mprintf("select contact, profile_name, '%q' "
- "from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%') "
- "and contact not like '%%%s%%'", (concat != NULL) ? concat : "", user, domain, domain, exclude_contact);
- } else {
- sql = switch_mprintf("select contact, profile_name, '%q' "
- "from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
- (concat != NULL) ? concat : "", user, domain, domain);
- }
+ if (profile || !zstr(domain)) {
+ SWITCH_STANDARD_STREAM(mystream);
+ switch_assert(mystream.data);
+ }
- switch_assert(sql);
- sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, contact_callback, &cb);
- switch_safe_free(sql);
- reply = (char *) mystream.data;
- if (!zstr(reply) && end_of(reply) == ',') {
- end_of(reply) = '\0';
- }
+ if (profile) {
+ if (zstr(domain)) {
+ domain = profile->name;
+ }
- if (zstr(reply)) {
- reply = "error/user_not_registered";
+ if (!zstr(profile->domain_name) && !zstr(profile_name) && !strcmp(profile_name, profile->name)) {
+ domain = profile->domain_name;
+ }
+
+ select_from_profile(profile, user, domain, concat, exclude_contact, &mystream);
+ sofia_glue_release_profile(profile);
+
+ } else if (!zstr(domain)) {
+ switch_mutex_lock(mod_sofia_globals.hash_mutex);
+ if (mod_sofia_globals.profile_hash) {
+ switch_hash_index_t *hi;
+ const void *var;
+ void *val;
+
+ for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, &var, NULL, &val);
+ if ((profile = (sofia_profile_t *) val) && !strcmp((char *)var, profile->name)) {
+ select_from_profile(profile, user, domain, concat, exclude_contact, &mystream);
+ profile = NULL;
+ }
}
+
+ if (user_replacement) {
+ int urlcount = 0;
+ int copyerr = 0;
+ char *newreply = NULL;
+ char *urlstart = NULL;
+ char *newptr = NULL;
+ char *bufend = NULL;
+ char *str = reply;
+ switch_size_t copysize = 0;
+ switch_size_t replacesize = strlen(user_replacement);
+ switch_size_t allocsize = 0;
+
+ /* first pass to count how many URLs we have */
+ while ((urlstart = strcasestr(str, "sip:")) || (urlstart = strcasestr(str, "sips:"))) {
+ urlcount++;
+ str = urlstart + 4;
+ }
+
+ if (!urlcount) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "sofia_contact(): no sip URLs found to replace the user\n");
+ copyerr++;
+ goto copydone;
+ }
+
+ /* this allocates a bit more than needed but better safe than sorry doing more funky math */
+ allocsize = strlen(reply) + (urlcount * replacesize);
+ newreply = switch_core_session_alloc(session, allocsize);
+ if (!newreply) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "sofia_contact(): no buffer space available for replacement\n");
+ copyerr++;
+ goto copydone;
+ }
+
+ /* get a working pointer to the new reply */
+ newptr = newreply;
+
+ /* pointer to the end of the allocated buffer for safety checks */
+ bufend = newreply + allocsize - 1;
+ *bufend = 0;
+
+ /* go thru all the urls and replace the user part */
+ str = reply;
+ while ((urlstart = strcasestr(str, "sip:")) || (urlstart = strcasestr(str, "sips:"))) {
+
+ /* found an URL, copy up to the start of the url */
+ copysize = ( urlstart - str ) + 4;
+
+ /* double check boundaries before copying anything at all (this should not happen) */
+ if ((newptr + copysize + replacesize) >= bufend) {
+ copyerr++;
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "sofia_contact(): wow buffer was not big enough!\n");
+ break;
+ }
+
+ /* copy the original contact string except for the user */
+ memcpy(newptr, str, copysize);
+ newptr += copysize;
+
+ /* copy the user replacement */
+ memcpy(newptr, user_replacement, replacesize);
+ newptr += replacesize;
+
+ /* skip the original user part */
+ str = strchr(urlstart, '@');
+ if (!str) {
+ copyerr++;
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "sofia_contact(): not host part found for contact\n");
+ break;
+ }
+ /* continue searching for the next sip: URL */
+ }
+
+copydone:
+ if (!copyerr) {
+ /* copy the remaining reply string */
+ copysize = strlen(str);
+ if ((newptr + copysize) >= bufend) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "sofia_contact(): wow buffer was not big enough, close, but not enough!\n");
+ } else {
+ strcpy(newptr, str);
+ reply = newreply;
+ }
+ } else {
+ reply = "error/replacement error";
+ }
+ }
+
+ stream->write_function(stream, "%s", reply);
+ reply = NULL;
+
+ switch_safe_free(mystream.data);
}
- }
+
- if (reply) {
- stream->write_function(stream, "%s", reply);
+ switch_mutex_unlock(mod_sofia_globals.hash_mutex);
+ }
+
+ reply = (char *) mystream.data;
+
+ end:
+
+ if (zstr(reply)) {
+ reply = "error/user_not_registered";
+ } else if (end_of(reply) == ',') {
+ end_of(reply) = '\0';
}
- switch_safe_free(data);
+ stream->write_function(stream, "%s", reply);
+ reply = NULL;
- if (profile) {
- sofia_glue_release_profile(profile);
- }
+ switch_safe_free(mystream.data);
+
+ switch_safe_free(data);
return SWITCH_STATUS_SUCCESS;
}