#include <switch.h>
#include <curl/curl.h>
+#define SWITCH_REWIND_STREAM(s) s.end = s.data
+
/* Prototypes */
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_cidlookup_shutdown);
SWITCH_MODULE_RUNTIME_FUNCTION(mod_cidlookup_runtime);
*/
SWITCH_MODULE_DEFINITION(mod_cidlookup, mod_cidlookup_load, mod_cidlookup_shutdown, NULL);
-static char *SYNTAX = "cidlookup status|number [skipurl] [skipcitystate]";
+static char *SYNTAX = "cidlookup status|number [skipurl] [skipcitystate] [verbose]";
static struct {
char *url;
int err;
};
+struct cid_data_obj {
+ char *name;
+ char *area;
+ char *src;
+};
+typedef struct cid_data_obj cid_data_t;
+
struct callback_obj {
switch_memory_pool_t *pool;
len = strlen(str);
newstr = switch_core_alloc(pool, len+1);
+ switch_assert(newstr);
np = newstr;
while(*p) {
return newstr;
}
-static char *check_cache(switch_memory_pool_t *pool, const char *number) {
+static cid_data_t *check_cache(switch_memory_pool_t *pool, const char *number) {
char *cmd;
char *name = NULL;
+ char *area = NULL;
+ char *src = NULL;
+ cid_data_t *cid = NULL;
switch_stream_handle_t stream = { 0 };
SWITCH_STANDARD_STREAM(stream);
- cmd = switch_core_sprintf(pool, "get fs:cidlookup:%s", number);
+ cmd = switch_core_sprintf(pool, "get fs:cidlookup:name:%s", number);
if (switch_api_execute("memcache", cmd, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
if (strncmp("-ERR", stream.data, 4)) {
name = switch_core_strdup(pool, stream.data);
name = NULL;
}
}
+
+ SWITCH_REWIND_STREAM(stream);
+ cmd = switch_core_sprintf(pool, "get fs:cidlookup:area:%s", number);
+ if (switch_api_execute("memcache", cmd, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
+ if (strncmp("-ERR", stream.data, 4)) {
+ area = switch_core_strdup(pool, stream.data);
+ } else {
+ area = NULL;
+ }
+ }
+
+ SWITCH_REWIND_STREAM(stream);
+ cmd = switch_core_sprintf(pool, "get fs:cidlookup:src:%s", number);
+ if (switch_api_execute("memcache", cmd, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
+ if (strncmp("-ERR", stream.data, 4)) {
+ src = switch_core_strdup(pool, stream.data);
+ } else {
+ src = NULL;
+ }
+ }
+
+ if (name || area || src) {
+ cid = switch_core_alloc(pool, sizeof(cid_data_t));
+ switch_assert(cid);
+ cid->name = name;
+ cid->area = area;
+ cid->src = src;
+ }
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "memcache: k:'%s', v:'%s'\n", cmd, (name) ? name : "(null)");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "memcache: k:'%s', vn:'%s', va:'%s', vs:'%s'\n",
+ cmd,
+ (name) ? name : "(null)",
+ (area) ? area : "(null)",
+ (src) ? src : "(null)"
+ );
switch_safe_free(stream.data);
- return name;
+ return cid;
}
-switch_bool_t set_cache(switch_memory_pool_t *pool, const char *number, const char *cid) {
+switch_bool_t set_cache(switch_memory_pool_t *pool, char *number, cid_data_t *cid) {
char *cmd;
switch_bool_t success = SWITCH_TRUE;
switch_stream_handle_t stream = { 0 };
SWITCH_STANDARD_STREAM(stream);
- cmd = switch_core_sprintf(pool, "set fs:cidlookup:%s '%s' %d", number, cid, globals.cache_expire);
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "memcache: %s\n", cmd);
+ cmd = switch_core_sprintf(pool, "set fs:cidlookup:name:%s '%s' %d", number, cid->name, globals.cache_expire);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "memcache: %s\n", cmd);
if (switch_api_execute("memcache", cmd, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
if (strncmp("-ERR", stream.data, 4)) {
success = SWITCH_TRUE;
} else {
success = SWITCH_FALSE;
+ goto done;
}
}
-
+
+ SWITCH_REWIND_STREAM(stream);
+ cmd = switch_core_sprintf(pool, "set fs:cidlookup:area:%s '%s' %d", number, cid->area, globals.cache_expire);
+ if (switch_api_execute("memcache", cmd, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
+ if (strncmp("-ERR", stream.data, 4)) {
+ success = SWITCH_TRUE;
+ } else {
+ success = SWITCH_FALSE;
+ goto done;
+ }
+ }
+
+ SWITCH_REWIND_STREAM(stream);
+ cmd = switch_core_sprintf(pool, "set fs:cidlookup:src:%s '%s' %d", number, cid->src, globals.cache_expire);
+ if (switch_api_execute("memcache", cmd, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
+ if (strncmp("-ERR", stream.data, 4)) {
+ success = SWITCH_TRUE;
+ } else {
+ success = SWITCH_FALSE;
+ goto done;
+ }
+ }
+
+done:
switch_safe_free(stream.data);
return success;
}
return name;
}
-static char *do_whitepages_lookup(switch_memory_pool_t *pool, switch_event_t *event, const char *num, char **area)
+static cid_data_t *do_whitepages_lookup(switch_memory_pool_t *pool, switch_event_t *event, const char *num)
{
char *xml_s = NULL;
char *query = NULL;
char *name = NULL;
char *city = NULL;
char *state = NULL;
+ char *area = NULL;
switch_xml_t xml = NULL;
switch_xml_t node = NULL;
+ cid_data_t *cid = NULL;
/* NANPA check */
if (strlen(num) == 11 && num[0] == '1') {
goto done;
}
- switch_assert(area);
-
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "whitepages-cid", num);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "whitepages-api-key", globals.whitepages_apikey);
}
if (city || state) {
- *area = switch_core_sprintf(pool, "%s %s", city ? city : "", state ? state : "");
+ area = switch_core_sprintf(pool, "%s %s", city ? city : "", state ? state : "");
}
done:
switch_xml_free(xml);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "whitepages XML: %s\n", xml_s);
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "whitepages name: %s, area: %s\n", name ? name : "(null)", *area ? *area : "(null)");
- return name;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "whitepages name: %s, area: %s\n", name ? name : "(null)", area ? area : "(null)");
+
+ cid = switch_core_alloc(pool, sizeof(cid_data_t));
+ switch_assert(cid);
+
+ cid->name = name;
+ cid->area = area;
+ return cid;
}
static char *do_db_lookup(switch_memory_pool_t *pool, switch_event_t *event, const char *num, const char *sql) {
return name;
}
-static char *do_lookup(switch_memory_pool_t *pool, switch_event_t *event, const char *num, switch_bool_t skipurl, switch_bool_t skipcitystate) {
+static cid_data_t *do_lookup(switch_memory_pool_t *pool, switch_event_t *event, const char *num, switch_bool_t skipurl, switch_bool_t skipcitystate) {
char *number = NULL;
char *name = NULL;
- char *area = NULL;
char *url_query = NULL;
- char *src = NULL;
+ cid_data_t *cid = NULL;
+ switch_bool_t save_cache = SWITCH_FALSE;
+
+ cid = switch_core_alloc(pool, sizeof(cid_data_t));
+ switch_assert(cid);
number = string_digitsonly(pool, num);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "caller_id_number", number);
if (switch_odbc_available() && globals.master_odbc && globals.sql) {
name = do_db_lookup(pool, event, number, globals.sql);
if (name) {
- src = "database";
+ cid->name = name;
+ cid->src = "phone_database";
+ goto done;
}
}
- if (!name && (globals.url || globals.whitepages_apikey)) {
- if (globals.cache) {
- name = check_cache(pool, number);
- if (name) {
- src = "cache";
- }
+ if (globals.cache) {
+ cid = check_cache(pool, number);
+ if (cid) {
+ cid->src = switch_core_sprintf(pool, "%s (cache)", cid->src);
+ goto done;
}
- if (!skipurl && !name && globals.whitepages_apikey) {
- name = do_whitepages_lookup(pool, event, number, &area);
- if (area || name) {
- src = "whitepages";
- }
- if (name) {
- if (globals.cache) {
- set_cache(pool, number, name);
- }
- }
+ }
+
+ if (!skipurl && globals.whitepages_apikey) {
+ cid = do_whitepages_lookup(pool, event, number);
+ if (cid && cid->name) { /* only cache if we have a name */
+ save_cache = SWITCH_TRUE;
+ goto done;
}
- if (!skipurl && !name && globals.url) {
- url_query = switch_event_expand_headers(event, globals.url);
- name = do_lookup_url(pool, event, url_query);
- if (name) {
- src = "url";
- if (globals.cache) {
- set_cache(pool, number, name);
- }
- }
- if (url_query != globals.url) {
- switch_safe_free(url_query);
- }
+ }
+
+ if (!skipurl && globals.url) {
+ url_query = switch_event_expand_headers(event, globals.url);
+ name = do_lookup_url(pool, event, url_query);
+ if (name) {
+ cid->name = name;
+ cid->src = "url";
+ save_cache = SWITCH_TRUE;
+ }
+ if (url_query != globals.url) {
+ switch_safe_free(url_query);
}
}
- /* only do the below if we don't know anything about the # and it is a nanpa number */
- if (!area && !name &&
+
+done:
+ /* append area if we can */
+ if (!cid->area &&
!skipcitystate &&
strlen(number) == 11 && number[0] == '1' &&
switch_odbc_available() && globals.master_odbc && globals.citystate_sql) {
- area = do_db_lookup(pool, event, number, globals.citystate_sql);
- src = "npanxx";
+ name = do_db_lookup(pool, event, number, globals.citystate_sql);
+ if (name) {
+ cid->area = name;
+ if (cid->src) {
+ cid->src = switch_core_sprintf(pool, "%s,%s", cid->src, "npanxx_database");
+ } else {
+ cid->src = "npanxx_database";
+ }
+ }
}
- if (!name && area) {
- name = area;
+ if (!cid->name) {
+ cid->name = "UNKNOWN";
+ }
+ if (!cid->area) {
+ cid->area = "UNKNOWN";
+ }
+ if (!cid->src) {
+ cid->src = "UNKNOWN";
}
- if (!name) {
- name = "UNKNOWN";
+ if (globals.cache && save_cache) {
+ set_cache(pool, number, cid);
}
+
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "cidlookup source: %s\n", src ? src : "none");
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "cidlookup_source", src ? src : "none");
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "cidlookup_area", area ? area : "unknown");
- return name;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "cidlookup source: %s\n", cid->src);
+ return cid;
}
SWITCH_STANDARD_APP(cidlookup_app_function)
switch_event_t *event = NULL;
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_caller_profile_t *profile = switch_channel_get_caller_profile(channel);
- char *name = NULL;
+ cid_data_t *cid = NULL;
const char *number = NULL;
switch_bool_t skipurl = SWITCH_FALSE;
switch_bool_t skipcitystate = SWITCH_FALSE;
}
if (number) {
- name = do_lookup(pool, event, number, skipurl, skipcitystate);
+ cid = do_lookup(pool, event, number, skipurl, skipcitystate);
}
- if (name && channel) {
+ if (cid && channel) {
switch_channel_set_variable(channel, "original_caller_id_name", switch_core_strdup(pool, profile->caller_id_name));
- if (!zstr(switch_event_get_header(event, "cidlookup_source"))) {
- switch_channel_set_variable(channel, "cidlookup_source", switch_core_strdup(pool, switch_event_get_header(event, "cidlookup_source")));
+ if (!zstr(cid->src)) {
+ switch_channel_set_variable(channel, "cidlookup_source", cid->src);
}
- if (!zstr(switch_event_get_header(event, "cidlookup_area"))) {
- switch_channel_set_variable(channel, "cidlookup_area", switch_core_strdup(pool, switch_event_get_header(event, "cidlookup_area")));
+ if (!zstr(cid->area)) {
+ switch_channel_set_variable(channel, "cidlookup_area", cid->area);
}
- profile->caller_id_name = switch_core_strdup(profile->pool, name);;
+ profile->caller_id_name = switch_core_strdup(profile->pool, cid->name);;
}
switch_goto_status(SWITCH_STATUS_SUCCESS, done);
char *argv[4] = { 0 };
int argc;
int i;
- char *name = NULL;
+ cid_data_t *cid = NULL;
char *mydata = NULL;
switch_memory_pool_t *pool = NULL;
switch_event_t *event = NULL;
switch_bool_t skipurl = SWITCH_FALSE;
switch_bool_t skipcitystate = SWITCH_FALSE;
+ switch_bool_t verbose = SWITCH_FALSE;
if (zstr(cmd)) {
switch_goto_status(SWITCH_STATUS_SUCCESS, usage);
skipurl = SWITCH_TRUE;
} else if (!strcasecmp(argv[i], "skipcitystate")) {
skipcitystate = SWITCH_TRUE;
+ } else if (!strcasecmp(argv[i], "verbose")) {
+ verbose = SWITCH_TRUE;
}
}
- name = do_lookup(pool, event, argv[0], skipurl, skipcitystate);
- if (name) {
- stream->write_function(stream, name);
+ cid = do_lookup(pool, event, argv[0], skipurl, skipcitystate);
+ if (cid) {
+ stream->write_function(stream, cid->name);
+ if (verbose) {
+ stream->write_function(stream, " (%s) [%s]", cid->area, cid->src);
+ }
} else {
stream->write_function(stream, "UNKNOWN");
}