summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/file.c34
-rw-r--r--main/media_cache.c42
2 files changed, 70 insertions, 6 deletions
diff --git a/main/file.c b/main/file.c
index 8dded8123..3ee58b168 100644
--- a/main/file.c
+++ b/main/file.c
@@ -333,20 +333,21 @@ static char *build_filename(const char *filename, const char *ext)
/* compare type against the list 'exts' */
/* XXX need a better algorithm */
-static int exts_compare(const char *exts, const char *type)
+static int type_in_list(const char *list, const char *type, int (*cmp)(const char *s1, const char *s2))
{
- char tmp[256];
- char *stringp = tmp, *ext;
+ char *stringp = ast_strdupa(list), *item;
- ast_copy_string(tmp, exts, sizeof(tmp));
- while ((ext = strsep(&stringp, "|"))) {
- if (!strcmp(ext, type))
+ while ((item = strsep(&stringp, "|"))) {
+ if (!cmp(item, type)) {
return 1;
+ }
}
return 0;
}
+#define exts_compare(list, type) (type_in_list((list), (type), strcmp))
+
/*!
* \internal
* \brief Close the file stream by canceling any pending read / write callbacks
@@ -1926,6 +1927,27 @@ struct ast_format *ast_get_format_for_file_ext(const char *file_ext)
return NULL;
}
+int ast_get_extension_for_mime_type(const char *mime_type, char *buffer, size_t capacity)
+{
+ struct ast_format_def *f;
+ SCOPED_RDLOCK(lock, &formats.lock);
+
+ ast_assert(buffer && capacity);
+
+ AST_RWLIST_TRAVERSE(&formats, f, list) {
+ if (type_in_list(f->mime_types, mime_type, strcasecmp)) {
+ size_t item_len = strcspn(f->exts, "|");
+ size_t bytes_written = snprintf(buffer, capacity, ".%.*s", (int) item_len, f->exts);
+ if (bytes_written < capacity) {
+ /* Only return success if we didn't truncate */
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
static struct ast_cli_entry cli_file[] = {
AST_CLI_DEFINE(handle_cli_core_show_file_formats, "Displays file formats")
};
diff --git a/main/media_cache.c b/main/media_cache.c
index e93d1a02f..e0a6dbb74 100644
--- a/main/media_cache.c
+++ b/main/media_cache.c
@@ -35,6 +35,7 @@
#include "asterisk/bucket.h"
#include "asterisk/astdb.h"
#include "asterisk/cli.h"
+#include "asterisk/file.h"
#include "asterisk/media_cache.h"
/*! The name of the AstDB family holding items in the cache. */
@@ -125,6 +126,24 @@ static void media_cache_item_del_from_astdb(struct ast_bucket_file *bucket_file)
/*!
* \internal
+ * \brief Normalize the value of a Content-Type header
+ *
+ * This will trim off any optional parameters after the type/subtype.
+ */
+static void normalize_content_type_header(char *content_type)
+{
+ char *params = strchr(content_type, ';');
+
+ if (params) {
+ *params-- = 0;
+ while (params > content_type && (*params == ' ' || *params == '\t')) {
+ *params-- = 0;
+ }
+ }
+}
+
+/*!
+ * \internal
* \brief Update the name of the file backing a \c bucket_file
* \param preferred_file_name The preferred name of the backing file
*/
@@ -142,9 +161,32 @@ static void bucket_file_update_path(struct ast_bucket_file *bucket_file,
} else if (!strchr(bucket_file->path, '.') && (ext = strrchr(ast_sorcery_object_get_id(bucket_file), '.'))) {
/* If we don't have a file extension and were provided one in the URI, use it */
char new_path[PATH_MAX];
+ char found_ext[PATH_MAX];
ast_bucket_file_metadata_set(bucket_file, "ext", ext);
+ /* Don't pass '.' while checking for supported extension */
+ if (!ast_get_format_for_file_ext(ext + 1)) {
+ /* If the file extension passed in the URI isn't supported check for the
+ * extension based on the MIME type passed in the Content-Type header before
+ * giving up.
+ * If a match is found then retrieve the extension from the supported list
+ * corresponding to the mime-type and use that to rename the file */
+ struct ast_bucket_metadata *header = ast_bucket_file_metadata_get(bucket_file, "content-type");
+ if (header) {
+ char *mime_type = ast_strdup(header->value);
+ if (mime_type) {
+ normalize_content_type_header(mime_type);
+ if (!ast_strlen_zero(mime_type)) {
+ if (ast_get_extension_for_mime_type(mime_type, found_ext, sizeof(found_ext))) {
+ ext = found_ext;
+ }
+ }
+ ast_free(mime_type);
+ }
+ }
+ }
+
snprintf(new_path, sizeof(new_path), "%s%s", bucket_file->path, ext);
rename(bucket_file->path, new_path);
ast_copy_string(bucket_file->path, new_path, sizeof(bucket_file->path));