[asterisk-commits] twilson: trunk r109229 - in /trunk: ./ build_tools/ include/asterisk/ main/ m...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Mar 17 17:10:07 CDT 2008
Author: twilson
Date: Mon Mar 17 17:10:06 2008
New Revision: 109229
URL: http://svn.digium.com/view/asterisk?view=rev&rev=109229
Log:
Replace minimime with superior GMime library so that the entire contents of an http post are not read into memory.
This does introduce a dependency on the GMime library for handling HTTP POSTs, but it is available in most distros.
If the library is present, then the compile flag for ENABLE_UPLOADS is enabled by default in menuselect.
Removed:
trunk/main/minimime/
Modified:
trunk/build_tools/cflags.xml
trunk/build_tools/make_buildopts_h
trunk/build_tools/menuselect-deps.in
trunk/configure
trunk/configure.ac
trunk/include/asterisk/autoconfig.h.in
trunk/main/Makefile
trunk/main/http.c
trunk/makeopts.in
Modified: trunk/build_tools/cflags.xml
URL: http://svn.digium.com/view/asterisk/trunk/build_tools/cflags.xml?view=diff&rev=109229&r1=109228&r2=109229
==============================================================================
--- trunk/build_tools/cflags.xml (original)
+++ trunk/build_tools/cflags.xml Mon Mar 17 17:10:06 2008
@@ -1,5 +1,9 @@
<category name="MENUSELECT_CFLAGS" displayname="Compiler Flags" positive_output="yes" remove_on_change=".lastclean">
<member name="DONT_OPTIMIZE" displayname="Disable Optimizations by the Compiler">
+ </member>
+ <member name="ENABLE_UPLOADS" displayname="Enable HTTP uploads">
+ <defaultenabled>yes</defaultenabled>
+ <depend>gmime</depend>
</member>
<member name="DEBUG_THREADS" displayname="Enable Thread Debugging">
</member>
Modified: trunk/build_tools/make_buildopts_h
URL: http://svn.digium.com/view/asterisk/trunk/build_tools/make_buildopts_h?view=diff&rev=109229&r1=109228&r2=109229
==============================================================================
--- trunk/build_tools/make_buildopts_h (original)
+++ trunk/build_tools/make_buildopts_h Mon Mar 17 17:10:06 2008
@@ -7,11 +7,11 @@
*/
END
-TMP=`${GREP} MENUSELECT_CFLAGS menuselect.makeopts | sed 's/MENUSELECT_CFLAGS\=//g' | sed 's/-D//g'`
+TMP=`${GREP} -e ^MENUSELECT_CFLAGS menuselect.makeopts | sed 's/MENUSELECT_CFLAGS\=//g' | sed 's/-D//g'`
for x in ${TMP}; do
echo "#define ${x} 1"
done
-TMP=`${GREP} MENUSELECT_BUILD_DEPS menuselect.makeopts | sed 's/MENUSELECT_BUILD_DEPS\=//g'`
+TMP=`${GREP} -e ^MENUSELECT_BUILD_DEPS menuselect.makeopts | sed 's/MENUSELECT_BUILD_DEPS\=//g'`
for x in ${TMP}; do
x2=`echo ${x} | tr a-z A-Z`
echo "#define AST_MODULE_${x2} 1"
Modified: trunk/build_tools/menuselect-deps.in
URL: http://svn.digium.com/view/asterisk/trunk/build_tools/menuselect-deps.in?view=diff&rev=109229&r1=109228&r2=109229
==============================================================================
--- trunk/build_tools/menuselect-deps.in (original)
+++ trunk/build_tools/menuselect-deps.in Mon Mar 17 17:10:06 2008
@@ -2,6 +2,7 @@
CRYPTO=@PBX_CRYPTO@
CURL=@PBX_CURL@
FREETDS=@PBX_FREETDS@
+GMIME=@PBX_GMIME@
GNU_LD=@GNU_LD@
GSM=@PBX_GSM@
GTK2=@PBX_GTK2@
Modified: trunk/configure.ac
URL: http://svn.digium.com/view/asterisk/trunk/configure.ac?view=diff&rev=109229&r1=109228&r2=109229
==============================================================================
--- trunk/configure.ac (original)
+++ trunk/configure.ac Mon Mar 17 17:10:06 2008
@@ -211,6 +211,7 @@
AST_EXT_LIB_SETUP([GSM], [External GSM library], [gsm], [, use 'internal' GSM otherwise])
AST_EXT_LIB_SETUP([GTK], [gtk libraries], [gtk])
AST_EXT_LIB_SETUP([GTK2], [gtk2 libraries], [gtk2])
+AST_EXT_LIB_SETUP([GMIME], [GMime library], [gmime])
AST_EXT_LIB_SETUP([ICONV], [Iconv Library], [iconv])
AST_EXT_LIB_SETUP([IKSEMEL], [Iksemel Jabber Library], [iksemel])
AST_EXT_LIB_SETUP([IMAP_TK], [UW IMAP Toolkit], [imap])
@@ -1330,6 +1331,8 @@
AST_EXT_LIB_CHECK([OSPTK], [osptk], [OSPPCryptoDecrypt], [osp/osp.h], [-lcrypto -lssl])
fi
+AST_EXT_TOOL_CHECK([GMIME], [gmime])
+
AST_EXT_LIB_CHECK([FREETDS], [tds], [tds_version], [tds.h])
if test "${PBX_FREETDS}" != "0";
then
Modified: trunk/include/asterisk/autoconfig.h.in
URL: http://svn.digium.com/view/asterisk/trunk/include/asterisk/autoconfig.h.in?view=diff&rev=109229&r1=109228&r2=109229
==============================================================================
--- trunk/include/asterisk/autoconfig.h.in (original)
+++ trunk/include/asterisk/autoconfig.h.in Mon Mar 17 17:10:06 2008
@@ -308,6 +308,9 @@
/* Define to 1 if you have the `glob' function. */
#undef HAVE_GLOB
+
+/* Define if your system has the GMIME libraries. */
+#undef HAVE_GMIME
/* Define to indicate the GSM library */
#undef HAVE_GSM
@@ -1175,9 +1178,6 @@
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
-#ifndef _TANDEM_SOURCE
-# undef _TANDEM_SOURCE
-#endif
/* Define like PROTOTYPES; this can be used by system headers. */
#undef __PROTOTYPES
Modified: trunk/main/Makefile
URL: http://svn.digium.com/view/asterisk/trunk/main/Makefile?view=diff&rev=109229&r1=109228&r2=109229
==============================================================================
--- trunk/main/Makefile (original)
+++ trunk/main/Makefile Mon Mar 17 17:10:06 2008
@@ -132,6 +132,11 @@
channel.o: ASTCFLAGS+=$(ZAPTEL_INCLUDE)
+
+ifneq ($(findstring ENABLE_UPLOADS,$(MENUSELECT_CFLAGS)),)
+http.o: ASTCFLAGS+=$(GMIME_INCLUDE)
+endif
+
stdtime/localtime.o: ASTCFLAGS+=$(AST_NO_STRICT_OVERFLOW)
AST_EMBED_LDSCRIPTS:=$(sort $(EMBED_LDSCRIPTS))
@@ -146,9 +151,6 @@
H323LDLIBS=
endif
-minimime/libmmime.a: CHECK_SUBDIR
- @cd minimime && $(MAKE) libmmime.a
-
ifneq ($(findstring $(OSARCH), mingw32 cygwin ),)
MAIN_TGT:=asterisk.dll
asterisk: cygload
@@ -159,13 +161,17 @@
MAIN_TGT:=asterisk
endif
-$(MAIN_TGT): $(OBJS) editline/libedit.a db1-ast/libdb1.a minimime/libmmime.a $(AST_EMBED_LDSCRIPTS)
+ifneq ($(findstring ENABLE_UPLOADS,$(MENUSELECT_CFLAGS)),)
+GMIMELDFLAGS+=$(GMIME_LIB)
+endif
+
+$(MAIN_TGT): $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS)
@$(CC) -c -o buildinfo.o $(ASTCFLAGS) buildinfo.c
$(ECHO_PREFIX) echo " [LD] $^ -> $@"
ifneq ($(findstring chan_h323,$(MENUSELECT_CHANNELS)),)
- $(CMD_PREFIX) $(CC) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $^ buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS)
+ $(CMD_PREFIX) $(CC) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $^ buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(GMIMELDFLAGS)
else
- $(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $(H323LDFLAGS) $^ buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(H323LDLIBS)
+ $(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $(H323LDFLAGS) $^ buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(H323LDLIBS) $(GMIMELDFLAGS)
endif
$(CMD_PREFIX) $(ASTTOPDIR)/build_tools/strip_nonapi $@ || rm $@
@@ -175,5 +181,4 @@
@if [ -f editline/Makefile ]; then $(MAKE) -C editline distclean ; fi
@$(MAKE) -C db1-ast clean
@$(MAKE) -C stdtime clean
- @$(MAKE) -C minimime clean
rm -f libresample/src/*.o
Modified: trunk/main/http.c
URL: http://svn.digium.com/view/asterisk/trunk/main/http.c?view=diff&rev=109229&r1=109228&r2=109229
==============================================================================
--- trunk/main/http.c (original)
+++ trunk/main/http.c Mon Mar 17 17:10:06 2008
@@ -40,7 +40,9 @@
#include <sys/signal.h>
#include <fcntl.h>
-#include "minimime/mm.h"
+#ifdef ENABLE_UPLOADS
+#include <gmime/gmime.h>
+#endif /* ENABLE_UPLOADS */
#include "asterisk/cli.h"
#include "asterisk/tcptls.h"
@@ -88,6 +90,7 @@
static AST_RWLIST_HEAD_STATIC(uris, ast_http_uri); /*!< list of supported handlers */
+#ifdef ENABLE_UPLOADS
struct ast_http_post_mapping {
AST_RWLIST_ENTRY(ast_http_post_mapping) entry;
char *from;
@@ -95,6 +98,12 @@
};
static AST_RWLIST_HEAD_STATIC(post_mappings, ast_http_post_mapping);
+
+struct mime_cbinfo {
+ int count;
+ const char *post_dir;
+};
+#endif /* ENABLE_UPLOADS */
/* all valid URIs must be prepended by the string in prefix. */
static char prefix[MAX_PREFIX];
@@ -325,6 +334,7 @@
AST_RWLIST_UNLOCK(&uris);
}
+#ifdef ENABLE_UPLOADS
/*! \note This assumes that the post_mappings list is locked */
static struct ast_http_post_mapping *find_post_mapping(const char *uri)
{
@@ -347,64 +357,115 @@
return NULL;
}
-static int get_filename(struct mm_mimepart *part, char *fn, size_t fn_len)
-{
- const char *filename;
-
- filename = mm_content_getdispositionparambyname(part->type, "filename");
-
- if (ast_strlen_zero(filename))
- return -1;
-
- ast_copy_string(fn, filename, fn_len);
-
- return 0;
-}
-
-static void post_raw(struct mm_mimepart *part, const char *post_dir, const char *fn)
+static void post_raw(GMimePart *part, const char *post_dir, const char *fn)
{
char filename[PATH_MAX];
- FILE *f;
- const char *body;
- size_t body_len;
+ GMimeDataWrapper *content;
+ GMimeStream *stream;
+ int fd;
snprintf(filename, sizeof(filename), "%s/%s", post_dir, fn);
ast_debug(1, "Posting raw data to %s\n", filename);
- if (!(f = fopen(filename, "w"))) {
+ if ((fd = open(filename, O_CREAT | O_WRONLY, 0666)) == -1) {
ast_log(LOG_WARNING, "Unable to open %s for writing file from a POST!\n", filename);
return;
}
- if (!(body = mm_mimepart_getbody(part, 0))) {
- ast_debug(1, "Couldn't get the mimepart body\n");
- fclose(f);
+ stream = g_mime_stream_fs_new(fd);
+
+ content = g_mime_part_get_content_object(part);
+ g_mime_data_wrapper_write_to_stream(content, stream);
+ g_mime_stream_flush(stream);
+
+ g_object_unref(content);
+ g_object_unref(stream);
+}
+
+static GMimeMessage *parse_message(FILE *f)
+{
+ GMimeMessage *message;
+ GMimeParser *parser;
+ GMimeStream *stream;
+
+ stream = g_mime_stream_file_new(f);
+
+ parser = g_mime_parser_new_with_stream(stream);
+ g_mime_parser_set_respect_content_length(parser, 1);
+
+ g_object_unref(stream);
+
+ message = g_mime_parser_construct_message(parser);
+
+ g_object_unref(parser);
+
+ return message;
+}
+
+static void process_message_callback(GMimeObject *part, gpointer user_data)
+{
+ struct mime_cbinfo *cbinfo = user_data;
+
+ cbinfo->count++;
+
+ /* We strip off the headers before we get here, so should only see GMIME_IS_PART */
+ if (GMIME_IS_MESSAGE_PART(part)) {
+ ast_log(LOG_WARNING, "Got unexpected GMIME_IS_MESSAGE_PART\n");
return;
- }
- body_len = mm_mimepart_getlength(part);
-
- ast_debug(1, "Body length is %ld\n", (long int)body_len);
-
- fwrite(body, 1, body_len, f);
-
- fclose(f);
+ } else if (GMIME_IS_MESSAGE_PARTIAL(part)) {
+ ast_log(LOG_WARNING, "Got unexpected GMIME_IS_MESSAGE_PARTIAL\n");
+ return;
+ } else if (GMIME_IS_MULTIPART(part)) {
+ GList *l;
+
+ ast_log(LOG_WARNING, "Got unexpected GMIME_IS_MULTIPART, trying to process subparts\n");
+ l = GMIME_MULTIPART (part)->subparts;
+ while (l) {
+ process_message_callback(l->data, cbinfo);
+ l = l->next;
+ }
+ } else if (GMIME_IS_PART(part)) {
+ const char *filename;
+
+ ast_debug(3, "Got mime part\n");
+ if (ast_strlen_zero(filename = g_mime_part_get_filename(GMIME_PART(part)))) {
+ ast_debug(1, "Skipping part with no filename\n");
+ return;
+ }
+
+ post_raw(GMIME_PART(part), cbinfo->post_dir, filename);
+ } else {
+ ast_log(LOG_ERROR, "Encountered unknown MIME part. This should never happen!\n");
+ }
+}
+
+static int process_message(GMimeMessage *message, const char *post_dir)
+{
+ struct mime_cbinfo cbinfo = {
+ .count = 0,
+ .post_dir = post_dir,
+ };
+
+ g_mime_message_foreach_part(message, process_message_callback, &cbinfo);
+
+ return cbinfo.count;
}
static struct ast_str *handle_post(struct ast_tcptls_session_instance *ser, char *uri,
int *status, char **title, int *contentlength, struct ast_variable *headers,
struct ast_variable *cookies)
{
- char buf;
+ char buf[4096];
FILE *f;
size_t res;
struct ast_variable *var;
int content_len = 0;
- MM_CTX *ctx;
- int mm_res, i;
struct ast_http_post_mapping *post_map;
const char *post_dir;
unsigned long ident = 0;
+ GMimeMessage *message;
+ int message_count = 0;
for (var = cookies; var; var = var->next) {
if (strcasecmp(var->name, "mansession_id"))
@@ -445,11 +506,11 @@
fprintf(f, "Content-Type: %s\r\n\r\n", var->value);
}
- while ((res = fread(&buf, 1, 1, ser->f))) {
- fwrite(&buf, 1, 1, f);
- content_len--;
- if (!content_len)
- break;
+ for(res = sizeof(buf);content_len;content_len -= res) {
+ if (content_len < res)
+ res = content_len;
+ fread(buf, 1, res, ser->f);
+ fwrite(buf, 1, res, f);
}
if (fseek(f, SEEK_SET, 0)) {
@@ -462,7 +523,6 @@
if (!(post_map = find_post_mapping(uri))) {
ast_debug(1, "%s is not a valid URI for POST\n", uri);
AST_RWLIST_UNLOCK(&post_mappings);
- fclose(f);
*status = 404;
*title = ast_strdup("Not Found");
return ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this server.");
@@ -473,66 +533,27 @@
ast_debug(1, "Going to post files to dir %s\n", post_dir);
- if (!(ctx = mm_context_new())) {
- fclose(f);
- return NULL;
- }
-
- mm_res = mm_parse_fileptr(ctx, f, MM_PARSE_LOOSE, 0);
- fclose(f);
- if (mm_res == -1) {
+ message = parse_message(f); /* Takes ownership and will close f */
+
+ if (!message) {
ast_log(LOG_ERROR, "Error parsing MIME data\n");
- mm_context_free(ctx);
*status = 400;
*title = ast_strdup("Bad Request");
return ast_http_error(400, "Bad Request", NULL, "The was an error parsing the request.");
}
- mm_res = mm_context_countparts(ctx);
- if (!mm_res) {
+ if (!(message_count = process_message(message, post_dir))) {
ast_log(LOG_ERROR, "Invalid MIME data, found no parts!\n");
- mm_context_free(ctx);
*status = 400;
*title = ast_strdup("Bad Request");
return ast_http_error(400, "Bad Request", NULL, "The was an error parsing the request.");
}
- if (option_debug) {
- if (mm_context_iscomposite(ctx))
- ast_debug(1, "Found %d MIME parts\n", mm_res - 1);
- else
- ast_debug(1, "We have a flat (not multi-part) message\n");
- }
-
- for (i = 1; i < mm_res; i++) {
- struct mm_mimepart *part;
- char fn[PATH_MAX];
-
- if (!(part = mm_context_getpart(ctx, i))) {
- ast_debug(1, "Failed to get mime part num %d\n", i);
- continue;
- }
-
- if (get_filename(part, fn, sizeof(fn))) {
- ast_debug(1, "Failed to retrieve a filename for part num %d\n", i);
- continue;
- }
-
- if (!part->type) {
- ast_debug(1, "This part has no content struct?\n");
- continue;
- }
-
- /* XXX This assumes the MIME part body is not encoded! */
- post_raw(part, post_dir, fn);
- }
-
- mm_context_free(ctx);
-
*status = 200;
*title = ast_strdup("OK");
return ast_http_error(200, "OK", NULL, "File successfully uploaded.");
}
+#endif /* ENABLE_UPLOADS */
static struct ast_str *handle_uri(struct ast_tcptls_session_instance *ser, char *uri, int *status,
char **title, int *contentlength, struct ast_variable **cookies,
@@ -773,15 +794,21 @@
}
}
- if (!*uri)
+ if (!*uri) {
out = ast_http_error(400, "Bad Request", NULL, "Invalid Request");
- else if (!strcasecmp(buf, "post"))
+ } else if (!strcasecmp(buf, "post")) {
+#ifdef ENABLE_UPLOADS
out = handle_post(ser, uri, &status, &title, &contentlength, headers, vars);
- else if (strcasecmp(buf, "get"))
+#else
out = ast_http_error(501, "Not Implemented", NULL,
"Attempt to use unimplemented / unsupported method");
- else /* try to serve it */
+#endif /* ENABLE_UPLOADS */
+ } else if (strcasecmp(buf, "get")) {
+ out = ast_http_error(501, "Not Implemented", NULL,
+ "Attempt to use unimplemented / unsupported method");
+ } else { /* try to serve it */
out = handle_uri(ser, uri, &status, &title, &contentlength, &vars, &static_content);
+ }
/* If they aren't mopped up already, clean up the cookies */
if (vars)
@@ -887,6 +914,7 @@
AST_RWLIST_UNLOCK(&uri_redirects);
}
+#ifdef ENABLE_UPLOADS
static void destroy_post_mapping(struct ast_http_post_mapping *post_map)
{
if (post_map->from)
@@ -927,6 +955,7 @@
AST_RWLIST_INSERT_TAIL(&post_mappings, post_map, entry);
AST_RWLIST_UNLOCK(&post_mappings);
}
+#endif /* ENABLE_UPLOADS */
static int __ast_http_load(int reload)
{
@@ -964,7 +993,9 @@
ast_free(redirect);
AST_RWLIST_UNLOCK(&uri_redirects);
+#ifdef ENABLE_UPLOADS
destroy_post_mappings();
+#endif /* ENABLE_UPLOADS */
if (cfg) {
v = ast_variable_browse(cfg, "general");
@@ -1013,8 +1044,10 @@
}
}
+#ifdef ENABLE_UPLOADS
for (v = ast_variable_browse(cfg, "post_mappings"); v; v = v->next)
add_post_mapping(v->name, v->value);
+#endif /* ENABLE_UPLOADS */
ast_config_destroy(cfg);
}
@@ -1036,7 +1069,11 @@
{
struct ast_http_uri *urih;
struct http_uri_redirect *redirect;
+
+#ifdef ENABLE_UPLOADS
struct ast_http_post_mapping *post_map;
+#endif /* ENABLE_UPLOADS */
+
switch (cmd) {
case CLI_INIT:
e->command = "http show status";
@@ -1083,12 +1120,15 @@
AST_RWLIST_UNLOCK(&uri_redirects);
+#ifdef ENABLE_UPLOADS
ast_cli(a->fd, "\nPOST mappings:\n");
AST_RWLIST_RDLOCK(&post_mappings);
- AST_LIST_TRAVERSE(&post_mappings, post_map, entry)
+ AST_LIST_TRAVERSE(&post_mappings, post_map, entry) {
ast_cli(a->fd, "%s/%s => %s\n", prefix, post_map->from, post_map->to);
+ }
ast_cli(a->fd, "%s\n", AST_LIST_EMPTY(&post_mappings) ? "None.\n" : "");
AST_RWLIST_UNLOCK(&post_mappings);
+#endif /* ENABLE_UPLOADS */
return CLI_SUCCESS;
}
@@ -1104,8 +1144,9 @@
int ast_http_init(void)
{
- mm_library_init();
- mm_codec_registerdefaultcodecs();
+#ifdef ENABLE_UPLOADS
+ g_mime_init(0);
+#endif /* ENABLE_UPLOADS */
ast_http_uri_link(&statusuri);
ast_http_uri_link(&staticuri);
Modified: trunk/makeopts.in
URL: http://svn.digium.com/view/asterisk/trunk/makeopts.in?view=diff&rev=109229&r1=109228&r2=109229
==============================================================================
--- trunk/makeopts.in (original)
+++ trunk/makeopts.in Mon Mar 17 17:10:06 2008
@@ -81,6 +81,9 @@
FREETDS_INCLUDE=@FREETDS_INCLUDE@
FREETDS_LIB=@FREETDS_LIB@
+GMIME_INCLUDE=@GMIME_INCLUDE@
+GMIME_LIB=@GMIME_LIB@
+
GSM_INTERNAL=@GSM_INTERNAL@
GSM_INCLUDE=@GSM_INCLUDE@
GSM_LIB=@GSM_LIB@
More information about the asterisk-commits
mailing list