mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-14 08:05:37 +00:00
add arrays to event headers and chanvars
This commit is contained in:
parent
b978d39d48
commit
c1c759526d
@ -34,10 +34,10 @@ testclient: $(MYLIB) testclient.c
|
|||||||
fs_cli: $(MYLIB) fs_cli.c
|
fs_cli: $(MYLIB) fs_cli.c
|
||||||
$(CC) $(CC_CFLAGS) $(CFLAGS) fs_cli.c -o fs_cli $(LDFLAGS) -L$(LIBEDIT_DIR)/src/.libs $(LIBS) -ledit
|
$(CC) $(CC_CFLAGS) $(CFLAGS) fs_cli.c -o fs_cli $(LDFLAGS) -L$(LIBEDIT_DIR)/src/.libs $(LIBS) -ledit
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c $(HEADERS)
|
||||||
$(CC) $(CC_CFLAGS) $(CFLAGS) -c $< -o $@
|
$(CC) $(CC_CFLAGS) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
%.o: %.cpp
|
%.o: %.cpp $(HEADERS)
|
||||||
$(CXX) $(CXX_CFLAGS) $(CXXFLAGS) -c $< -o $@
|
$(CXX) $(CXX_CFLAGS) $(CXXFLAGS) -c $< -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
@ -1025,6 +1025,51 @@ static esl_ssize_t handle_recv(esl_handle_t *handle, void *data, esl_size_t data
|
|||||||
return recv(handle->sock, data, datalen, 0);
|
return recv(handle->sock, data, datalen, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int add_array(esl_event_t *event, const char *var, const char *val)
|
||||||
|
{
|
||||||
|
char *data;
|
||||||
|
char **array;
|
||||||
|
int idx;
|
||||||
|
int max = 0;
|
||||||
|
int len;
|
||||||
|
const char *p;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (strlen(val) < 8) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = val + 7;
|
||||||
|
|
||||||
|
while((p = strstr(p, "::"))) {
|
||||||
|
max++;
|
||||||
|
p += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!max) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = strdup(val + 7);
|
||||||
|
|
||||||
|
len = (sizeof(char *) * max) + 1;
|
||||||
|
array = malloc(len);
|
||||||
|
memset(array, 0, len);
|
||||||
|
|
||||||
|
idx = esl_separate_string_string(data, "::", array, max);
|
||||||
|
|
||||||
|
for(i = 0; i < max; i++) {
|
||||||
|
esl_event_add_header_string(event, ESL_STACK_PUSH, var, array[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(array);
|
||||||
|
free(data);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_event_t **save_event)
|
ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_event_t **save_event)
|
||||||
{
|
{
|
||||||
char *c;
|
char *c;
|
||||||
@ -1088,7 +1133,11 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
|
|||||||
if (hname && hval) {
|
if (hname && hval) {
|
||||||
esl_url_decode(hval);
|
esl_url_decode(hval);
|
||||||
esl_log(ESL_LOG_DEBUG, "RECV HEADER [%s] = [%s]\n", hname, hval);
|
esl_log(ESL_LOG_DEBUG, "RECV HEADER [%s] = [%s]\n", hname, hval);
|
||||||
esl_event_add_header_string(revent, ESL_STACK_BOTTOM, hname, hval);
|
if (!strncmp(hval, "ARRAY::", 7)) {
|
||||||
|
add_array(revent, hname, hval);
|
||||||
|
} else {
|
||||||
|
esl_event_add_header_string(revent, ESL_STACK_BOTTOM, hname, hval);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p = e;
|
p = e;
|
||||||
@ -1217,7 +1266,12 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
|
|||||||
esl_event_del_header(handle->last_ievent, "event-name");
|
esl_event_del_header(handle->last_ievent, "event-name");
|
||||||
esl_name_event(hval, &handle->last_ievent->event_id);
|
esl_name_event(hval, &handle->last_ievent->event_id);
|
||||||
}
|
}
|
||||||
esl_event_add_header_string(handle->last_ievent, ESL_STACK_BOTTOM, hname, hval);
|
|
||||||
|
if (!strncmp(hval, "ARRAY::", 7)) {
|
||||||
|
add_array(handle->last_ievent, hname, hval);
|
||||||
|
} else {
|
||||||
|
esl_event_add_header_string(handle->last_ievent, ESL_STACK_BOTTOM, hname, hval);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
beg = c + 1;
|
beg = c + 1;
|
||||||
@ -1371,5 +1425,23 @@ ESL_DECLARE(esl_status_t) esl_send_recv_timed(esl_handle_t *handle, const char *
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ESL_DECLARE(unsigned int) esl_separate_string_string(char *buf, const char *delim, char **array, unsigned int arraylen)
|
||||||
|
{
|
||||||
|
unsigned int count = 0;
|
||||||
|
char *d;
|
||||||
|
size_t dlen = strlen(delim);
|
||||||
|
|
||||||
|
array[count++] = buf;
|
||||||
|
|
||||||
|
while (count < arraylen && array[count - 1]) {
|
||||||
|
if ((d = strstr(array[count - 1], delim))) {
|
||||||
|
*d = '\0';
|
||||||
|
d += dlen;
|
||||||
|
array[count++] = d;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -235,8 +235,7 @@ static unsigned int esl_ci_hashfunc_default(const char *char_key, esl_ssize_t *k
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ESL_DECLARE(esl_event_header_t *) esl_event_get_header_ptr(esl_event_t *event, const char *header_name)
|
||||||
ESL_DECLARE(char *)esl_event_get_header(esl_event_t *event, const char *header_name)
|
|
||||||
{
|
{
|
||||||
esl_event_header_t *hp;
|
esl_event_header_t *hp;
|
||||||
esl_ssize_t hlen = -1;
|
esl_ssize_t hlen = -1;
|
||||||
@ -244,18 +243,39 @@ ESL_DECLARE(char *)esl_event_get_header(esl_event_t *event, const char *header_n
|
|||||||
|
|
||||||
esl_assert(event);
|
esl_assert(event);
|
||||||
|
|
||||||
if (!header_name) return NULL;
|
if (!header_name)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
hash = esl_ci_hashfunc_default(header_name, &hlen);
|
hash = esl_ci_hashfunc_default(header_name, &hlen);
|
||||||
|
|
||||||
for (hp = event->headers; hp; hp = hp->next) {
|
for (hp = event->headers; hp; hp = hp->next) {
|
||||||
if ((!hp->hash || hash == hp->hash) && !strcasecmp(hp->name, header_name) ) {
|
if ((!hp->hash || hash == hp->hash) && !strcasecmp(hp->name, header_name)) {
|
||||||
return hp->value;
|
return hp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ESL_DECLARE(char *) esl_event_get_header_idx(esl_event_t *event, const char *header_name, int idx)
|
||||||
|
{
|
||||||
|
esl_event_header_t *hp;
|
||||||
|
|
||||||
|
if ((hp = esl_event_get_header_ptr(event, header_name))) {
|
||||||
|
if (idx > -1) {
|
||||||
|
if (idx < hp->idx) {
|
||||||
|
return hp->array[idx];
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hp->value;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ESL_DECLARE(char *)esl_event_get_body(esl_event_t *event)
|
ESL_DECLARE(char *)esl_event_get_body(esl_event_t *event)
|
||||||
{
|
{
|
||||||
return (event ? event->body : NULL);
|
return (event ? event->body : NULL);
|
||||||
@ -264,7 +284,7 @@ ESL_DECLARE(char *)esl_event_get_body(esl_event_t *event)
|
|||||||
ESL_DECLARE(esl_status_t) esl_event_del_header_val(esl_event_t *event, const char *header_name, const char *val)
|
ESL_DECLARE(esl_status_t) esl_event_del_header_val(esl_event_t *event, const char *header_name, const char *val)
|
||||||
{
|
{
|
||||||
esl_event_header_t *hp, *lp = NULL, *tp;
|
esl_event_header_t *hp, *lp = NULL, *tp;
|
||||||
esl_status_t status = ESL_FAIL;
|
esl_status_t status = ESL_FALSE;
|
||||||
int x = 0;
|
int x = 0;
|
||||||
esl_ssize_t hlen = -1;
|
esl_ssize_t hlen = -1;
|
||||||
unsigned long hash = 0;
|
unsigned long hash = 0;
|
||||||
@ -273,12 +293,12 @@ ESL_DECLARE(esl_status_t) esl_event_del_header_val(esl_event_t *event, const cha
|
|||||||
while (tp) {
|
while (tp) {
|
||||||
hp = tp;
|
hp = tp;
|
||||||
tp = tp->next;
|
tp = tp->next;
|
||||||
|
|
||||||
x++;
|
x++;
|
||||||
esl_assert(x < 1000);
|
esl_assert(x < 1000000);
|
||||||
hash = esl_ci_hashfunc_default(header_name, &hlen);
|
hash = esl_ci_hashfunc_default(header_name, &hlen);
|
||||||
|
|
||||||
if (hp->name && (!hp->hash || hash == hp->hash) && !strcasecmp(header_name, hp->name) && (esl_strlen_zero(val) || !strcmp(hp->value, val))) {
|
if ((!hp->hash || hash == hp->hash) && !strcasecmp(header_name, hp->name) && (esl_strlen_zero(val) || !strcmp(hp->value, val))) {
|
||||||
if (lp) {
|
if (lp) {
|
||||||
lp->next = hp->next;
|
lp->next = hp->next;
|
||||||
} else {
|
} else {
|
||||||
@ -288,10 +308,27 @@ ESL_DECLARE(esl_status_t) esl_event_del_header_val(esl_event_t *event, const cha
|
|||||||
event->last_header = lp;
|
event->last_header = lp;
|
||||||
}
|
}
|
||||||
FREE(hp->name);
|
FREE(hp->name);
|
||||||
FREE(hp->value);
|
|
||||||
memset(hp, 0, sizeof(*hp));
|
|
||||||
FREE(hp);
|
|
||||||
|
|
||||||
|
if (hp->idx) {
|
||||||
|
int i = 0;
|
||||||
|
hp->value = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < hp->idx; i++) {
|
||||||
|
FREE(hp->array[i]);
|
||||||
|
}
|
||||||
|
FREE(hp->array);
|
||||||
|
}
|
||||||
|
|
||||||
|
FREE(hp->value);
|
||||||
|
|
||||||
|
memset(hp, 0, sizeof(*hp));
|
||||||
|
#ifdef ESL_EVENT_RECYCLE
|
||||||
|
if (esl_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, hp) != ESL_SUCCESS) {
|
||||||
|
FREE(hp);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
FREE(hp);
|
||||||
|
#endif
|
||||||
status = ESL_SUCCESS;
|
status = ESL_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
lp = hp;
|
lp = hp;
|
||||||
@ -303,36 +340,122 @@ ESL_DECLARE(esl_status_t) esl_event_del_header_val(esl_event_t *event, const cha
|
|||||||
|
|
||||||
static esl_status_t esl_event_base_add_header(esl_event_t *event, esl_stack_t stack, const char *header_name, char *data)
|
static esl_status_t esl_event_base_add_header(esl_event_t *event, esl_stack_t stack, const char *header_name, char *data)
|
||||||
{
|
{
|
||||||
esl_event_header_t *header;
|
esl_event_header_t *header = NULL;
|
||||||
esl_ssize_t hlen = -1;
|
esl_ssize_t hlen = -1;
|
||||||
|
int exists = 0;
|
||||||
|
|
||||||
header = ALLOC(sizeof(*header));
|
if ((stack & ESL_STACK_PUSH) || (stack & ESL_STACK_UNSHIFT) || esl_test_flag(event, ESL_EF_CONTAINS_ARRAYS)) {
|
||||||
esl_assert(header);
|
|
||||||
|
|
||||||
if ((event->flags & ESL_UNIQ_HEADERS)) {
|
if ((header = esl_event_get_header_ptr(event, header_name))) {
|
||||||
esl_event_del_header(event, header_name);
|
|
||||||
|
if (!(stack & ESL_STACK_PUSH) && !(stack & ESL_STACK_UNSHIFT) && header->idx) {
|
||||||
|
stack |= ESL_STACK_PUSH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((stack & ESL_STACK_PUSH) || (stack & ESL_STACK_UNSHIFT)) {
|
||||||
|
exists++;
|
||||||
|
stack &= ~(ESL_STACK_TOP | ESL_STACK_BOTTOM);
|
||||||
|
} else {
|
||||||
|
header = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(header, 0, sizeof(*header));
|
if (!header) {
|
||||||
|
|
||||||
header->name = DUP(header_name);
|
#ifdef ESL_EVENT_RECYCLE
|
||||||
header->value = data;
|
void *pop;
|
||||||
header->hash = esl_ci_hashfunc_default(header->name, &hlen);
|
if (esl_queue_trypop(EVENT_HEADER_RECYCLE_QUEUE, &pop) == ESL_SUCCESS) {
|
||||||
|
header = (esl_event_header_t *) pop;
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
header = ALLOC(sizeof(*header));
|
||||||
|
esl_assert(header);
|
||||||
|
#ifdef ESL_EVENT_RECYCLE
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (stack == ESL_STACK_TOP) {
|
|
||||||
header->next = event->headers;
|
if (esl_test_flag(event, ESL_EF_UNIQ_HEADERS)) {
|
||||||
event->headers = header;
|
esl_event_del_header(event, header_name);
|
||||||
if (!event->last_header) {
|
}
|
||||||
|
|
||||||
|
memset(header, 0, sizeof(*header));
|
||||||
|
|
||||||
|
header->name = DUP(header_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((stack & ESL_STACK_PUSH) || (stack & ESL_STACK_UNSHIFT)) {
|
||||||
|
char **m = NULL;
|
||||||
|
esl_size_t len = 0;
|
||||||
|
char *hv;
|
||||||
|
int i = 0, j = 0;
|
||||||
|
|
||||||
|
esl_set_flag(event, ESL_EF_CONTAINS_ARRAYS);
|
||||||
|
|
||||||
|
if (header->value && !header->idx) {
|
||||||
|
m = malloc(sizeof(char *));
|
||||||
|
esl_assert(m);
|
||||||
|
m[0] = header->value;
|
||||||
|
header->value = NULL;
|
||||||
|
header->array = m;
|
||||||
|
header->idx++;
|
||||||
|
m = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = header->idx + 1;
|
||||||
|
m = realloc(header->array, sizeof(char *) * i);
|
||||||
|
esl_assert(m);
|
||||||
|
|
||||||
|
if ((stack & ESL_STACK_PUSH)) {
|
||||||
|
m[header->idx] = data;
|
||||||
|
} else if ((stack & ESL_STACK_UNSHIFT)) {
|
||||||
|
for (j = header->idx; j > 0; j--) {
|
||||||
|
m[j] = m[j-1];
|
||||||
|
}
|
||||||
|
m[0] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
header->idx++;
|
||||||
|
header->array = m;
|
||||||
|
|
||||||
|
for(j = 0; j < header->idx; j++) {
|
||||||
|
len += strlen(header->array[j]) + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len) {
|
||||||
|
len += 8;
|
||||||
|
hv = realloc(header->value, len);
|
||||||
|
esl_assert(hv);
|
||||||
|
header->value = hv;
|
||||||
|
esl_snprintf(header->value, len, "ARRAY::");
|
||||||
|
for(j = 0; j < header->idx; j++) {
|
||||||
|
esl_snprintf(header->value + strlen(header->value), len - strlen(header->value), "%s%s", j == 0 ? "" : "::", header->array[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
header->value = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
header->hash = esl_ci_hashfunc_default(header->name, &hlen);
|
||||||
|
|
||||||
|
if ((stack & ESL_STACK_TOP)) {
|
||||||
|
header->next = event->headers;
|
||||||
|
event->headers = header;
|
||||||
|
if (!event->last_header) {
|
||||||
|
event->last_header = header;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (event->last_header) {
|
||||||
|
event->last_header->next = header;
|
||||||
|
} else {
|
||||||
|
event->headers = header;
|
||||||
|
header->next = NULL;
|
||||||
|
}
|
||||||
event->last_header = header;
|
event->last_header = header;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (event->last_header) {
|
|
||||||
event->last_header->next = header;
|
|
||||||
} else {
|
|
||||||
event->headers = header;
|
|
||||||
header->next = NULL;
|
|
||||||
}
|
|
||||||
event->last_header = header;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ESL_SUCCESS;
|
return ESL_SUCCESS;
|
||||||
@ -386,48 +509,98 @@ ESL_DECLARE(esl_status_t) esl_event_add_body(esl_event_t *event, const char *fmt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ESL_DECLARE(void) esl_event_destroy(esl_event_t **event)
|
ESL_DECLARE(void) esl_event_destroy(esl_event_t **event)
|
||||||
{
|
{
|
||||||
esl_event_t *ep = *event, *this_event;
|
esl_event_t *ep = *event;
|
||||||
esl_event_header_t *hp, *this_header;
|
esl_event_header_t *hp, *this;
|
||||||
|
|
||||||
for (ep = *event ; ep ;) {
|
if (ep) {
|
||||||
this_event = ep;
|
for (hp = ep->headers; hp;) {
|
||||||
ep = ep->next;
|
this = hp;
|
||||||
|
|
||||||
for (hp = this_event->headers; hp;) {
|
|
||||||
this_header = hp;
|
|
||||||
hp = hp->next;
|
hp = hp->next;
|
||||||
FREE(this_header->name);
|
FREE(this->name);
|
||||||
FREE(this_header->value);
|
|
||||||
memset(this_header, 0, sizeof(*this_header));
|
if (this->idx) {
|
||||||
FREE(this_header);
|
int i = 0;
|
||||||
|
this->value = NULL;
|
||||||
|
for (i = 0; i < this->idx; i++) {
|
||||||
|
FREE(this->array[i]);
|
||||||
|
}
|
||||||
|
FREE(this->array);
|
||||||
|
}
|
||||||
|
|
||||||
|
FREE(this->value);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ESL_EVENT_RECYCLE
|
||||||
|
if (esl_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, this) != ESL_SUCCESS) {
|
||||||
|
FREE(this);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
FREE(this);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
FREE(this_event->body);
|
FREE(ep->body);
|
||||||
FREE(this_event->subclass_name);
|
FREE(ep->subclass_name);
|
||||||
memset(this_event, 0, sizeof(*this_event));
|
#ifdef ESL_EVENT_RECYCLE
|
||||||
FREE(this_event);
|
if (esl_queue_trypush(EVENT_RECYCLE_QUEUE, ep) != ESL_SUCCESS) {
|
||||||
|
FREE(ep);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
FREE(ep);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
*event = NULL;
|
*event = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ESL_DECLARE(void) esl_event_merge(esl_event_t *event, esl_event_t *tomerge)
|
||||||
|
{
|
||||||
|
esl_event_header_t *hp;
|
||||||
|
|
||||||
|
esl_assert(tomerge && event);
|
||||||
|
|
||||||
|
for (hp = tomerge->headers; hp; hp = hp->next) {
|
||||||
|
if (hp->idx) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < hp->idx; i++) {
|
||||||
|
esl_event_add_header_string(event, ESL_STACK_PUSH, hp->name, hp->array[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
esl_event_add_header_string(event, ESL_STACK_BOTTOM, hp->name, hp->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ESL_DECLARE(esl_status_t) esl_event_dup(esl_event_t **event, esl_event_t *todup)
|
ESL_DECLARE(esl_status_t) esl_event_dup(esl_event_t **event, esl_event_t *todup)
|
||||||
{
|
{
|
||||||
esl_event_header_t *hp;
|
esl_event_header_t *hp;
|
||||||
|
|
||||||
if (esl_event_create_subclass(event, ESL_EVENT_CLONE, todup->subclass_name) != ESL_SUCCESS) {
|
if (esl_event_create_subclass(event, ESL_EVENT_CLONE, todup->subclass_name) != ESL_SUCCESS) {
|
||||||
return ESL_FAIL;
|
return ESL_GENERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*event)->event_id = todup->event_id;
|
(*event)->event_id = todup->event_id;
|
||||||
|
|
||||||
(*event)->event_user_data = todup->event_user_data;
|
(*event)->event_user_data = todup->event_user_data;
|
||||||
(*event)->bind_user_data = todup->bind_user_data;
|
(*event)->bind_user_data = todup->bind_user_data;
|
||||||
|
(*event)->flags = todup->flags;
|
||||||
for (hp = todup->headers; hp; hp = hp->next) {
|
for (hp = todup->headers; hp; hp = hp->next) {
|
||||||
esl_event_add_header_string(*event, ESL_STACK_BOTTOM, hp->name, hp->value);
|
if (todup->subclass_name && !strcmp(hp->name, "Event-Subclass")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hp->idx) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < hp->idx; i++) {
|
||||||
|
esl_event_add_header_string(*event, ESL_STACK_PUSH, hp->name, hp->array[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
esl_event_add_header_string(*event, ESL_STACK_BOTTOM, hp->name, hp->value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (todup->body) {
|
if (todup->body) {
|
||||||
@ -439,97 +612,26 @@ ESL_DECLARE(esl_status_t) esl_event_dup(esl_event_t **event, esl_event_t *todup)
|
|||||||
return ESL_SUCCESS;
|
return ESL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ESL_DECLARE(esl_status_t) esl_event_create_json(esl_event_t **event, const char *json)
|
|
||||||
{
|
|
||||||
esl_event_t *new_event;
|
|
||||||
cJSON *cj, *cjp;
|
|
||||||
|
|
||||||
|
|
||||||
if (!(cj = cJSON_Parse(json))) {
|
|
||||||
return ESL_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esl_event_create(&new_event, ESL_EVENT_CLONE) != ESL_SUCCESS) {
|
|
||||||
cJSON_Delete(cj);
|
|
||||||
return ESL_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (cjp = cj->child; cjp; cjp = cjp->next) {
|
|
||||||
char *name = cjp->string;
|
|
||||||
char *value = cjp->valuestring;
|
|
||||||
|
|
||||||
if (name && value) {
|
|
||||||
if (!strcasecmp(name, "_body")) {
|
|
||||||
esl_event_add_body(new_event, value);
|
|
||||||
} else {
|
|
||||||
if (!strcasecmp(name, "event-name")) {
|
|
||||||
esl_event_del_header(new_event, "event-name");
|
|
||||||
}
|
|
||||||
|
|
||||||
esl_name_event(value, &new_event->event_id);
|
|
||||||
esl_event_add_header_string(new_event, ESL_STACK_BOTTOM, name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cJSON_Delete(cj);
|
|
||||||
*event = new_event;
|
|
||||||
return ESL_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESL_DECLARE(esl_status_t) esl_event_serialize_json(esl_event_t *event, char **str)
|
|
||||||
{
|
|
||||||
esl_event_header_t *hp;
|
|
||||||
cJSON *cj;
|
|
||||||
|
|
||||||
*str = NULL;
|
|
||||||
|
|
||||||
cj = cJSON_CreateObject();
|
|
||||||
|
|
||||||
for (hp = event->headers; hp; hp = hp->next) {
|
|
||||||
cJSON_AddItemToObject(cj, hp->name, cJSON_CreateString(hp->value));
|
|
||||||
}
|
|
||||||
if (event->body) {
|
|
||||||
int blen = (int) strlen(event->body);
|
|
||||||
char tmp[25];
|
|
||||||
|
|
||||||
esl_snprintf(tmp, sizeof(tmp), "%d", blen);
|
|
||||||
|
|
||||||
cJSON_AddItemToObject(cj, "Content-Length", cJSON_CreateString(tmp));
|
|
||||||
cJSON_AddItemToObject(cj, "_body", cJSON_CreateString(event->body));
|
|
||||||
}
|
|
||||||
|
|
||||||
*str = cJSON_Print(cj);
|
|
||||||
cJSON_Delete(cj);
|
|
||||||
|
|
||||||
return ESL_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESL_DECLARE(esl_status_t) esl_event_serialize(esl_event_t *event, char **str, esl_bool_t encode)
|
ESL_DECLARE(esl_status_t) esl_event_serialize(esl_event_t *event, char **str, esl_bool_t encode)
|
||||||
{
|
{
|
||||||
size_t len = 0;
|
esl_size_t len = 0;
|
||||||
esl_event_header_t *hp;
|
esl_event_header_t *hp;
|
||||||
size_t llen = 0, dlen = 0, blocksize = 512, encode_len = 1536, new_len = 0;
|
esl_size_t llen = 0, dlen = 0, blocksize = 512, encode_len = 1536, new_len = 0;
|
||||||
char *buf;
|
char *buf;
|
||||||
char *encode_buf = NULL; /* used for url encoding of variables to make sure unsafe things stay out of the serialized copy */
|
char *encode_buf = NULL; /* used for url encoding of variables to make sure unsafe things stay out of the serialized copy */
|
||||||
int clen = 0;
|
|
||||||
|
|
||||||
if (!event || !event->headers)
|
|
||||||
return ESL_FAIL;
|
|
||||||
|
|
||||||
*str = NULL;
|
*str = NULL;
|
||||||
|
|
||||||
dlen = blocksize * 2;
|
dlen = blocksize * 2;
|
||||||
|
|
||||||
if (!(buf = malloc(dlen))) {
|
if (!(buf = malloc(dlen))) {
|
||||||
return ESL_FAIL;
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* go ahead and give ourselves some space to work with, should save a few reallocs */
|
/* go ahead and give ourselves some space to work with, should save a few reallocs */
|
||||||
if (!(encode_buf = malloc(encode_len))) {
|
if (!(encode_buf = malloc(encode_len))) {
|
||||||
esl_safe_free(buf);
|
abort();
|
||||||
return ESL_FAIL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* esl_log_printf(ESL_CHANNEL_LOG, ESL_LOG_INFO, "hit serialized!.\n"); */
|
/* esl_log_printf(ESL_CHANNEL_LOG, ESL_LOG_INFO, "hit serialized!.\n"); */
|
||||||
@ -542,38 +644,39 @@ ESL_DECLARE(esl_status_t) esl_event_serialize(esl_event_t *event, char **str, es
|
|||||||
* destroying loop.
|
* destroying loop.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!strcasecmp(hp->name, "content-length")) {
|
if (hp->idx) {
|
||||||
clen++;
|
int i;
|
||||||
|
new_len = 0;
|
||||||
|
for(i = 0; i < hp->idx; i++) {
|
||||||
|
new_len += (strlen(hp->array[i]) * 3) + 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
new_len = (strlen(hp->value) * 3) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
new_len = (strlen(hp->value) * 3) + 1;
|
|
||||||
|
|
||||||
if (encode_len < new_len) {
|
if (encode_len < new_len) {
|
||||||
char *tmp;
|
char *tmp;
|
||||||
/* esl_log_printf(ESL_CHANNEL_LOG, ESL_LOG_INFO, "Allocing %d was %d.\n", ((strlen(hp->value) * 3) + 1), encode_len); */
|
|
||||||
/* we can use realloc for initial alloc as well, if encode_buf is zero it treats it as a malloc */
|
|
||||||
|
|
||||||
/* keep track of the size of our allocation */
|
/* keep track of the size of our allocation */
|
||||||
encode_len = new_len;
|
encode_len = new_len;
|
||||||
|
|
||||||
if (!(tmp = realloc(encode_buf, encode_len))) {
|
if (!(tmp = realloc(encode_buf, encode_len))) {
|
||||||
/* oh boy, ram's gone, give back what little we grabbed and bail */
|
abort();
|
||||||
esl_safe_free(buf);
|
|
||||||
esl_safe_free(encode_buf);
|
|
||||||
return ESL_FAIL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
encode_buf = tmp;
|
encode_buf = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle any bad things in the string like newlines : etc that screw up the serialized format */
|
/* handle any bad things in the string like newlines : etc that screw up the serialized format */
|
||||||
|
|
||||||
|
|
||||||
if (encode) {
|
if (encode) {
|
||||||
esl_url_encode(hp->value, encode_buf, encode_len);
|
esl_url_encode(hp->value, encode_buf, encode_len);
|
||||||
} else {
|
} else {
|
||||||
esl_snprintf(encode_buf, encode_len, "%s", hp->value);
|
esl_snprintf(encode_buf, encode_len, "[%s]", hp->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
llen = strlen(hp->name) + strlen(encode_buf) + 8;
|
llen = strlen(hp->name) + strlen(encode_buf) + 8;
|
||||||
|
|
||||||
if ((len + llen) > dlen) {
|
if ((len + llen) > dlen) {
|
||||||
@ -582,14 +685,11 @@ ESL_DECLARE(esl_status_t) esl_event_serialize(esl_event_t *event, char **str, es
|
|||||||
if ((m = realloc(buf, dlen))) {
|
if ((m = realloc(buf, dlen))) {
|
||||||
buf = m;
|
buf = m;
|
||||||
} else {
|
} else {
|
||||||
/* we seem to be out of memory trying to resize the serialize string, give back what we already have and give up */
|
abort();
|
||||||
esl_safe_free(buf);
|
|
||||||
esl_safe_free(encode_buf);
|
|
||||||
return ESL_FAIL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(buf + len, dlen - len, "%s: %s\n", hp->name, *encode_buf == '\0' ? "_undef_" : encode_buf);
|
esl_snprintf(buf + len, dlen - len, "%s: %s\n", hp->name, *encode_buf == '\0' ? "_undef_" : encode_buf);
|
||||||
len = strlen(buf);
|
len = strlen(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -612,29 +712,115 @@ ESL_DECLARE(esl_status_t) esl_event_serialize(esl_event_t *event, char **str, es
|
|||||||
if ((m = realloc(buf, dlen))) {
|
if ((m = realloc(buf, dlen))) {
|
||||||
buf = m;
|
buf = m;
|
||||||
} else {
|
} else {
|
||||||
esl_safe_free(buf);
|
abort();
|
||||||
return ESL_FAIL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blen) {
|
if (blen) {
|
||||||
if (clen) {
|
esl_snprintf(buf + len, dlen - len, "Content-Length: %d\n\n%s", blen, event->body);
|
||||||
snprintf(buf + len, dlen - len, "\n%s", event->body);
|
} else {
|
||||||
} else {
|
esl_snprintf(buf + len, dlen - len, "\n");
|
||||||
snprintf(buf + len, dlen - len, "Content-Length: %d\n\n%s", (int)strlen(event->body), event->body);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
snprintf(buf + len, dlen - len, "\n");
|
esl_snprintf(buf + len, dlen - len, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
*str = buf;
|
*str = buf;
|
||||||
|
|
||||||
return ESL_SUCCESS;
|
return ESL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ESL_DECLARE(esl_status_t) esl_event_create_json(esl_event_t **event, const char *json)
|
||||||
|
{
|
||||||
|
esl_event_t *new_event;
|
||||||
|
cJSON *cj, *cjp;
|
||||||
|
|
||||||
|
|
||||||
|
if (!(cj = cJSON_Parse(json))) {
|
||||||
|
return ESL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (esl_event_create(&new_event, ESL_EVENT_CLONE) != ESL_SUCCESS) {
|
||||||
|
cJSON_Delete(cj);
|
||||||
|
return ESL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (cjp = cj->child; cjp; cjp = cjp->next) {
|
||||||
|
char *name = cjp->string;
|
||||||
|
char *value = cjp->valuestring;
|
||||||
|
|
||||||
|
if (name && value) {
|
||||||
|
if (!strcasecmp(name, "_body")) {
|
||||||
|
esl_event_add_body(new_event, value, ESL_VA_NONE);
|
||||||
|
} else {
|
||||||
|
if (!strcasecmp(name, "event-name")) {
|
||||||
|
esl_event_del_header(new_event, "event-name");
|
||||||
|
esl_name_event(value, &new_event->event_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
esl_event_add_header_string(new_event, ESL_STACK_BOTTOM, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (name) {
|
||||||
|
if (cjp->type == cJSON_Array) {
|
||||||
|
int i, x = cJSON_GetArraySize(cjp);
|
||||||
|
|
||||||
|
for (i = 0; i < x; i++) {
|
||||||
|
cJSON *item = cJSON_GetArrayItem(cjp, i);
|
||||||
|
|
||||||
|
if (item && item->type == cJSON_String && item->valuestring) {
|
||||||
|
esl_event_add_header_string(new_event, ESL_STACK_PUSH, name, item->valuestring);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cJSON_Delete(cj);
|
||||||
|
*event = new_event;
|
||||||
|
return ESL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESL_DECLARE(esl_status_t) esl_event_serialize_json(esl_event_t *event, char **str)
|
||||||
|
{
|
||||||
|
esl_event_header_t *hp;
|
||||||
|
cJSON *cj;
|
||||||
|
|
||||||
|
*str = NULL;
|
||||||
|
|
||||||
|
cj = cJSON_CreateObject();
|
||||||
|
|
||||||
|
for (hp = event->headers; hp; hp = hp->next) {
|
||||||
|
if (hp->idx) {
|
||||||
|
cJSON *a = cJSON_CreateArray();
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < hp->idx; i++) {
|
||||||
|
cJSON_AddItemToArray(a, cJSON_CreateString(hp->array[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
cJSON_AddItemToObject(cj, hp->name, a);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
cJSON_AddItemToObject(cj, hp->name, cJSON_CreateString(hp->value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event->body) {
|
||||||
|
int blen = (int) strlen(event->body);
|
||||||
|
char tmp[25];
|
||||||
|
|
||||||
|
esl_snprintf(tmp, sizeof(tmp), "%d", blen);
|
||||||
|
|
||||||
|
cJSON_AddItemToObject(cj, "Content-Length", cJSON_CreateString(tmp));
|
||||||
|
cJSON_AddItemToObject(cj, "_body", cJSON_CreateString(event->body));
|
||||||
|
}
|
||||||
|
|
||||||
|
*str = cJSON_Print(cj);
|
||||||
|
cJSON_Delete(cj);
|
||||||
|
|
||||||
|
return ESL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/* For Emacs:
|
/* For Emacs:
|
||||||
* Local Variables:
|
* Local Variables:
|
||||||
|
@ -42,6 +42,7 @@ extern "C" {
|
|||||||
|
|
||||||
#define esl_copy_string(_x, _y, _z) strncpy(_x, _y, _z - 1)
|
#define esl_copy_string(_x, _y, _z) strncpy(_x, _y, _z - 1)
|
||||||
#define esl_set_string(_x, _y) esl_copy_string(_x, _y, sizeof(_x))
|
#define esl_set_string(_x, _y) esl_copy_string(_x, _y, sizeof(_x))
|
||||||
|
#define ESL_VA_NONE "%s", ""
|
||||||
|
|
||||||
typedef struct esl_event_header esl_event_header_t;
|
typedef struct esl_event_header esl_event_header_t;
|
||||||
typedef struct esl_event esl_event_t;
|
typedef struct esl_event esl_event_t;
|
||||||
@ -262,7 +263,8 @@ typedef enum {
|
|||||||
ESL_SUCCESS,
|
ESL_SUCCESS,
|
||||||
ESL_FAIL,
|
ESL_FAIL,
|
||||||
ESL_BREAK,
|
ESL_BREAK,
|
||||||
ESL_DISCONNECTED
|
ESL_DISCONNECTED,
|
||||||
|
ESL_GENERR
|
||||||
} esl_status_t;
|
} esl_status_t;
|
||||||
|
|
||||||
#define BUF_CHUNK 65536 * 50
|
#define BUF_CHUNK 65536 * 50
|
||||||
@ -309,6 +311,10 @@ typedef struct {
|
|||||||
int destroyed;
|
int destroyed;
|
||||||
} esl_handle_t;
|
} esl_handle_t;
|
||||||
|
|
||||||
|
#define esl_test_flag(obj, flag) ((obj)->flags & flag)
|
||||||
|
#define esl_set_flag(obj, flag) (obj)->flags |= (flag)
|
||||||
|
#define esl_clear_flag(obj, flag) (obj)->flags &= ~(flag)
|
||||||
|
|
||||||
/*! \brief Used internally for truth test */
|
/*! \brief Used internally for truth test */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ESL_TRUE = 1,
|
ESL_TRUE = 1,
|
||||||
@ -453,6 +459,8 @@ ESL_DECLARE(esl_status_t) esl_events(esl_handle_t *handle, esl_event_type_t etyp
|
|||||||
|
|
||||||
ESL_DECLARE(int) esl_wait_sock(esl_socket_t sock, uint32_t ms, esl_poll_t flags);
|
ESL_DECLARE(int) esl_wait_sock(esl_socket_t sock, uint32_t ms, esl_poll_t flags);
|
||||||
|
|
||||||
|
ESL_DECLARE(unsigned int) esl_separate_string_string(char *buf, const char *delim, char **array, unsigned int arraylen);
|
||||||
|
|
||||||
#define esl_recv(_h) esl_recv_event(_h, 0, NULL)
|
#define esl_recv(_h) esl_recv_event(_h, 0, NULL)
|
||||||
#define esl_recv_timed(_h, _ms) esl_recv_event_timed(_h, _ms, 0, NULL)
|
#define esl_recv_timed(_h, _ms) esl_recv_event_timed(_h, _ms, 0, NULL)
|
||||||
|
|
||||||
|
@ -42,7 +42,9 @@ extern "C" {
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ESL_STACK_BOTTOM,
|
ESL_STACK_BOTTOM,
|
||||||
ESL_STACK_TOP
|
ESL_STACK_TOP,
|
||||||
|
ESL_STACK_PUSH,
|
||||||
|
ESL_STACK_UNSHIFT
|
||||||
} esl_stack_t;
|
} esl_stack_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -141,6 +143,10 @@ typedef enum {
|
|||||||
char *name;
|
char *name;
|
||||||
/*! the header value */
|
/*! the header value */
|
||||||
char *value;
|
char *value;
|
||||||
|
/*! array space */
|
||||||
|
char **array;
|
||||||
|
/*! array index */
|
||||||
|
int idx;
|
||||||
/*! hash of the header name */
|
/*! hash of the header name */
|
||||||
unsigned long hash;
|
unsigned long hash;
|
||||||
struct esl_event_header *next;
|
struct esl_event_header *next;
|
||||||
@ -174,7 +180,8 @@ struct esl_event {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ESL_UNIQ_HEADERS = (1 << 0)
|
ESL_EF_UNIQ_HEADERS = (1 << 0),
|
||||||
|
ESL_EF_CONTAINS_ARRAYS = (1 << 1)
|
||||||
} esl_event_flag_t;
|
} esl_event_flag_t;
|
||||||
|
|
||||||
|
|
||||||
@ -203,7 +210,11 @@ ESL_DECLARE(esl_status_t) esl_event_set_priority(esl_event_t *event, esl_priorit
|
|||||||
\param header_name the name of the header to read
|
\param header_name the name of the header to read
|
||||||
\return the value of the requested header
|
\return the value of the requested header
|
||||||
*/
|
*/
|
||||||
ESL_DECLARE(char *)esl_event_get_header(esl_event_t *event, const char *header_name);
|
|
||||||
|
|
||||||
|
ESL_DECLARE(esl_event_header_t *) esl_event_get_header_ptr(esl_event_t *event, const char *header_name);
|
||||||
|
ESL_DECLARE(char *) esl_event_get_header_idx(esl_event_t *event, const char *header_name, int idx);
|
||||||
|
#define esl_event_get_header(_e, _h) esl_event_get_header_idx(_e, _h, -1)
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Retrieve the body value from an event
|
\brief Retrieve the body value from an event
|
||||||
@ -250,6 +261,7 @@ ESL_DECLARE(void) esl_event_destroy(esl_event_t **event);
|
|||||||
\return ESL_SUCCESS if the event was duplicated
|
\return ESL_SUCCESS if the event was duplicated
|
||||||
*/
|
*/
|
||||||
ESL_DECLARE(esl_status_t) esl_event_dup(esl_event_t **event, esl_event_t *todup);
|
ESL_DECLARE(esl_status_t) esl_event_dup(esl_event_t **event, esl_event_t *todup);
|
||||||
|
ESL_DECLARE(void) esl_event_merge(esl_event_t *event, esl_event_t *tomerge);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Render the name of an event id enumeration
|
\brief Render the name of an event id enumeration
|
||||||
|
@ -251,6 +251,8 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_profile_var(switch_channel_t
|
|||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_var_check(switch_channel_t *channel,
|
SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_var_check(switch_channel_t *channel,
|
||||||
const char *varname, const char *value, switch_bool_t var_check);
|
const char *varname, const char *value, switch_bool_t var_check);
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_channel_add_variable_var_check(switch_channel_t *channel,
|
||||||
|
const char *varname, const char *value, switch_bool_t var_check, switch_stack_t stack);
|
||||||
SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_printf(switch_channel_t *channel, const char *varname, const char *fmt, ...);
|
SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_printf(switch_channel_t *channel, const char *varname, const char *fmt, ...);
|
||||||
SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_name_printf(switch_channel_t *channel, const char *val, const char *fmt, ...);
|
SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_name_printf(switch_channel_t *channel, const char *val, const char *fmt, ...);
|
||||||
|
|
||||||
@ -284,8 +286,8 @@ SWITCH_DECLARE(switch_status_t) switch_channel_export_variable_printf(switch_cha
|
|||||||
\param varname the name of the variable
|
\param varname the name of the variable
|
||||||
\return the value of the requested variable
|
\return the value of the requested variable
|
||||||
*/
|
*/
|
||||||
SWITCH_DECLARE(const char *) switch_channel_get_variable_dup(switch_channel_t *channel, const char *varname, switch_bool_t dup);
|
SWITCH_DECLARE(const char *) switch_channel_get_variable_dup(switch_channel_t *channel, const char *varname, switch_bool_t dup, int idx);
|
||||||
#define switch_channel_get_variable(_c, _v) switch_channel_get_variable_dup(_c, _v, SWITCH_TRUE)
|
#define switch_channel_get_variable(_c, _v) switch_channel_get_variable_dup(_c, _v, SWITCH_TRUE, -1)
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_channel_get_variables(switch_channel_t *channel, switch_event_t **event);
|
SWITCH_DECLARE(switch_status_t) switch_channel_get_variables(switch_channel_t *channel, switch_event_t **event);
|
||||||
|
|
||||||
|
@ -67,6 +67,10 @@ SWITCH_BEGIN_EXTERN_C
|
|||||||
char *name;
|
char *name;
|
||||||
/*! the header value */
|
/*! the header value */
|
||||||
char *value;
|
char *value;
|
||||||
|
/*! array space */
|
||||||
|
char **array;
|
||||||
|
/*! array index */
|
||||||
|
int idx;
|
||||||
/*! hash of the header name */
|
/*! hash of the header name */
|
||||||
unsigned long hash;
|
unsigned long hash;
|
||||||
struct switch_event_header *next;
|
struct switch_event_header *next;
|
||||||
@ -99,7 +103,8 @@ struct switch_event {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
EF_UNIQ_HEADERS = (1 << 0)
|
EF_UNIQ_HEADERS = (1 << 0),
|
||||||
|
EF_CONTAINS_ARRAYS = (1 << 1),
|
||||||
} switch_event_flag_t;
|
} switch_event_flag_t;
|
||||||
|
|
||||||
|
|
||||||
@ -146,7 +151,10 @@ SWITCH_DECLARE(switch_status_t) switch_event_set_priority(switch_event_t *event,
|
|||||||
\param header_name the name of the header to read
|
\param header_name the name of the header to read
|
||||||
\return the value of the requested header
|
\return the value of the requested header
|
||||||
*/
|
*/
|
||||||
_Ret_opt_z_ SWITCH_DECLARE(char *) switch_event_get_header(switch_event_t *event, const char *header_name);
|
|
||||||
|
_Ret_opt_z_ SWITCH_DECLARE(switch_event_header_t *) switch_event_get_header_ptr(switch_event_t *event, const char *header_name);
|
||||||
|
_Ret_opt_z_ SWITCH_DECLARE(char *) switch_event_get_header_idx(switch_event_t *event, const char *header_name, int idx);
|
||||||
|
#define switch_event_get_header(_e, _h) switch_event_get_header_idx(_e, _h, -1)
|
||||||
|
|
||||||
#define switch_event_get_header_nil(e, h) switch_str_nil(switch_event_get_header(e,h))
|
#define switch_event_get_header_nil(e, h) switch_str_nil(switch_event_get_header(e,h))
|
||||||
|
|
||||||
|
@ -70,6 +70,8 @@ SWITCH_DECLARE(switch_status_t) switch_regex_match(const char *target, const cha
|
|||||||
*/
|
*/
|
||||||
SWITCH_DECLARE(switch_status_t) switch_regex_match_partial(const char *target, const char *expression, int *partial_match);
|
SWITCH_DECLARE(switch_status_t) switch_regex_match_partial(const char *target, const char *expression, int *partial_match);
|
||||||
|
|
||||||
|
SWITCH_DECLARE(void) switch_capture_regex(switch_regex_t *re, int match_count, const char *field_data,
|
||||||
|
int *ovector, const char *var, switch_cap_callback_t callback, void *user_data);
|
||||||
|
|
||||||
#define switch_regex_safe_free(re) if (re) {\
|
#define switch_regex_safe_free(re) if (re) {\
|
||||||
switch_regex_free(re);\
|
switch_regex_free(re);\
|
||||||
|
@ -830,7 +830,9 @@ SWITCH_STACK_TOP - Stack on the top
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
SWITCH_STACK_BOTTOM = (1 << 0),
|
SWITCH_STACK_BOTTOM = (1 << 0),
|
||||||
SWITCH_STACK_TOP = (1 << 1),
|
SWITCH_STACK_TOP = (1 << 1),
|
||||||
SWITCH_STACK_NODUP = (1 << 2)
|
SWITCH_STACK_NODUP = (1 << 2),
|
||||||
|
SWITCH_STACK_UNSHIFT = (1 << 3),
|
||||||
|
SWITCH_STACK_PUSH = (1 << 4),
|
||||||
} switch_stack_t;
|
} switch_stack_t;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1688,6 +1690,7 @@ struct switch_console_callback_match {
|
|||||||
};
|
};
|
||||||
typedef struct switch_console_callback_match switch_console_callback_match_t;
|
typedef struct switch_console_callback_match switch_console_callback_match_t;
|
||||||
|
|
||||||
|
typedef void (*switch_cap_callback_t) (const char *var, const char *val, void *user_data);
|
||||||
typedef switch_status_t (*switch_console_complete_callback_t) (const char *, const char *, switch_console_callback_match_t **matches);
|
typedef switch_status_t (*switch_console_complete_callback_t) (const char *, const char *, switch_console_callback_match_t **matches);
|
||||||
typedef switch_bool_t (*switch_media_bug_callback_t) (switch_media_bug_t *, void *, switch_abc_type_t);
|
typedef switch_bool_t (*switch_media_bug_callback_t) (switch_media_bug_t *, void *, switch_abc_type_t);
|
||||||
typedef switch_bool_t (*switch_tone_detect_callback_t) (switch_core_session_t *, const char *, const char *);
|
typedef switch_bool_t (*switch_tone_detect_callback_t) (switch_core_session_t *, const char *, const char *);
|
||||||
|
@ -1033,7 +1033,7 @@ SWITCH_STANDARD_APP(sched_cancel_function)
|
|||||||
switch_scheduler_del_task_group(group);
|
switch_scheduler_del_task_group(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_STANDARD_APP(set_function)
|
static void base_set (switch_core_session_t *session, const char *data, switch_stack_t stack)
|
||||||
{
|
{
|
||||||
char *var, *val = NULL;
|
char *var, *val = NULL;
|
||||||
|
|
||||||
@ -1044,7 +1044,10 @@ SWITCH_STANDARD_APP(set_function)
|
|||||||
char *expanded = NULL;
|
char *expanded = NULL;
|
||||||
|
|
||||||
var = switch_core_session_strdup(session, data);
|
var = switch_core_session_strdup(session, data);
|
||||||
val = strchr(var, '=');
|
|
||||||
|
if (!(val = strchr(var, '='))) {
|
||||||
|
val = strchr(var, ',');
|
||||||
|
}
|
||||||
|
|
||||||
if (val) {
|
if (val) {
|
||||||
*val++ = '\0';
|
*val++ = '\0';
|
||||||
@ -1059,7 +1062,7 @@ SWITCH_STANDARD_APP(set_function)
|
|||||||
|
|
||||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SET [%s]=[%s]\n", switch_channel_get_name(channel), var,
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SET [%s]=[%s]\n", switch_channel_get_name(channel), var,
|
||||||
expanded ? expanded : "UNDEF");
|
expanded ? expanded : "UNDEF");
|
||||||
switch_channel_set_variable_var_check(channel, var, expanded, SWITCH_FALSE);
|
switch_channel_add_variable_var_check(channel, var, expanded, SWITCH_FALSE, stack);
|
||||||
|
|
||||||
if (expanded && expanded != val) {
|
if (expanded && expanded != val) {
|
||||||
switch_safe_free(expanded);
|
switch_safe_free(expanded);
|
||||||
@ -1067,6 +1070,21 @@ SWITCH_STANDARD_APP(set_function)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SWITCH_STANDARD_APP(set_function)
|
||||||
|
{
|
||||||
|
base_set(session, data, SWITCH_STACK_BOTTOM);
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_STANDARD_APP(push_function)
|
||||||
|
{
|
||||||
|
base_set(session, data, SWITCH_STACK_PUSH);
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_STANDARD_APP(unshift_function)
|
||||||
|
{
|
||||||
|
base_set(session, data, SWITCH_STACK_UNSHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
SWITCH_STANDARD_APP(set_global_function)
|
SWITCH_STANDARD_APP(set_global_function)
|
||||||
{
|
{
|
||||||
char *var, *val = NULL;
|
char *var, *val = NULL;
|
||||||
@ -3769,6 +3787,13 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
|
|||||||
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
|
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
|
||||||
SWITCH_ADD_APP(app_interface, "set", "Set a channel variable", SET_LONG_DESC, set_function, "<varname>=<value>",
|
SWITCH_ADD_APP(app_interface, "set", "Set a channel variable", SET_LONG_DESC, set_function, "<varname>=<value>",
|
||||||
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
|
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
|
||||||
|
|
||||||
|
SWITCH_ADD_APP(app_interface, "push", "Set a channel variable", SET_LONG_DESC, push_function, "<varname>=<value>",
|
||||||
|
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
|
||||||
|
|
||||||
|
SWITCH_ADD_APP(app_interface, "unshift", "Set a channel variable", SET_LONG_DESC, unshift_function, "<varname>=<value>",
|
||||||
|
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
|
||||||
|
|
||||||
SWITCH_ADD_APP(app_interface, "set_global", "Set a global variable", SET_GLOBAL_LONG_DESC, set_global_function, "<varname>=<value>",
|
SWITCH_ADD_APP(app_interface, "set_global", "Set a global variable", SET_GLOBAL_LONG_DESC, set_global_function, "<varname>=<value>",
|
||||||
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
|
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
|
||||||
SWITCH_ADD_APP(app_interface, "set_profile_var", "Set a caller profile variable", SET_PROFILE_VAR_LONG_DESC, set_profile_var_function,
|
SWITCH_ADD_APP(app_interface, "set_profile_var", "Set a caller profile variable", SET_PROFILE_VAR_LONG_DESC, set_profile_var_function,
|
||||||
|
@ -79,6 +79,13 @@ static switch_status_t exec_app(switch_core_session_t *session, const char *app,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_var_callback(const char *var, const char *val, void *user_data)
|
||||||
|
{
|
||||||
|
switch_core_session_t *session = (switch_core_session_t *) user_data;
|
||||||
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||||
|
switch_channel_add_variable_var_check(channel, var, val, SWITCH_FALSE, SWITCH_STACK_PUSH);
|
||||||
|
}
|
||||||
|
|
||||||
static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *caller_profile, switch_xml_t xexten, switch_caller_extension_t **extension)
|
static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *caller_profile, switch_xml_t xexten, switch_caller_extension_t **extension)
|
||||||
{
|
{
|
||||||
switch_xml_t xcond, xaction, xexpression;
|
switch_xml_t xcond, xaction, xexpression;
|
||||||
@ -222,6 +229,11 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *
|
|||||||
proceed = 1;
|
proceed = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (field && strchr(expression, '(')) {
|
||||||
|
switch_channel_set_variable(channel, "DP_MATCH", NULL);
|
||||||
|
switch_capture_regex(re, proceed, field_data, ovector, "DP_MATCH", set_var_callback, session);
|
||||||
|
}
|
||||||
|
|
||||||
for (xaction = switch_xml_child(xcond, "action"); xaction; xaction = xaction->next) {
|
for (xaction = switch_xml_child(xcond, "action"); xaction; xaction = xaction->next) {
|
||||||
char *application = (char *) switch_xml_attr_soft(xaction, "application");
|
char *application = (char *) switch_xml_attr_soft(xaction, "application");
|
||||||
const char *loop = switch_xml_attr(xaction, "loop");
|
const char *loop = switch_xml_attr(xaction, "loop");
|
||||||
|
@ -5332,11 +5332,11 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName
|
|||||||
|
|
||||||
tech_pvt->dest = switch_core_session_sprintf(session, "sip:%s", switch_channel_get_variable(channel, "sip_from_uri"));
|
tech_pvt->dest = switch_core_session_sprintf(session, "sip:%s", switch_channel_get_variable(channel, "sip_from_uri"));
|
||||||
|
|
||||||
if (!switch_channel_get_variable_dup(channel, "sip_handle_full_from", SWITCH_FALSE)) {
|
if (!switch_channel_get_variable_dup(channel, "sip_handle_full_from", SWITCH_FALSE, -1)) {
|
||||||
switch_channel_set_variable(channel, "sip_handle_full_from", switch_channel_get_variable(channel, "sip_full_to"));
|
switch_channel_set_variable(channel, "sip_handle_full_from", switch_channel_get_variable(channel, "sip_full_to"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!switch_channel_get_variable_dup(channel, "sip_handle_full_to", SWITCH_FALSE)) {
|
if (!switch_channel_get_variable_dup(channel, "sip_handle_full_to", SWITCH_FALSE, -1)) {
|
||||||
switch_channel_set_variable(channel, "sip_handle_full_to", switch_channel_get_variable(channel, "sip_full_from"));
|
switch_channel_set_variable(channel, "sip_handle_full_to", switch_channel_get_variable(channel, "sip_full_from"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -675,13 +675,13 @@ SWITCH_DECLARE(const char *) switch_channel_get_hold_music_partner(switch_channe
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(const char *) switch_channel_get_variable_dup(switch_channel_t *channel, const char *varname, switch_bool_t dup)
|
SWITCH_DECLARE(const char *) switch_channel_get_variable_dup(switch_channel_t *channel, const char *varname, switch_bool_t dup, int idx)
|
||||||
{
|
{
|
||||||
const char *v = NULL, *r = NULL, *vdup = NULL;
|
const char *v = NULL, *r = NULL, *vdup = NULL;
|
||||||
switch_assert(channel != NULL);
|
switch_assert(channel != NULL);
|
||||||
|
|
||||||
switch_mutex_lock(channel->profile_mutex);
|
switch_mutex_lock(channel->profile_mutex);
|
||||||
if (!channel->variables || !(v = switch_event_get_header(channel->variables, varname))) {
|
if (!channel->variables || !(v = switch_event_get_header_idx(channel->variables, varname, idx))) {
|
||||||
switch_caller_profile_t *cp = channel->caller_profile;
|
switch_caller_profile_t *cp = channel->caller_profile;
|
||||||
|
|
||||||
if (cp) {
|
if (cp) {
|
||||||
@ -1032,8 +1032,6 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_var_check(switch_cha
|
|||||||
|
|
||||||
switch_mutex_lock(channel->profile_mutex);
|
switch_mutex_lock(channel->profile_mutex);
|
||||||
if (channel->variables && !zstr(varname)) {
|
if (channel->variables && !zstr(varname)) {
|
||||||
|
|
||||||
switch_event_del_header(channel->variables, varname);
|
|
||||||
if (!zstr(value)) {
|
if (!zstr(value)) {
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
|
|
||||||
@ -1053,6 +1051,36 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_var_check(switch_cha
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_channel_add_variable_var_check(switch_channel_t *channel,
|
||||||
|
const char *varname, const char *value, switch_bool_t var_check, switch_stack_t stack)
|
||||||
|
{
|
||||||
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||||
|
|
||||||
|
switch_assert(channel != NULL);
|
||||||
|
|
||||||
|
switch_mutex_lock(channel->profile_mutex);
|
||||||
|
if (channel->variables && !zstr(varname)) {
|
||||||
|
if (!zstr(value)) {
|
||||||
|
int ok = 1;
|
||||||
|
|
||||||
|
if (var_check) {
|
||||||
|
ok = !switch_string_var_check_const(value);
|
||||||
|
}
|
||||||
|
if (ok) {
|
||||||
|
switch_event_add_header_string(channel->variables, stack, varname, value);
|
||||||
|
} else {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_CRIT, "Invalid data (${%s} contains a variable)\n", varname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
status = SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
switch_mutex_unlock(channel->profile_mutex);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
switch_status_t switch_event_base_add_header(switch_event_t *event, switch_stack_t stack, const char *header_name, char *data);
|
switch_status_t switch_event_base_add_header(switch_event_t *event, switch_stack_t stack, const char *header_name, char *data);
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_printf(switch_channel_t *channel, const char *varname, const char *fmt, ...)
|
SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_printf(switch_channel_t *channel, const char *varname, const char *fmt, ...)
|
||||||
@ -3108,12 +3136,14 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel
|
|||||||
int offset = 0;
|
int offset = 0;
|
||||||
int ooffset = 0;
|
int ooffset = 0;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
int idx = -1;
|
||||||
|
|
||||||
if ((expanded = switch_channel_expand_variables(channel, (char *) vname)) == vname) {
|
if ((expanded = switch_channel_expand_variables(channel, (char *) vname)) == vname) {
|
||||||
expanded = NULL;
|
expanded = NULL;
|
||||||
} else {
|
} else {
|
||||||
vname = expanded;
|
vname = expanded;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ptr = strchr(vname, ':'))) {
|
if ((ptr = strchr(vname, ':'))) {
|
||||||
*ptr++ = '\0';
|
*ptr++ = '\0';
|
||||||
offset = atoi(ptr);
|
offset = atoi(ptr);
|
||||||
@ -3123,7 +3153,12 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sub_val = (char *) switch_channel_get_variable(channel, vname))) {
|
if ((ptr = strchr(vname, '[')) && strchr(ptr, ']')) {
|
||||||
|
*ptr++ = '\0';
|
||||||
|
idx = atoi(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sub_val = (char *) switch_channel_get_variable_dup(channel, vname, SWITCH_TRUE, idx))) {
|
||||||
if (offset || ooffset) {
|
if (offset || ooffset) {
|
||||||
cloned_sub_val = strdup(sub_val);
|
cloned_sub_val = strdup(sub_val);
|
||||||
switch_assert(cloned_sub_val);
|
switch_assert(cloned_sub_val);
|
||||||
|
@ -727,7 +727,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_set_priority(switch_event_t *event,
|
|||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(char *) switch_event_get_header(switch_event_t *event, const char *header_name)
|
SWITCH_DECLARE(switch_event_header_t *) switch_event_get_header_ptr(switch_event_t *event, const char *header_name)
|
||||||
{
|
{
|
||||||
switch_event_header_t *hp;
|
switch_event_header_t *hp;
|
||||||
switch_ssize_t hlen = -1;
|
switch_ssize_t hlen = -1;
|
||||||
@ -742,12 +742,31 @@ SWITCH_DECLARE(char *) switch_event_get_header(switch_event_t *event, const char
|
|||||||
|
|
||||||
for (hp = event->headers; hp; hp = hp->next) {
|
for (hp = event->headers; hp; hp = hp->next) {
|
||||||
if ((!hp->hash || hash == hp->hash) && !strcasecmp(hp->name, header_name)) {
|
if ((!hp->hash || hash == hp->hash) && !strcasecmp(hp->name, header_name)) {
|
||||||
return hp->value;
|
return hp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(char *) switch_event_get_header_idx(switch_event_t *event, const char *header_name, int idx)
|
||||||
|
{
|
||||||
|
switch_event_header_t *hp;
|
||||||
|
|
||||||
|
if ((hp = switch_event_get_header_ptr(event, header_name))) {
|
||||||
|
if (idx > -1) {
|
||||||
|
if (idx < hp->idx) {
|
||||||
|
return hp->array[idx];
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hp->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(char *) switch_event_get_body(switch_event_t *event)
|
SWITCH_DECLARE(char *) switch_event_get_body(switch_event_t *event)
|
||||||
{
|
{
|
||||||
return (event ? event->body : NULL);
|
return (event ? event->body : NULL);
|
||||||
@ -780,7 +799,19 @@ SWITCH_DECLARE(switch_status_t) switch_event_del_header_val(switch_event_t *even
|
|||||||
event->last_header = lp;
|
event->last_header = lp;
|
||||||
}
|
}
|
||||||
FREE(hp->name);
|
FREE(hp->name);
|
||||||
|
|
||||||
|
if (hp->idx) {
|
||||||
|
int i = 0;
|
||||||
|
hp->value = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < hp->idx; i++) {
|
||||||
|
FREE(hp->array[i]);
|
||||||
|
}
|
||||||
|
FREE(hp->array);
|
||||||
|
}
|
||||||
|
|
||||||
FREE(hp->value);
|
FREE(hp->value);
|
||||||
|
|
||||||
memset(hp, 0, sizeof(*hp));
|
memset(hp, 0, sizeof(*hp));
|
||||||
#ifdef SWITCH_EVENT_RECYCLE
|
#ifdef SWITCH_EVENT_RECYCLE
|
||||||
if (switch_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, hp) != SWITCH_STATUS_SUCCESS) {
|
if (switch_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, hp) != SWITCH_STATUS_SUCCESS) {
|
||||||
@ -798,49 +829,185 @@ SWITCH_DECLARE(switch_status_t) switch_event_del_header_val(switch_event_t *even
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_status_t switch_event_base_add_header(switch_event_t *event, switch_stack_t stack, const char *header_name, char *data)
|
static switch_status_t switch_event_base_add_header(switch_event_t *event, switch_stack_t stack, const char *header_name, char *data)
|
||||||
{
|
{
|
||||||
switch_event_header_t *header;
|
switch_event_header_t *header = NULL;
|
||||||
switch_ssize_t hlen = -1;
|
switch_ssize_t hlen = -1;
|
||||||
|
int exists = 0, fly = 0;
|
||||||
|
char *index_ptr;
|
||||||
|
int index = 0;
|
||||||
|
char *real_header_name = NULL;
|
||||||
|
|
||||||
|
if ((index_ptr = strchr(header_name, '['))) {
|
||||||
|
index_ptr++;
|
||||||
|
index = atoi(index_ptr);
|
||||||
|
real_header_name = DUP(header_name);
|
||||||
|
if ((index_ptr = strchr(real_header_name, '['))) {
|
||||||
|
*index_ptr++ = '\0';
|
||||||
|
}
|
||||||
|
header_name = real_header_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index_ptr || (stack & SWITCH_STACK_PUSH) || (stack & SWITCH_STACK_UNSHIFT) || switch_test_flag(event, EF_CONTAINS_ARRAYS)) {
|
||||||
|
|
||||||
|
if (!(header = switch_event_get_header_ptr(event, header_name)) && index_ptr) {
|
||||||
|
header = ALLOC(sizeof(*header));
|
||||||
|
switch_assert(header);
|
||||||
|
memset(header, 0, sizeof(*header));
|
||||||
|
header->name = DUP(header_name);
|
||||||
|
if (switch_test_flag(event, EF_UNIQ_HEADERS)) {
|
||||||
|
switch_event_del_header(event, header_name);
|
||||||
|
}
|
||||||
|
fly++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((header = switch_event_get_header_ptr(event, header_name))) {
|
||||||
|
|
||||||
|
if (index_ptr) {
|
||||||
|
if (index > -1 && index <= 4000) {
|
||||||
|
if (index < header->idx) {
|
||||||
|
FREE(header->array[index]);
|
||||||
|
header->array[index] = DUP(data);
|
||||||
|
} else {
|
||||||
|
int i;
|
||||||
|
char **m;
|
||||||
|
|
||||||
|
m = realloc(header->array, sizeof(char *) * (index + 1));
|
||||||
|
switch_assert(m);
|
||||||
|
header->array = m;
|
||||||
|
for (i = header->idx; i < index; i++) {
|
||||||
|
m[i] = DUP("");
|
||||||
|
}
|
||||||
|
m[index] = DUP(data);
|
||||||
|
header->idx = index + 1;
|
||||||
|
if (!fly) {
|
||||||
|
exists = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto redraw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goto end;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (!(stack & SWITCH_STACK_PUSH) && !(stack & SWITCH_STACK_UNSHIFT) && header->idx) {
|
||||||
|
stack |= SWITCH_STACK_PUSH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((stack & SWITCH_STACK_PUSH) || (stack & SWITCH_STACK_UNSHIFT)) {
|
||||||
|
exists++;
|
||||||
|
stack &= ~(SWITCH_STACK_TOP | SWITCH_STACK_BOTTOM);
|
||||||
|
} else {
|
||||||
|
header = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!header) {
|
||||||
|
|
||||||
#ifdef SWITCH_EVENT_RECYCLE
|
#ifdef SWITCH_EVENT_RECYCLE
|
||||||
void *pop;
|
void *pop;
|
||||||
if (switch_queue_trypop(EVENT_HEADER_RECYCLE_QUEUE, &pop) == SWITCH_STATUS_SUCCESS) {
|
if (switch_queue_trypop(EVENT_HEADER_RECYCLE_QUEUE, &pop) == SWITCH_STATUS_SUCCESS) {
|
||||||
header = (switch_event_header_t *) pop;
|
header = (switch_event_header_t *) pop;
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
header = ALLOC(sizeof(*header));
|
||||||
|
switch_assert(header);
|
||||||
|
#ifdef SWITCH_EVENT_RECYCLE
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
if (switch_test_flag(event, EF_UNIQ_HEADERS)) {
|
||||||
|
switch_event_del_header(event, header_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(header, 0, sizeof(*header));
|
||||||
|
|
||||||
|
header->name = DUP(header_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((stack & SWITCH_STACK_PUSH) || (stack & SWITCH_STACK_UNSHIFT)) {
|
||||||
|
char **m = NULL;
|
||||||
|
switch_size_t len = 0;
|
||||||
|
char *hv;
|
||||||
|
int i = 0, j = 0;
|
||||||
|
|
||||||
|
switch_set_flag(event, EF_CONTAINS_ARRAYS);
|
||||||
|
|
||||||
|
if (header->value && !header->idx) {
|
||||||
|
m = malloc(sizeof(char *));
|
||||||
|
switch_assert(m);
|
||||||
|
m[0] = header->value;
|
||||||
|
header->value = NULL;
|
||||||
|
header->array = m;
|
||||||
|
header->idx++;
|
||||||
|
m = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = header->idx + 1;
|
||||||
|
m = realloc(header->array, sizeof(char *) * i);
|
||||||
|
switch_assert(m);
|
||||||
|
|
||||||
|
if ((stack & SWITCH_STACK_PUSH)) {
|
||||||
|
m[header->idx] = data;
|
||||||
|
} else if ((stack & SWITCH_STACK_UNSHIFT)) {
|
||||||
|
for (j = header->idx; j > 0; j--) {
|
||||||
|
m[j] = m[j-1];
|
||||||
|
}
|
||||||
|
m[0] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
header->idx++;
|
||||||
|
header->array = m;
|
||||||
|
|
||||||
|
redraw:
|
||||||
|
|
||||||
|
for(j = 0; j < header->idx; j++) {
|
||||||
|
len += strlen(header->array[j]) + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len) {
|
||||||
|
len += 8;
|
||||||
|
hv = realloc(header->value, len);
|
||||||
|
switch_assert(hv);
|
||||||
|
header->value = hv;
|
||||||
|
|
||||||
|
switch_snprintf(header->value, len, "ARRAY::");
|
||||||
|
for(j = 0; j < header->idx; j++) {
|
||||||
|
switch_snprintf(header->value + strlen(header->value), len - strlen(header->value), "%s%s", j == 0 ? "" : "::", header->array[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
#endif
|
header->value = data;
|
||||||
header = ALLOC(sizeof(*header));
|
|
||||||
switch_assert(header);
|
|
||||||
#ifdef SWITCH_EVENT_RECYCLE
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (switch_test_flag(event, EF_UNIQ_HEADERS)) {
|
|
||||||
switch_event_del_header(event, header_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(header, 0, sizeof(*header));
|
if (!exists) {
|
||||||
|
header->hash = switch_ci_hashfunc_default(header->name, &hlen);
|
||||||
|
|
||||||
header->name = DUP(header_name);
|
if ((stack & SWITCH_STACK_TOP)) {
|
||||||
header->value = data;
|
header->next = event->headers;
|
||||||
header->hash = switch_ci_hashfunc_default(header->name, &hlen);
|
event->headers = header;
|
||||||
|
if (!event->last_header) {
|
||||||
if ((stack & SWITCH_STACK_TOP)) {
|
event->last_header = header;
|
||||||
header->next = event->headers;
|
}
|
||||||
event->headers = header;
|
} else {
|
||||||
if (!event->last_header) {
|
if (event->last_header) {
|
||||||
|
event->last_header->next = header;
|
||||||
|
} else {
|
||||||
|
event->headers = header;
|
||||||
|
header->next = NULL;
|
||||||
|
}
|
||||||
event->last_header = header;
|
event->last_header = header;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (event->last_header) {
|
|
||||||
event->last_header->next = header;
|
|
||||||
} else {
|
|
||||||
event->headers = header;
|
|
||||||
header->next = NULL;
|
|
||||||
}
|
|
||||||
event->last_header = header;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
|
||||||
|
switch_safe_free(real_header_name);
|
||||||
|
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -914,7 +1081,19 @@ SWITCH_DECLARE(void) switch_event_destroy(switch_event_t **event)
|
|||||||
this = hp;
|
this = hp;
|
||||||
hp = hp->next;
|
hp = hp->next;
|
||||||
FREE(this->name);
|
FREE(this->name);
|
||||||
|
|
||||||
|
if (this->idx) {
|
||||||
|
int i = 0;
|
||||||
|
this->value = NULL;
|
||||||
|
for (i = 0; i < this->idx; i++) {
|
||||||
|
FREE(this->array[i]);
|
||||||
|
}
|
||||||
|
FREE(this->array);
|
||||||
|
}
|
||||||
|
|
||||||
FREE(this->value);
|
FREE(this->value);
|
||||||
|
|
||||||
|
|
||||||
#ifdef SWITCH_EVENT_RECYCLE
|
#ifdef SWITCH_EVENT_RECYCLE
|
||||||
if (switch_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, this) != SWITCH_STATUS_SUCCESS) {
|
if (switch_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, this) != SWITCH_STATUS_SUCCESS) {
|
||||||
FREE(this);
|
FREE(this);
|
||||||
@ -947,7 +1126,15 @@ SWITCH_DECLARE(void) switch_event_merge(switch_event_t *event, switch_event_t *t
|
|||||||
switch_assert(tomerge && event);
|
switch_assert(tomerge && event);
|
||||||
|
|
||||||
for (hp = tomerge->headers; hp; hp = hp->next) {
|
for (hp = tomerge->headers; hp; hp = hp->next) {
|
||||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, hp->name, hp->value);
|
if (hp->idx) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < hp->idx; i++) {
|
||||||
|
switch_event_add_header_string(event, SWITCH_STACK_PUSH, hp->name, hp->array[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, hp->name, hp->value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -967,7 +1154,15 @@ SWITCH_DECLARE(switch_status_t) switch_event_dup(switch_event_t **event, switch_
|
|||||||
if (todup->subclass_name && !strcmp(hp->name, "Event-Subclass")) {
|
if (todup->subclass_name && !strcmp(hp->name, "Event-Subclass")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, hp->name, hp->value);
|
|
||||||
|
if (hp->idx) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < hp->idx; i++) {
|
||||||
|
switch_event_add_header_string(*event, SWITCH_STACK_PUSH, hp->name, hp->array[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, hp->name, hp->value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (todup->body) {
|
if (todup->body) {
|
||||||
@ -992,13 +1187,12 @@ SWITCH_DECLARE(switch_status_t) switch_event_serialize(switch_event_t *event, ch
|
|||||||
dlen = blocksize * 2;
|
dlen = blocksize * 2;
|
||||||
|
|
||||||
if (!(buf = malloc(dlen))) {
|
if (!(buf = malloc(dlen))) {
|
||||||
return SWITCH_STATUS_MEMERR;
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* go ahead and give ourselves some space to work with, should save a few reallocs */
|
/* go ahead and give ourselves some space to work with, should save a few reallocs */
|
||||||
if (!(encode_buf = malloc(encode_len))) {
|
if (!(encode_buf = malloc(encode_len))) {
|
||||||
switch_safe_free(buf);
|
abort();
|
||||||
return SWITCH_STATUS_MEMERR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "hit serialized!.\n"); */
|
/* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "hit serialized!.\n"); */
|
||||||
@ -1011,33 +1205,39 @@ SWITCH_DECLARE(switch_status_t) switch_event_serialize(switch_event_t *event, ch
|
|||||||
* destroying loop.
|
* destroying loop.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
new_len = (strlen(hp->value) * 3) + 1;
|
if (hp->idx) {
|
||||||
|
int i;
|
||||||
|
new_len = 0;
|
||||||
|
for(i = 0; i < hp->idx; i++) {
|
||||||
|
new_len += (strlen(hp->array[i]) * 3) + 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
new_len = (strlen(hp->value) * 3) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (encode_len < new_len) {
|
if (encode_len < new_len) {
|
||||||
char *tmp;
|
char *tmp;
|
||||||
/* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Allocing %d was %d.\n", ((strlen(hp->value) * 3) + 1), encode_len); */
|
|
||||||
/* we can use realloc for initial alloc as well, if encode_buf is zero it treats it as a malloc */
|
|
||||||
|
|
||||||
/* keep track of the size of our allocation */
|
/* keep track of the size of our allocation */
|
||||||
encode_len = new_len;
|
encode_len = new_len;
|
||||||
|
|
||||||
if (!(tmp = realloc(encode_buf, encode_len))) {
|
if (!(tmp = realloc(encode_buf, encode_len))) {
|
||||||
/* oh boy, ram's gone, give back what little we grabbed and bail */
|
abort();
|
||||||
switch_safe_free(buf);
|
|
||||||
switch_safe_free(encode_buf);
|
|
||||||
return SWITCH_STATUS_MEMERR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
encode_buf = tmp;
|
encode_buf = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle any bad things in the string like newlines : etc that screw up the serialized format */
|
/* handle any bad things in the string like newlines : etc that screw up the serialized format */
|
||||||
|
|
||||||
|
|
||||||
if (encode) {
|
if (encode) {
|
||||||
switch_url_encode(hp->value, encode_buf, encode_len);
|
switch_url_encode(hp->value, encode_buf, encode_len);
|
||||||
} else {
|
} else {
|
||||||
switch_snprintf(encode_buf, encode_len, "[%s]", hp->value);
|
switch_snprintf(encode_buf, encode_len, "[%s]", hp->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
llen = strlen(hp->name) + strlen(encode_buf) + 8;
|
llen = strlen(hp->name) + strlen(encode_buf) + 8;
|
||||||
|
|
||||||
if ((len + llen) > dlen) {
|
if ((len + llen) > dlen) {
|
||||||
@ -1046,10 +1246,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_serialize(switch_event_t *event, ch
|
|||||||
if ((m = realloc(buf, dlen))) {
|
if ((m = realloc(buf, dlen))) {
|
||||||
buf = m;
|
buf = m;
|
||||||
} else {
|
} else {
|
||||||
/* we seem to be out of memory trying to resize the serialize string, give back what we already have and give up */
|
abort();
|
||||||
switch_safe_free(buf);
|
|
||||||
switch_safe_free(encode_buf);
|
|
||||||
return SWITCH_STATUS_MEMERR;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1076,8 +1273,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_serialize(switch_event_t *event, ch
|
|||||||
if ((m = realloc(buf, dlen))) {
|
if ((m = realloc(buf, dlen))) {
|
||||||
buf = m;
|
buf = m;
|
||||||
} else {
|
} else {
|
||||||
switch_safe_free(buf);
|
abort();
|
||||||
return SWITCH_STATUS_MEMERR;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1212,19 +1408,31 @@ SWITCH_DECLARE(switch_status_t) switch_event_create_json(switch_event_t **event,
|
|||||||
for (cjp = cj->child; cjp; cjp = cjp->next) {
|
for (cjp = cj->child; cjp; cjp = cjp->next) {
|
||||||
char *name = cjp->string;
|
char *name = cjp->string;
|
||||||
char *value = cjp->valuestring;
|
char *value = cjp->valuestring;
|
||||||
|
|
||||||
if (name && value) {
|
if (name && value) {
|
||||||
if (!strcasecmp(name, "_body")) {
|
if (!strcasecmp(name, "_body")) {
|
||||||
switch_event_add_body(new_event, value, SWITCH_VA_NONE);
|
switch_event_add_body(new_event, value, SWITCH_VA_NONE);
|
||||||
} else {
|
} else {
|
||||||
if (!strcasecmp(name, "event-name")) {
|
if (!strcasecmp(name, "event-name")) {
|
||||||
switch_event_del_header(new_event, "event-name");
|
switch_event_del_header(new_event, "event-name");
|
||||||
|
switch_name_event(value, &new_event->event_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_name_event(value, &new_event->event_id);
|
|
||||||
switch_event_add_header_string(new_event, SWITCH_STACK_BOTTOM, name, value);
|
switch_event_add_header_string(new_event, SWITCH_STACK_BOTTOM, name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (name) {
|
||||||
|
if (cjp->type == cJSON_Array) {
|
||||||
|
int i, x = cJSON_GetArraySize(cjp);
|
||||||
|
|
||||||
|
for (i = 0; i < x; i++) {
|
||||||
|
cJSON *item = cJSON_GetArrayItem(cjp, i);
|
||||||
|
|
||||||
|
if (item && item->type == cJSON_String && item->valuestring) {
|
||||||
|
switch_event_add_header_string(new_event, SWITCH_STACK_PUSH, name, item->valuestring);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1243,8 +1451,21 @@ SWITCH_DECLARE(switch_status_t) switch_event_serialize_json(switch_event_t *even
|
|||||||
cj = cJSON_CreateObject();
|
cj = cJSON_CreateObject();
|
||||||
|
|
||||||
for (hp = event->headers; hp; hp = hp->next) {
|
for (hp = event->headers; hp; hp = hp->next) {
|
||||||
cJSON_AddItemToObject(cj, hp->name, cJSON_CreateString(hp->value));
|
if (hp->idx) {
|
||||||
}
|
cJSON *a = cJSON_CreateArray();
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < hp->idx; i++) {
|
||||||
|
cJSON_AddItemToArray(a, cJSON_CreateString(hp->array[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
cJSON_AddItemToObject(cj, hp->name, a);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
cJSON_AddItemToObject(cj, hp->name, cJSON_CreateString(hp->value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (event->body) {
|
if (event->body) {
|
||||||
int blen = (int) strlen(event->body);
|
int blen = (int) strlen(event->body);
|
||||||
char tmp[25];
|
char tmp[25];
|
||||||
@ -1316,7 +1537,15 @@ SWITCH_DECLARE(switch_xml_t) switch_event_xmlize(switch_event_t *event, const ch
|
|||||||
if ((xheaders = switch_xml_add_child_d(xml, "headers", off++))) {
|
if ((xheaders = switch_xml_add_child_d(xml, "headers", off++))) {
|
||||||
int hoff = 0;
|
int hoff = 0;
|
||||||
for (hp = event->headers; hp; hp = hp->next) {
|
for (hp = event->headers; hp; hp = hp->next) {
|
||||||
add_xml_header(xheaders, hp->name, hp->value, hoff++);
|
|
||||||
|
if (hp->idx) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < hp->idx; i++) {
|
||||||
|
add_xml_header(xheaders, hp->name, hp->array[i], hoff++);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
add_xml_header(xheaders, hp->name, hp->value, hoff++);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1730,7 +1959,8 @@ SWITCH_DECLARE(char *) switch_event_expand_headers(switch_event_t *event, const
|
|||||||
int offset = 0;
|
int offset = 0;
|
||||||
int ooffset = 0;
|
int ooffset = 0;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
int idx = -1;
|
||||||
|
|
||||||
if ((expanded = switch_event_expand_headers(event, (char *) vname)) == vname) {
|
if ((expanded = switch_event_expand_headers(event, (char *) vname)) == vname) {
|
||||||
expanded = NULL;
|
expanded = NULL;
|
||||||
} else {
|
} else {
|
||||||
@ -1745,7 +1975,12 @@ SWITCH_DECLARE(char *) switch_event_expand_headers(switch_event_t *event, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(sub_val = switch_event_get_header(event, vname))) {
|
if ((ptr = strchr(vname, '[')) && strchr(ptr, ']')) {
|
||||||
|
*ptr++ = '\0';
|
||||||
|
idx = atoi(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(sub_val = switch_event_get_header_idx(event, vname, idx))) {
|
||||||
switch_safe_free(gvar);
|
switch_safe_free(gvar);
|
||||||
if ((gvar = switch_core_get_variable_dup(vname))) {
|
if ((gvar = switch_core_get_variable_dup(vname))) {
|
||||||
sub_val = gvar;
|
sub_val = gvar;
|
||||||
|
@ -1982,25 +1982,43 @@ SWITCH_DECLARE(int) switch_ivr_set_xml_profile_data(switch_xml_t xml, switch_cal
|
|||||||
return off;
|
return off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int switch_ivr_set_xml_chan_var(switch_xml_t xml, const char *var, const char *val, int off)
|
||||||
|
{
|
||||||
|
char *data;
|
||||||
|
switch_size_t dlen = strlen(val) * 3 + 1;
|
||||||
|
switch_xml_t variable;
|
||||||
|
|
||||||
|
if (!zstr(var) && !zstr(val) && ((variable = switch_xml_add_child_d(xml, var, off++)))) {
|
||||||
|
if ((data = malloc(dlen))) {
|
||||||
|
memset(data, 0, dlen);
|
||||||
|
switch_url_encode(val, data, dlen);
|
||||||
|
switch_xml_set_txt_d(variable, data);
|
||||||
|
free(data);
|
||||||
|
} else abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
return off;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SWITCH_DECLARE(int) switch_ivr_set_xml_chan_vars(switch_xml_t xml, switch_channel_t *channel, int off)
|
SWITCH_DECLARE(int) switch_ivr_set_xml_chan_vars(switch_xml_t xml, switch_channel_t *channel, int off)
|
||||||
{
|
{
|
||||||
switch_xml_t variable;
|
|
||||||
switch_event_header_t *hi = switch_channel_variable_first(channel);
|
switch_event_header_t *hi = switch_channel_variable_first(channel);
|
||||||
|
|
||||||
if (!hi)
|
if (!hi)
|
||||||
return off;
|
return off;
|
||||||
|
|
||||||
for (; hi; hi = hi->next) {
|
for (; hi; hi = hi->next) {
|
||||||
if (!zstr(hi->name) && !zstr(hi->value) && ((variable = switch_xml_add_child_d(xml, hi->name, off++)))) {
|
if (hi->idx) {
|
||||||
char *data;
|
int i;
|
||||||
switch_size_t dlen = strlen(hi->value) * 3 + 1;
|
|
||||||
|
for (i = 0; i < hi->idx; i++) {
|
||||||
if ((data = malloc(dlen))) {
|
off = switch_ivr_set_xml_chan_var(xml, hi->name, hi->array[i], off);
|
||||||
memset(data, 0, dlen);
|
|
||||||
switch_url_encode(hi->value, data, dlen);
|
|
||||||
switch_xml_set_txt_d(variable, data);
|
|
||||||
free(data);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
off = switch_ivr_set_xml_chan_var(xml, hi->name, hi->value, off);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch_channel_variable_last(channel);
|
switch_channel_variable_last(channel);
|
||||||
|
@ -129,7 +129,7 @@ SWITCH_DECLARE(void) switch_perform_substitution(switch_regex_t *re, int match_c
|
|||||||
char *substituted, switch_size_t len, int *ovector)
|
char *substituted, switch_size_t len, int *ovector)
|
||||||
{
|
{
|
||||||
char index[10] = "";
|
char index[10] = "";
|
||||||
char replace[1024] = "";
|
const char *replace = NULL;
|
||||||
switch_size_t x, y = 0, z = 0;
|
switch_size_t x, y = 0, z = 0;
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
|
||||||
@ -154,11 +154,12 @@ SWITCH_DECLARE(void) switch_perform_substitution(switch_regex_t *re, int match_c
|
|||||||
num = -1;
|
num = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pcre_copy_substring(field_data, ovector, match_count, num, replace, sizeof(replace)) > 0) {
|
if (pcre_get_substring(field_data, ovector, match_count, num, &replace) > 0) {
|
||||||
switch_size_t r;
|
switch_size_t r;
|
||||||
for (r = 0; r < strlen(replace); r++) {
|
for (r = 0; r < strlen(replace); r++) {
|
||||||
substituted[y++] = replace[r];
|
substituted[y++] = replace[r];
|
||||||
}
|
}
|
||||||
|
pcre_free_substring(replace);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
substituted[y++] = data[x];
|
substituted[y++] = data[x];
|
||||||
@ -168,6 +169,24 @@ SWITCH_DECLARE(void) switch_perform_substitution(switch_regex_t *re, int match_c
|
|||||||
substituted[y++] = '\0';
|
substituted[y++] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SWITCH_DECLARE(void) switch_capture_regex(switch_regex_t *re, int match_count, const char *field_data,
|
||||||
|
int *ovector, const char *var, switch_cap_callback_t callback, void *user_data)
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
const char *replace;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < match_count; i++) {
|
||||||
|
if (pcre_get_substring(field_data, ovector, match_count, i, &replace) > 0) {
|
||||||
|
callback(var, replace, user_data);
|
||||||
|
pcre_free_substring(replace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_regex_match_partial(const char *target, const char *expression, int *partial)
|
SWITCH_DECLARE(switch_status_t) switch_regex_match_partial(const char *target, const char *expression, int *partial)
|
||||||
{
|
{
|
||||||
const char *error = NULL; /* Used to hold any errors */
|
const char *error = NULL; /* Used to hold any errors */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user