summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorMatt Jordan <mjordan@digium.com>2015-06-08 13:16:13 -0500
committerGerrit Code Review <gerrit2@gerrit.digium.api>2015-06-08 13:16:13 -0500
commite29f28e7a5b058ba4a8e7d6edb8514a28fae0ec0 (patch)
treebfa84b94e391249929dafb0d06d6e356319b5fd9 /main
parent720251f2b80639324a37b2041997292d97858d39 (diff)
parentf5d5aa67dcdc274770c47b1a801a449fb83c2f79 (diff)
Merge "AMI: Escape string values." into 13
Diffstat (limited to 'main')
-rw-r--r--main/manager_channels.c33
-rw-r--r--main/presencestate.c15
-rw-r--r--main/stasis_channels.c10
-rw-r--r--main/utils.c108
4 files changed, 155 insertions, 11 deletions
diff --git a/main/manager_channels.c b/main/manager_channels.c
index 3aaab92d0..552adc763 100644
--- a/main/manager_channels.c
+++ b/main/manager_channels.c
@@ -408,6 +408,7 @@ struct ast_str *ast_manager_build_channel_state_string_prefix(
{
struct ast_str *out = ast_str_create(1024);
int res = 0;
+ char *caller_name, *connected_name;
if (!out) {
return NULL;
@@ -418,6 +419,9 @@ struct ast_str *ast_manager_build_channel_state_string_prefix(
return NULL;
}
+ caller_name = ast_escape_c_alloc(snapshot->caller_name);
+ connected_name = ast_escape_c_alloc(snapshot->connected_name);
+
res = ast_str_set(&out, 0,
"%sChannel: %s\r\n"
"%sChannelState: %u\r\n"
@@ -436,9 +440,9 @@ struct ast_str *ast_manager_build_channel_state_string_prefix(
prefix, snapshot->state,
prefix, ast_state2str(snapshot->state),
prefix, S_OR(snapshot->caller_number, "<unknown>"),
- prefix, S_OR(snapshot->caller_name, "<unknown>"),
+ prefix, S_OR(caller_name, "<unknown>"),
prefix, S_OR(snapshot->connected_number, "<unknown>"),
- prefix, S_OR(snapshot->connected_name, "<unknown>"),
+ prefix, S_OR(connected_name, "<unknown>"),
prefix, snapshot->language,
prefix, snapshot->accountcode,
prefix, snapshot->context,
@@ -448,18 +452,26 @@ struct ast_str *ast_manager_build_channel_state_string_prefix(
if (!res) {
ast_free(out);
+ ast_free(caller_name);
+ ast_free(connected_name);
return NULL;
}
if (snapshot->manager_vars) {
struct ast_var_t *var;
+ char *val;
AST_LIST_TRAVERSE(snapshot->manager_vars, var, entries) {
+ val = ast_escape_c_alloc(var->value);
ast_str_append(&out, 0, "%sChanVariable: %s=%s\r\n",
prefix,
- var->name, var->value);
+ var->name, S_OR(val, ""));
+ ast_free(val);
}
}
+ ast_free(caller_name);
+ ast_free(connected_name);
+
return out;
}
@@ -556,6 +568,9 @@ static struct ast_manager_event_blob *channel_new_callerid(
struct ast_channel_snapshot *old_snapshot,
struct ast_channel_snapshot *new_snapshot)
{
+ struct ast_manager_event_blob *res;
+ char *callerid;
+
/* No NewCallerid event on cache clear or first event */
if (!old_snapshot || !new_snapshot) {
return NULL;
@@ -565,11 +580,19 @@ static struct ast_manager_event_blob *channel_new_callerid(
return NULL;
}
- return ast_manager_event_blob_create(
+ if (!(callerid = ast_escape_c_alloc(
+ ast_describe_caller_presentation(new_snapshot->caller_pres)))) {
+ return NULL;
+ }
+
+ res = ast_manager_event_blob_create(
EVENT_FLAG_CALL, "NewCallerid",
"CID-CallingPres: %d (%s)\r\n",
new_snapshot->caller_pres,
- ast_describe_caller_presentation(new_snapshot->caller_pres));
+ callerid);
+
+ ast_free(callerid);
+ return res;
}
static struct ast_manager_event_blob *channel_new_connected_line(
diff --git a/main/presencestate.c b/main/presencestate.c
index ab03336e2..207e2aacb 100644
--- a/main/presencestate.c
+++ b/main/presencestate.c
@@ -393,14 +393,23 @@ int ast_presence_state_engine_init(void)
static struct ast_manager_event_blob *presence_state_to_ami(struct stasis_message *msg)
{
struct ast_presence_state_message *presence_state = stasis_message_data(msg);
+ struct ast_manager_event_blob *res;
- return ast_manager_event_blob_create(EVENT_FLAG_CALL, "PresenceStateChange",
+ char *subtype = ast_escape_c_alloc(presence_state->subtype);
+ char *message = ast_escape_c_alloc(presence_state->message);
+
+ res = ast_manager_event_blob_create(EVENT_FLAG_CALL, "PresenceStateChange",
"Presentity: %s\r\n"
"Status: %s\r\n"
"Subtype: %s\r\n"
"Message: %s\r\n",
presence_state->provider,
ast_presence_state2str(presence_state->state),
- presence_state->subtype,
- presence_state->message);
+ subtype ?: "",
+ message ?: "");
+
+ ast_free(subtype);
+ ast_free(message);
+
+ return res;
}
diff --git a/main/stasis_channels.c b/main/stasis_channels.c
index ae76c1e84..b8efd407b 100644
--- a/main/stasis_channels.c
+++ b/main/stasis_channels.c
@@ -793,8 +793,12 @@ static struct ast_manager_event_blob *varset_to_ami(struct stasis_message *msg)
struct ast_channel_blob *obj = stasis_message_data(msg);
const char *variable =
ast_json_string_get(ast_json_object_get(obj->blob, "variable"));
- const char *value =
- ast_json_string_get(ast_json_object_get(obj->blob, "value"));
+ RAII_VAR(char *, value, ast_escape_c_alloc(
+ ast_json_string_get(ast_json_object_get(obj->blob, "value"))), ast_free);
+
+ if (!value) {
+ return NULL;
+ }
if (obj->snapshot) {
channel_event_string =
@@ -1713,4 +1717,4 @@ static void remove_dial_masquerade_caller(struct ast_channel *caller)
ast_channel_datastore_remove(caller, datastore);
ast_datastore_free(datastore);
-} \ No newline at end of file
+}
diff --git a/main/utils.c b/main/utils.c
index d162cccf8..67c391ce2 100644
--- a/main/utils.c
+++ b/main/utils.c
@@ -1623,6 +1623,114 @@ char *ast_unescape_c(char *src)
return ret;
}
+/*
+ * Standard escape sequences - Note, '\0' is not included as a valid character
+ * to escape, but instead is used here as a NULL terminator for the string.
+ */
+char escape_sequences[] = {
+ '\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '\'', '\"', '\?', '\0'
+};
+
+/*
+ * Standard escape sequences output map (has to maintain matching order with
+ * escape_sequences). '\0' is included here as a NULL terminator for the string.
+ */
+static char escape_sequences_map[] = {
+ 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '\'', '"', '?', '\0'
+};
+
+char* ast_escape(char *dest, const char *s, size_t num, const char *to_escape)
+{
+ char *p;
+
+ if (!dest || ast_strlen_zero(s)) {
+ return dest;
+ }
+
+ if (ast_strlen_zero(to_escape)) {
+ ast_copy_string(dest, s, num);
+ return dest;
+ }
+
+ for (p = dest; *s && num--; ++s, ++p) {
+ /* If in the list of characters to escape then escape it */
+ if (strchr(to_escape, *s)) {
+ /*
+ * See if the character to escape is part of the standard escape
+ * sequences. If so we'll have to use its mapped counterpart
+ * otherwise just use the current character.
+ */
+ char *c = strchr(escape_sequences, *s);
+ *p++ = '\\';
+ *p = c ? escape_sequences_map[c - escape_sequences] : *s;
+ } else {
+ *p = *s;
+ }
+ }
+
+ *p = '\0';
+ return dest;
+}
+
+char* ast_escape_c(char *dest, const char *s, size_t num)
+{
+ /*
+ * Note - This is an optimized version of ast_escape. When looking only
+ * for escape_sequences a couple of checks used in the generic case can
+ * be left out thus making it slightly more efficient.
+ */
+ char *p;
+
+ if (!dest || ast_strlen_zero(s)) {
+ return dest;
+ }
+
+ for (p = dest; *s && num--; ++s, ++p) {
+ /*
+ * See if the character to escape is part of the standard escape
+ * sequences. If so use its mapped counterpart.
+ */
+ char *c = strchr(escape_sequences, *s);
+ if (c) {
+ *p++ = '\\';
+ *p = escape_sequences_map[c - escape_sequences];
+ } else {
+ *p = *s;
+ }
+ }
+
+ *p = '\0';
+ return dest;
+}
+
+static char *escape_alloc(const char *s, size_t *size)
+{
+ if (!s || !(*size = strlen(s))) {
+ return NULL;
+ }
+
+ /*
+ * The result string needs to be twice the size of the given
+ * string just in case every character in it needs to be escaped.
+ */
+ *size = *size * 2 + 1;
+ return ast_calloc(sizeof(char), *size);
+}
+
+char *ast_escape_alloc(const char *s, const char *to_escape)
+{
+ size_t size = 0;
+ char *dest = escape_alloc(s, &size);
+ return ast_escape(dest, s, size, to_escape);
+}
+
+char *ast_escape_c_alloc(const char *s)
+{
+ size_t size = 0;
+ char *dest = escape_alloc(s, &size);
+ return ast_escape_c(dest, s, size);
+}
+
int ast_build_string_va(char **buffer, size_t *space, const char *fmt, va_list ap)
{
int result;