Merge "app_record: Resolve some absolute vs. relative filename bugs" into 14

14
Joshua Colp 8 years ago committed by Gerrit Code Review
commit 9bce4d0670

@ -40,6 +40,7 @@ ASTERISK_REGISTER_FILE()
#include "asterisk/channel.h" #include "asterisk/channel.h"
#include "asterisk/dsp.h" /* use dsp routines for silence detection */ #include "asterisk/dsp.h" /* use dsp routines for silence detection */
#include "asterisk/format_cache.h" #include "asterisk/format_cache.h"
#include "asterisk/paths.h"
/*** DOCUMENTATION /*** DOCUMENTATION
<application name="Record" language="en_US"> <application name="Record" language="en_US">
@ -104,7 +105,7 @@ ASTERISK_REGISTER_FILE()
If the user hangs up during a recording, all data will be lost and the application will terminate.</para> If the user hangs up during a recording, all data will be lost and the application will terminate.</para>
<variablelist> <variablelist>
<variable name="RECORDED_FILE"> <variable name="RECORDED_FILE">
<para>Will be set to the final filename of the recording.</para> <para>Will be set to the final filename of the recording, without an extension.</para>
</variable> </variable>
<variable name="RECORD_STATUS"> <variable name="RECORD_STATUS">
<para>This is the final status of the command</para> <para>This is the final status of the command</para>
@ -133,10 +134,9 @@ enum {
OPTION_STAR_TERMINATE = (1 << 4), OPTION_STAR_TERMINATE = (1 << 4),
OPTION_IGNORE_TERMINATE = (1 << 5), OPTION_IGNORE_TERMINATE = (1 << 5),
OPTION_KEEP = (1 << 6), OPTION_KEEP = (1 << 6),
FLAG_HAS_PERCENT = (1 << 7), OPTION_ANY_TERMINATE = (1 << 7),
OPTION_ANY_TERMINATE = (1 << 8), OPTION_OPERATOR_EXIT = (1 << 8),
OPTION_OPERATOR_EXIT = (1 << 9), OPTION_NO_TRUNCATE = (1 << 9),
OPTION_NO_TRUNCATE = (1 << 10),
}; };
AST_APP_OPTIONS(app_opts,{ AST_APP_OPTIONS(app_opts,{
@ -182,14 +182,47 @@ static int record_dtmf_response(struct ast_channel *chan, struct ast_flags *flag
return 0; return 0;
} }
static int create_destination_directory(const char *path)
{
int res;
char directory[PATH_MAX], *file_sep;
if (!(file_sep = strrchr(path, '/'))) {
/* No directory to create */
return 0;
}
/* Overwrite temporarily */
*file_sep = '\0';
/* Absolute path? */
if (path[0] == '/') {
res = ast_mkdir(path, 0777);
*file_sep = '/';
return res;
}
/* Relative path */
res = snprintf(directory, sizeof(directory), "%s/sounds/%s",
ast_config_AST_DATA_DIR, path);
*file_sep = '/';
if (res >= sizeof(directory)) {
/* We truncated, so we fail */
return -1;
}
return ast_mkdir(directory, 0777);
}
static int record_exec(struct ast_channel *chan, const char *data) static int record_exec(struct ast_channel *chan, const char *data)
{ {
int res = 0; int res = 0;
int count = 0;
char *ext = NULL, *opts[0]; char *ext = NULL, *opts[0];
char *parse, *dir, *file; char *parse;
int i = 0; int i = 0;
char tmp[256]; char tmp[PATH_MAX];
struct ast_filestream *s = NULL; struct ast_filestream *s = NULL;
struct ast_frame *f = NULL; struct ast_frame *f = NULL;
@ -229,8 +262,6 @@ static int record_exec(struct ast_channel *chan, const char *data)
ast_app_parse_options(app_opts, &flags, opts, args.options); ast_app_parse_options(app_opts, &flags, opts, args.options);
if (!ast_strlen_zero(args.filename)) { if (!ast_strlen_zero(args.filename)) {
if (strstr(args.filename, "%d"))
ast_set_flag(&flags, FLAG_HAS_PERCENT);
ext = strrchr(args.filename, '.'); /* to support filename with a . in the filename, not format */ ext = strrchr(args.filename, '.'); /* to support filename with a . in the filename, not format */
if (!ext) if (!ext)
ext = strchr(args.filename, ':'); ext = strchr(args.filename, ':');
@ -268,38 +299,31 @@ static int record_exec(struct ast_channel *chan, const char *data)
if (ast_test_flag(&flags, OPTION_IGNORE_TERMINATE)) if (ast_test_flag(&flags, OPTION_IGNORE_TERMINATE))
terminator = '\0'; terminator = '\0';
/* done parsing */ /*
If a '%d' is specified as part of the filename, we replace that token with
/* these are to allow the use of the %d in the config file for a wild card of sort to sequentially incrementing numbers until we find a unique filename.
create a new file with the inputed name scheme */ */
if (ast_test_flag(&flags, FLAG_HAS_PERCENT)) { if (strchr(args.filename, '%')) {
AST_DECLARE_APP_ARGS(fname, size_t src, dst, count = 0;
AST_APP_ARG(piece)[100]; size_t src_len = strlen(args.filename);
); size_t dst_len = sizeof(tmp) - 1;
char *tmp2 = ast_strdupa(args.filename);
char countstring[15];
int idx;
/* Separate each piece out by the format specifier */
AST_NONSTANDARD_APP_ARGS(fname, tmp2, '%');
do { do {
int tmplen; for (src = 0, dst = 0; src < src_len && dst < dst_len; src++) {
/* First piece has no leading percent, so it's copied verbatim */ if (!strncmp(&args.filename[src], "%d", 2)) {
ast_copy_string(tmp, fname.piece[0], sizeof(tmp)); int s = snprintf(&tmp[dst], PATH_MAX - dst, "%zu", count);
tmplen = strlen(tmp); if (s >= PATH_MAX - dst) {
for (idx = 1; idx < fname.argc; idx++) { /* We truncated, so we need to bail */
if (fname.piece[idx][0] == 'd') { ast_log(LOG_WARNING, "Failed to create unique filename from template: %s\n", args.filename);
/* Substitute the count */ pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
snprintf(countstring, sizeof(countstring), "%d", count); return -1;
ast_copy_string(tmp + tmplen, countstring, sizeof(tmp) - tmplen); }
tmplen += strlen(countstring); dst += s;
} else if (tmplen + 2 < sizeof(tmp)) { src++;
/* Unknown format specifier - just copy it verbatim */ } else {
tmp[tmplen++] = '%'; tmp[dst] = args.filename[src];
tmp[tmplen++] = fname.piece[idx][0]; tmp[++dst] = '\0';
} }
/* Copy the remaining portion of the piece */
ast_copy_string(tmp + tmplen, &(fname.piece[idx][1]), sizeof(tmp) - tmplen);
} }
count++; count++;
} while (ast_fileexists(tmp, ext, ast_channel_language(chan)) > 0); } while (ast_fileexists(tmp, ext, ast_channel_language(chan)) > 0);
@ -307,7 +331,6 @@ static int record_exec(struct ast_channel *chan, const char *data)
ast_copy_string(tmp, args.filename, sizeof(tmp)); ast_copy_string(tmp, args.filename, sizeof(tmp));
pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp); pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp);
/* end of routine mentioned */
if (ast_channel_state(chan) != AST_STATE_UP) { if (ast_channel_state(chan) != AST_STATE_UP) {
if (ast_test_flag(&flags, OPTION_SKIP)) { if (ast_test_flag(&flags, OPTION_SKIP)) {
@ -356,11 +379,11 @@ static int record_exec(struct ast_channel *chan, const char *data)
ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE)); ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
} }
/* Create the directory if it does not exist. */ if (create_destination_directory(tmp)) {
dir = ast_strdupa(tmp); ast_log(LOG_WARNING, "Could not create directory for file %s\n", args.filename);
if ((file = strrchr(dir, '/'))) pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
*file++ = '\0'; goto out;
ast_mkdir (dir, 0777); }
ioflags = ast_test_flag(&flags, OPTION_APPEND) ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY; ioflags = ast_test_flag(&flags, OPTION_APPEND) ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY;
s = ast_writefile(tmp, ext, NULL, ioflags, 0, AST_FILE_MODE); s = ast_writefile(tmp, ext, NULL, ioflags, 0, AST_FILE_MODE);

Loading…
Cancel
Save