From 1a774b9d99106b4a680e41e9643fce1eb68bc073 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 16 Sep 2009 20:09:27 +0000 Subject: [PATCH] BOUNTY-9 (Thank you Xpander Communications) git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@14889 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/include/switch_module_interfaces.h | 2 + src/include/switch_types.h | 1 + src/include/switch_utils.h | 32 +++++-- src/switch_core_file.c | 114 ++++++++++++++++++++----- 4 files changed, 121 insertions(+), 28 deletions(-) diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index a4e5022387..e3fc4570bf 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -333,6 +333,8 @@ struct switch_file_handle { const char *file; const char *func; int line; + char *file_path; + char *spool_path; }; /*! \brief Abstract interface to an asr module */ diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 52fad40abf..334972b5e5 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -110,6 +110,7 @@ SWITCH_BEGIN_EXTERN_C #define SWITCH_PATH_SEPARATOR "/" #endif #define SWITCH_URL_SEPARATOR "://" +#define SWITCH_AUDIO_SPOOL_PATH_VARIABLE "audio_spool_path" #define SWITCH_BRIDGE_HANGUP_CAUSE_VARIABLE "bridge_hangup_cause" #define SWITCH_READ_TERMINATOR_USED_VARIABLE "read_terminator_used" #define SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE "send_silence_when_idle" diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index 3bac7c02c7..dbf3bb56f5 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -66,11 +66,9 @@ SWITCH_DECLARE(int) switch_isxdigit(int c); codec->implementation->iananame, \ codec->implementation->samples_per_second, \ codec->implementation->microseconds_per_packet / 1000) -#ifdef WIN32 -#define switch_is_file_path(file) (file && (*file == '\\' || *(file +1) == ':' || *file == '/' || strstr(file, SWITCH_URL_SEPARATOR))) -#else -#define switch_is_file_path(file) (file && ((*file == '/') || strstr(file, SWITCH_URL_SEPARATOR))) -#endif + + + /*! \brief Test for NULL or zero length string \param s the string to test @@ -553,6 +551,30 @@ SWITCH_DECLARE(char *) switch_url_decode(char *s); SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to, const char *from, const char *headers, const char *body, const char *file); SWITCH_DECLARE(char *) switch_find_end_paren(const char *s, char open, char close); + +static inline switch_bool_t switch_is_file_path(const char *file) +{ + const char *e; + int r; + + if (*file == '[' && *(file + 1) == *SWITCH_PATH_SEPARATOR) { + if ((e = switch_find_end_paren(file, '[', ']'))) { + file = e + 1; + } + } + +#ifdef WIN32 + r = (file && (*file == '\\' || *(file +1) == ':' || *file == '/' || strstr(file, SWITCH_URL_SEPARATOR))); +#else + r = (file && ((*file == '/') || strstr(file, SWITCH_URL_SEPARATOR))); +#endif + + return r ? SWITCH_TRUE : SWITCH_FALSE; + +} + + + SWITCH_DECLARE(int) switch_parse_cidr(const char *string, uint32_t *ip, uint32_t *mask, uint32_t *bitp); SWITCH_DECLARE(switch_status_t) switch_network_list_create(switch_network_list_t **list, const char *name, switch_bool_t default_type, switch_memory_pool_t *pool); SWITCH_DECLARE(switch_status_t) switch_network_list_add_cidr_token(switch_network_list_t *list, const char *cidr_str, switch_bool_t ok, const char *token); diff --git a/src/switch_core_file.c b/src/switch_core_file.c index 34b88e110f..2c47b4530a 100644 --- a/src/switch_core_file.c +++ b/src/switch_core_file.c @@ -45,6 +45,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, switch_status_t status; char stream_name[128] = ""; char *rhs = NULL; + const char *spool_path = NULL; if (switch_test_flag(fh, SWITCH_FILE_OPEN)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Handle already open\n"); @@ -56,28 +57,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, return SWITCH_STATUS_FALSE; } - if ((rhs = strstr(file_path, SWITCH_URL_SEPARATOR))) { - switch_copy_string(stream_name, file_path, (rhs + 1) - file_path); - ext = stream_name; - file_path = rhs + 3; - } else { - if ((ext = strrchr(file_path, '.')) == 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown file Format [%s]\n", file_path); - return SWITCH_STATUS_FALSE; - } - ext++; - } - - if ((fh->file_interface = switch_loadable_module_get_file_interface(ext)) == 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid file format [%s] for [%s]!\n", ext, file_path); - return SWITCH_STATUS_GENERR; - } - - fh->file = file; - fh->func = func; - fh->line = line; - - fh->flags = flags; if (pool) { fh->memory_pool = pool; } else { @@ -88,6 +67,60 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, switch_set_flag(fh, SWITCH_FILE_FLAG_FREE_POOL); } + fh->file_path = switch_core_strdup(fh->memory_pool, file_path); + + if ((flags & SWITCH_FILE_FLAG_WRITE)) { + char *p = fh->file_path, *e; + + if (*p == '[' && *(p + 1) == *SWITCH_PATH_SEPARATOR) { + e = switch_find_end_paren(p, '[', ']'); + + if (e) { + *e = '\0'; + spool_path = p + 1; + fh->file_path = e + 1; + } + } + + if (!spool_path) { + spool_path = switch_core_get_variable(SWITCH_AUDIO_SPOOL_PATH_VARIABLE); + } + + file_path = fh->file_path; + + } + + if ((rhs = strstr(file_path, SWITCH_URL_SEPARATOR))) { + switch_copy_string(stream_name, file_path, (rhs + 1) - file_path); + ext = stream_name; + file_path = rhs + 3; + } else { + if ((ext = strrchr(file_path, '.')) == 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown file Format [%s]\n", file_path); + switch_goto_status(SWITCH_STATUS_FALSE, end); + } + ext++; + } + + if ((fh->file_interface = switch_loadable_module_get_file_interface(ext)) == 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid file format [%s] for [%s]!\n", ext, file_path); + switch_goto_status(SWITCH_STATUS_GENERR, end); + } + + fh->file = file; + fh->func = func; + fh->line = line; + fh->flags = flags; + + if (spool_path) { + char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; + switch_uuid_t uuid; + switch_uuid_get(&uuid); + switch_uuid_format(uuid_str, &uuid); + + fh->spool_path = switch_core_sprintf(fh->memory_pool, "%s%s%s.%s", spool_path, SWITCH_PATH_SEPARATOR, uuid_str, ext); + } + if (rhs) { fh->handler = switch_core_strdup(fh->memory_pool, rhs); } @@ -104,11 +137,25 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, fh->channels = 1; } + file_path = fh->spool_path ? fh->spool_path : fh->file_path; + + if ((status = fh->file_interface->file_open(fh, file_path)) != SWITCH_STATUS_SUCCESS) { + if (fh->spool_path) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Spool dir is set. Make sure [%s] is also a valid path\n", fh->spool_path); + } UNPROTECT_INTERFACE(fh->file_interface); - return status; + switch_goto_status(status, end); } + if ((status = switch_file_exists(file_path, fh->memory_pool)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File [%s] not created!\n", fh->spool_path); + fh->file_interface->file_close(fh); + UNPROTECT_INTERFACE(fh->file_interface); + switch_goto_status(status, end); + } + + if ((flags & SWITCH_FILE_FLAG_READ)) { fh->native_rate = fh->samplerate; @@ -135,6 +182,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, switch_set_flag(fh, SWITCH_FILE_OPEN); + end: + + if (switch_test_flag(fh, SWITCH_FILE_FLAG_FREE_POOL)) { + switch_core_destroy_memory_pool(&fh->memory_pool); + } + return status; } @@ -449,6 +502,21 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh) switch_resample_destroy(&fh->resampler); + + if (fh->spool_path) { + char *command; + +#ifdef _MSC_VER + command = switch_mprintf("move %s %s", fh->spool_path, fh->file_path); +#else + command = switch_mprintf("/bin/mv %s %s", fh->spool_path, fh->file_path); +#endif + system(command); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Copy spooled file [%s] to [%s]\n", fh->spool_path, fh->file_path); + free(command); + } + + UNPROTECT_INTERFACE(fh->file_interface); if (switch_test_flag(fh, SWITCH_FILE_FLAG_FREE_POOL)) {