From 184d967741680e046e8cc0e42125ec3565273c97 Mon Sep 17 00:00:00 2001 From: mnick Date: Wed, 30 Sep 2009 20:16:34 +0000 Subject: Merged revisions 221368 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r221368 | mnick | 2009-09-30 14:42:36 -0500 (Wed, 30 Sep 2009) | 23 lines Merged revisions 221153,221157,221303 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r221153 | mnick | 2009-09-30 10:37:39 -0500 (Wed, 30 Sep 2009) | 2 lines check bounds - prevents for buffer overflow ........ r221157 | mnick | 2009-09-30 10:41:46 -0500 (Wed, 30 Sep 2009) | 8 lines added a new dialplan function 'CSV_QUOTE' and changed the cdr_custom.sample.conf (closes issue #15471) Reported by: dkerr Patches: csv_quote_14.txt uploaded by mnick (license ) Tested by: mnick ........ r221303 | mnick | 2009-09-30 14:02:00 -0500 (Wed, 30 Sep 2009) | 2 lines changed the prototype definition of csv_quote ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.2@221371 f38db490-d61c-443f-a65b-d21fe96a405b --- configs/cdr_custom.conf.sample | 3 +- funcs/func_strings.c | 132 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 131 insertions(+), 4 deletions(-) diff --git a/configs/cdr_custom.conf.sample b/configs/cdr_custom.conf.sample index 8bc2cb34e..999d9aa8c 100644 --- a/configs/cdr_custom.conf.sample +++ b/configs/cdr_custom.conf.sample @@ -6,5 +6,6 @@ ; ; ;[mappings] -;Master.csv => "${CDR(clid)}","${CDR(src)}","${CDR(dst)}","${CDR(dcontext)}","${CDR(channel)}","${CDR(dstchannel)}","${CDR(lastapp)}","${CDR(lastdata)}","${CDR(start)}","${CDR(answer)}","${CDR(end)}","${CDR(duration)}","${CDR(billsec)}","${CDR(disposition)}","${CDR(amaflags)}","${CDR(accountcode)}","${CDR(uniqueid)}","${CDR(userfield)}" +;Master.csv => ${CSV_QUOTE(${CDR(clid)})},${CSV_QUOTE(${CDR(src)})},${CSV_QUOTE(${CDR(dst)})},${CSV_QUOTE(${CDR(dcontext)})},${CSV_QUOTE(${CDR(channel)})},${CSV_QUOTE(${CDR(dstchannel)})},${CSV_QUOTE(${CDR(lastapp)})},${CSV_QUOTE(${CDR(lastdata)})},${CSV_QUOTE(${CDR(start)})},${CSV_QUOTE(${CDR(answer)})},${CSV_QUOTE(${CDR(end)})},${CSV_QUOTE(${CDR(duration)})},${CSV_QUOTE(${CDR(billsec)})},${CSV_QUOTE(${CDR(disposition)})},${CSV_QUOTE(${CDR(amaflags)})},${CSV_QUOTE(${CDR(accountcode)})},${CSV_QUOTE(${CDR(uniqueid)})},${CSV_QUOTE(${CDR(userfield)})} +;Simple.csv => ${CSV_QUOTE(${EPOCH})},${CSV_QUOTE(${CDR(src)})},${CSV_QUOTE(${CDR(dst)})} diff --git a/funcs/func_strings.c b/funcs/func_strings.c index db1e8af2f..4df364d32 100644 --- a/funcs/func_strings.c +++ b/funcs/func_strings.c @@ -276,6 +276,90 @@ AST_THREADSTORAGE(result_buf); Example: ${QUOTE(ab"c"de)} will return "abcde" +<<<<<<< .working +======= + + + Quotes a given string for use in a CSV file, escaping embedded quotes as necessary + + + + + + Example: ${CSV_QUOTE("a,b" 123)} will return """a,b"" 123" + + + + + Removes and returns the first item off of a variable containing delimited text + + + + + + + Example: + exten => s,1,Set(array=one,two,three) + exten => s,n,While($["${SET(var=${SHIFT(array)})}" != ""]) + exten => s,n,NoOp(var is ${var}) + exten => s,n,EndWhile + This would iterate over each value in array, left to right, and + would result in NoOp(var is one), NoOp(var is two), and + NoOp(var is three) being executed. + + + + + + Removes and returns the last item off of a variable containing delimited text + + + + + + + Example: + exten => s,1,Set(array=one,two,three) + exten => s,n,While($["${SET(var=${POP(array)})}" != ""]) + exten => s,n,NoOp(var is ${var}) + exten => s,n,EndWhile + This would iterate over each value in array, right to left, and + would result in NoOp(var is three), NoOp(var is two), and + NoOp(var is one) being executed. + + + + + + Appends one or more values to the end of a variable containing delimited text + + + + + + + Example: Set(PUSH(array)=one,two,three) would append one, + two, and three to the end of the values stored in the variable + "array". + + + + + + Inserts one or more values to the beginning of a variable containing delimited text + + + + + + + Example: Set(UNSHIFT(array)=one,two,three) would insert one, + two, and three before the values stored in the variable + "array". + + + +>>>>>>> .merge-right.r221368 ***/ static int function_fieldqty(struct ast_channel *chan, const char *cmd, @@ -718,6 +802,12 @@ static struct ast_custom_function array_function = { static int quote(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) { char *bufptr = buf, *dataptr = data; + + if (len < 3){ /* at least two for quotes and one for binary zero */ + ast_log(LOG_ERROR, "Not enough buffer"); + return -1; + } + if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "No argument specified!\n"); ast_copy_string(buf, "\"\"", len); @@ -725,7 +815,7 @@ static int quote(struct ast_channel *chan, const char *cmd, char *data, char *bu } *bufptr++ = '"'; - for (; bufptr < buf + len - 1; dataptr++) { + for (; bufptr < buf + len - 3; dataptr++) { if (*dataptr == '\\') { *bufptr++ = '\\'; *bufptr++ = '\\'; @@ -748,9 +838,43 @@ static struct ast_custom_function quote_function = { .read = quote, }; +static int csv_quote(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) +{ + char *bufptr = buf, *dataptr = data; + + if (len < 3){ /* at least two for quotes and one for binary zero */ + ast_log(LOG_ERROR, "Not enough buffer"); + return -1; + } + + if (ast_strlen_zero(data)) { + ast_log(LOG_WARNING, "No argument specified!\n"); + ast_copy_string(buf,"\"\"",len); + return 0; + } + + *bufptr++ = '"'; + for (; bufptr < buf + len - 3; dataptr++){ + if (*dataptr == '"') { + *bufptr++ = '"'; + *bufptr++ = '"'; + } else if (*dataptr == '\0') { + break; + } else { + *bufptr++ = *dataptr; + } + } + *bufptr++ = '"'; + *bufptr='\0'; + return 0; +} + +static struct ast_custom_function csv_quote_function = { + .name = "CSV_QUOTE", + .read = csv_quote, +}; -static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, - size_t buflen) +static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen) { int length = 0; @@ -939,6 +1063,7 @@ static int unload_module(void) res |= ast_custom_function_unregister(®ex_function); res |= ast_custom_function_unregister(&array_function); res |= ast_custom_function_unregister("e_function); + res |= ast_custom_function_unregister(&csv_quote_function); res |= ast_custom_function_unregister(&len_function); res |= ast_custom_function_unregister(&strftime_function); res |= ast_custom_function_unregister(&strptime_function); @@ -963,6 +1088,7 @@ static int load_module(void) res |= ast_custom_function_register(®ex_function); res |= ast_custom_function_register(&array_function); res |= ast_custom_function_register("e_function); + res |= ast_custom_function_register(&csv_quote_function); res |= ast_custom_function_register(&len_function); res |= ast_custom_function_register(&strftime_function); res |= ast_custom_function_register(&strptime_function); -- cgit v1.2.3