Skip to content
Snippets Groups Projects
func_strings.c 41.7 KiB
Newer Older
  • Learn to ignore specific revisions
  • 		} else if (*dataptr == '"') {
    			*bufptr++ = '\\';
    			*bufptr++ = '"';
    		} else if (*dataptr == '\0') {
    			break;
    		} else {
    			*bufptr++ = *dataptr;
    		}
    	}
    	*bufptr++ = '"';
    	*bufptr = '\0';
    
    }
    
    static struct ast_custom_function quote_function = {
    	.name = "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)
    
    		length = strlen(data);
    
    	snprintf(buf, buflen, "%d", length);
    
    static struct ast_custom_function len_function = {
    
    	.read_max = 12,
    
    static int acf_strftime(struct ast_channel *chan, const char *cmd, char *parse,
    
    	AST_DECLARE_APP_ARGS(args,
    
    			     AST_APP_ARG(epoch);
    			     AST_APP_ARG(timezone);
    			     AST_APP_ARG(format);
    
    	AST_STANDARD_APP_ARGS(args, parse);
    
    	ast_get_timeval(args.epoch, &when, ast_tvnow(), NULL);
    	ast_localtime(&when, &tm, args.timezone);
    
    	if (ast_strftime(buf, buflen, args.format, &tm) <= 0)
    
    		ast_log(LOG_WARNING, "C function strftime() output nothing?!!\n");
    
    static struct ast_custom_function strftime_function = {
    
    static int acf_strptime(struct ast_channel *chan, const char *cmd, char *data,
    
    {
    	AST_DECLARE_APP_ARGS(args,
    
    			     AST_APP_ARG(timestring);
    			     AST_APP_ARG(timezone);
    			     AST_APP_ARG(format);
    
    	buf[0] = '\0';
    
    	if (!data) {
    
    		ast_log(LOG_ERROR,
    				"Asterisk function STRPTIME() requires an argument.\n");
    		return -1;
    
    	}
    
    	AST_STANDARD_APP_ARGS(args, data);
    
    
    	if (ast_strlen_zero(args.format)) {
    		ast_log(LOG_ERROR,
    
    				"No format supplied to STRPTIME(<timestring>,<timezone>,<format>)");
    
    		return -1;
    
    	if (!ast_strptime(args.timestring, args.format, &tm)) {
    		ast_log(LOG_WARNING, "STRPTIME() found no time specified within the string\n");
    
    		when = ast_mktime(&tm, args.timezone);
    
    		snprintf(buf, buflen, "%d", (int) when.tv_sec);
    
    static struct ast_custom_function strptime_function = {
    
    	.name = "STRPTIME",
    	.read = acf_strptime,
    };
    
    
    static int function_eval(struct ast_channel *chan, const char *cmd, char *data,
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    	if (ast_strlen_zero(data)) {
    
    		ast_log(LOG_WARNING, "EVAL requires an argument: EVAL(<string>)\n");
    
    		return -1;
    
    	pbx_substitute_variables_helper(chan, data, buf, buflen - 1);
    
    static int function_eval2(struct ast_channel *chan, const char *cmd, char *data,
    			 struct ast_str **buf, ssize_t buflen)
    {
    	if (ast_strlen_zero(data)) {
    		ast_log(LOG_WARNING, "EVAL requires an argument: EVAL(<string>)\n");
    		return -1;
    	}
    
    	ast_str_substitute_variables(buf, buflen, chan, data);
    
    	return 0;
    }
    
    
    static struct ast_custom_function eval_function = {
    
    	.name = "EVAL",
    	.read = function_eval,
    
    	.read2 = function_eval2,
    
    static int keypadhash(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
    
    	for (bufptr = buf, dataptr = data; bufptr < buf + buflen - 1; dataptr++) {
    
    		if (*dataptr == '\0') {
    			*bufptr++ = '\0';
    			break;
    		} else if (*dataptr == '1') {
    
    			*bufptr++ = '1';
    		} else if (strchr("AaBbCc2", *dataptr)) {
    			*bufptr++ = '2';
    		} else if (strchr("DdEeFf3", *dataptr)) {
    			*bufptr++ = '3';
    		} else if (strchr("GgHhIi4", *dataptr)) {
    			*bufptr++ = '4';
    		} else if (strchr("JjKkLl5", *dataptr)) {
    			*bufptr++ = '5';
    		} else if (strchr("MmNnOo6", *dataptr)) {
    			*bufptr++ = '6';
    		} else if (strchr("PpQqRrSs7", *dataptr)) {
    			*bufptr++ = '7';
    		} else if (strchr("TtUuVv8", *dataptr)) {
    			*bufptr++ = '8';
    		} else if (strchr("WwXxYyZz9", *dataptr)) {
    			*bufptr++ = '9';
    		} else if (*dataptr == '0') {
    			*bufptr++ = '0';
    		}
    	}
    
    
    	return 0;
    }
    
    static struct ast_custom_function keypadhash_function = {
    	.name = "KEYPADHASH",
    	.read = keypadhash,
    };
    
    
    static int string_toupper(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
    
    	while ((bufptr < buf + buflen - 1) && (*bufptr++ = toupper(*dataptr++)));
    
    static int string_toupper2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t buflen)
    {
    	char *bufptr, *dataptr = data;
    
    	if (buflen > -1) {
    		ast_str_make_space(buf, buflen > 0 ? buflen : strlen(data) + 1);
    	}
    	bufptr = ast_str_buffer(*buf);
    	while ((bufptr < ast_str_buffer(*buf) + ast_str_size(*buf) - 1) && (*bufptr++ = toupper(*dataptr++)));
    	ast_str_update(*buf);
    
    	return 0;
    }
    
    
    static struct ast_custom_function toupper_function = {
    	.name = "TOUPPER",
    	.read = string_toupper,
    
    	.read2 = string_toupper2,
    
    static int string_tolower(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
    
    	while ((bufptr < buf + buflen - 1) && (*bufptr++ = tolower(*dataptr++)));
    
    static int string_tolower2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t buflen)
    {
    	char *bufptr, *dataptr = data;
    
    	if (buflen > -1) {
    		ast_str_make_space(buf, buflen > 0 ? buflen : strlen(data) + 1);
    	}
    	bufptr = ast_str_buffer(*buf);
    	while ((bufptr < ast_str_buffer(*buf) + ast_str_size(*buf) - 1) && (*bufptr++ = tolower(*dataptr++)));
    	ast_str_update(*buf);
    
    	return 0;
    }
    
    
    static struct ast_custom_function tolower_function = {
    	.name = "TOLOWER",
    	.read = string_tolower,
    
    	.read2 = string_tolower2,
    
    static int shift_pop(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
    
    #define beginning	(cmd[0] == 'S') /* SHIFT */
    	char *after, delimiter[2] = ",", *varsubst;
    	size_t unused;
    	struct ast_str *before = ast_str_thread_get(&result_buf, 16);
    	char *(*search_func)(const char *s, int c) = (beginning ? strchr : strrchr);
    
    	AST_DECLARE_APP_ARGS(args,
    		AST_APP_ARG(var);
    		AST_APP_ARG(delimiter);
    	);
    
    
    
    	if (ast_strlen_zero(args.var)) {
    
    		ast_log(LOG_WARNING, "%s requires a variable name\n", cmd);
    
    	varsubst = alloca(strlen(args.var) + 4);
    	sprintf(varsubst, "${%s}", args.var);
    	ast_str_substitute_variables(&before, 0, chan, varsubst);
    
    	if (args.argc > 1 && !ast_strlen_zero(args.delimiter)) {
    		ast_get_encoded_char(args.delimiter, delimiter, &unused);
    
    	if (!ast_str_strlen(before)) {
    		/* Nothing to pop */
    		return -1;
    	}
    
    	if (!(after = search_func(ast_str_buffer(before), delimiter[0]))) {
    		/* Only one entry in array */
    		ast_str_set(buf, len, "%s", ast_str_buffer(before));
    
    		pbx_builtin_setvar_helper(chan, args.var, "");
    	} else {
    		*after++ = '\0';
    
    		ast_str_set(buf, len, "%s", beginning ? ast_str_buffer(before) : after);
    		pbx_builtin_setvar_helper(chan, args.var, beginning ? after : ast_str_buffer(before));
    
    }
    
    static struct ast_custom_function shift_function = {
    	.name = "SHIFT",
    
    };
    
    static struct ast_custom_function pop_function = {
    	.name = "POP",
    
    static int unshift_push(struct ast_channel *chan, const char *cmd, char *data, const char *new_value)
    
    #define beginning	(cmd[0] == 'U') /* UNSHIFT */
    	char delimiter[2] = ",", *varsubst;
    	size_t unused;
    	struct ast_str *buf, *previous_value;
    
    	AST_DECLARE_APP_ARGS(args,
    		AST_APP_ARG(var);
    		AST_APP_ARG(delimiter);
    	);
    
    
    	if (!(buf = ast_str_thread_get(&result_buf, 16)) ||
    		!(previous_value = ast_str_thread_get(&tmp_buf, 16))) {
    
    	if (ast_strlen_zero(args.var)) {
    		ast_log(LOG_WARNING, "%s requires a variable name\n", cmd);
    
    	if (args.argc > 1 && !ast_strlen_zero(args.delimiter)) {
    		ast_get_encoded_char(args.delimiter, delimiter, &unused);
    
    	varsubst = alloca(strlen(args.var) + 4);
    	sprintf(varsubst, "${%s}", args.var);
    	ast_str_substitute_variables(&previous_value, 0, chan, varsubst);
    
    	if (!ast_str_strlen(previous_value)) {
    		ast_str_set(&buf, 0, "%s", new_value);
    
    		ast_str_set(&buf, 0, "%s%c%s",
    			beginning ? new_value : ast_str_buffer(previous_value),
    			delimiter[0],
    			beginning ? ast_str_buffer(previous_value) : new_value);
    
    	}
    
    	pbx_builtin_setvar_helper(chan, args.var, ast_str_buffer(buf));
    
    	return 0;
    
    }
    
    static struct ast_custom_function push_function = {
    	.name = "PUSH",
    
    static struct ast_custom_function unshift_function = {
    	.name = "UNSHIFT",
    	.write = unshift_push,
    };
    
    static int passthru(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
    
    static struct ast_custom_function passthru_function = {
    	.name = "PASSTHRU",
    	.read2 = passthru,
    
    static int unload_module(void)
    
    {
    	int res = 0;
    
    	res |= ast_custom_function_unregister(&fieldqty_function);
    	res |= ast_custom_function_unregister(&filter_function);
    
    	res |= ast_custom_function_unregister(&replace_function);
    
    	res |= ast_custom_function_unregister(&listfilter_function);
    
    	res |= ast_custom_function_unregister(&regex_function);
    	res |= ast_custom_function_unregister(&array_function);
    
    	res |= ast_custom_function_unregister(&quote_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);
    	res |= ast_custom_function_unregister(&eval_function);
    
    	res |= ast_custom_function_unregister(&keypadhash_function);
    
    	res |= ast_custom_function_unregister(&hashkeys_function);
    	res |= ast_custom_function_unregister(&hash_function);
    	res |= ast_unregister_application(app_clearhash);
    
    	res |= ast_custom_function_unregister(&toupper_function);
    	res |= ast_custom_function_unregister(&tolower_function);
    
    	res |= ast_custom_function_unregister(&shift_function);
    	res |= ast_custom_function_unregister(&pop_function);
    	res |= ast_custom_function_unregister(&push_function);
    	res |= ast_custom_function_unregister(&unshift_function);
    
    	res |= ast_custom_function_unregister(&passthru_function);
    
    static int load_module(void)
    
    {
    	int res = 0;
    
    	res |= ast_custom_function_register(&fieldqty_function);
    	res |= ast_custom_function_register(&filter_function);
    
    	res |= ast_custom_function_register(&replace_function);
    
    	res |= ast_custom_function_register(&listfilter_function);
    
    	res |= ast_custom_function_register(&regex_function);
    	res |= ast_custom_function_register(&array_function);
    
    	res |= ast_custom_function_register(&quote_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);
    	res |= ast_custom_function_register(&eval_function);
    
    	res |= ast_custom_function_register(&keypadhash_function);
    
    	res |= ast_custom_function_register(&hashkeys_function);
    	res |= ast_custom_function_register(&hash_function);
    
    	res |= ast_register_application_xml(app_clearhash, exec_clearhash);
    
    	res |= ast_custom_function_register(&toupper_function);
    	res |= ast_custom_function_register(&tolower_function);
    
    	res |= ast_custom_function_register(&shift_function);
    	res |= ast_custom_function_register(&pop_function);
    	res |= ast_custom_function_register(&push_function);
    	res |= ast_custom_function_register(&unshift_function);
    
    	res |= ast_custom_function_register(&passthru_function);
    
    AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "String handling dialplan functions");