[asterisk-commits] russell: branch 1.4 r60603 - in /branches/1.4: ./ configs/ include/asterisk/ ...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Fri Apr 6 13:58:44 MST 2007


Author: russell
Date: Fri Apr  6 15:58:43 2007
New Revision: 60603

URL: http://svn.digium.com/view/asterisk?view=rev&rev=60603
Log:
To be able to achieve the things that we would like to achieve with the
Asterisk GUI project, we need a fully functional HTTP interface with access
to the Asterisk manager interface.  One of the things that was intended to be
a part of this system, but was never actually implemented, was the ability for
the GUI to be able to upload files to Asterisk.  So, this commit adds this in
the most minimally invasive way that we could come up with.

A lot of work on minimime was done by Steve Murphy.  He fixed a lot of bugs in
the parser, and updated it to be thread-safe.  The ability to check
permissions of active manager sessions was added by Dwayne Hubbard.  Then,
hacking this all together and do doing the modifications necessary to the HTTP
interface was done by me.

Added:
    branches/1.4/main/minimime/   (props changed)
      - copied from r60567, team/group/http_mods/main/minimime/
    branches/1.4/main/minimime/Doxyfile
      - copied unchanged from r60567, team/group/http_mods/main/minimime/Doxyfile
    branches/1.4/main/minimime/Makefile
      - copied unchanged from r60567, team/group/http_mods/main/minimime/Makefile
    branches/1.4/main/minimime/mimeparser.h
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mimeparser.h
    branches/1.4/main/minimime/mimeparser.l
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mimeparser.l
    branches/1.4/main/minimime/mimeparser.tab.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mimeparser.tab.c
    branches/1.4/main/minimime/mimeparser.tab.h
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mimeparser.tab.h
    branches/1.4/main/minimime/mimeparser.y
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mimeparser.y
    branches/1.4/main/minimime/mimeparser.yy.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mimeparser.yy.c
    branches/1.4/main/minimime/minimime.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/minimime.c
    branches/1.4/main/minimime/mm.h
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm.h
    branches/1.4/main/minimime/mm_base64.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_base64.c
    branches/1.4/main/minimime/mm_codecs.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_codecs.c
    branches/1.4/main/minimime/mm_contenttype.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_contenttype.c
    branches/1.4/main/minimime/mm_context.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_context.c
    branches/1.4/main/minimime/mm_envelope.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_envelope.c
    branches/1.4/main/minimime/mm_error.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_error.c
    branches/1.4/main/minimime/mm_header.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_header.c
    branches/1.4/main/minimime/mm_init.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_init.c
    branches/1.4/main/minimime/mm_internal.h
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_internal.h
    branches/1.4/main/minimime/mm_mem.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_mem.c
    branches/1.4/main/minimime/mm_mem.h
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_mem.h
    branches/1.4/main/minimime/mm_mimepart.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_mimepart.c
    branches/1.4/main/minimime/mm_mimeutil.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_mimeutil.c
    branches/1.4/main/minimime/mm_param.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_param.c
    branches/1.4/main/minimime/mm_parse.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_parse.c
    branches/1.4/main/minimime/mm_queue.h
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_queue.h
    branches/1.4/main/minimime/mm_util.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_util.c
    branches/1.4/main/minimime/mm_util.h
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_util.h
    branches/1.4/main/minimime/mm_warnings.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/mm_warnings.c
    branches/1.4/main/minimime/strlcat.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/strlcat.c
    branches/1.4/main/minimime/strlcpy.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/strlcpy.c
    branches/1.4/main/minimime/sys/
      - copied from r60567, team/group/http_mods/main/minimime/sys/
    branches/1.4/main/minimime/sys/mm_queue.h
      - copied unchanged from r60567, team/group/http_mods/main/minimime/sys/mm_queue.h
    branches/1.4/main/minimime/test.sh
      - copied unchanged from r60567, team/group/http_mods/main/minimime/test.sh
    branches/1.4/main/minimime/tests/
      - copied from r60567, team/group/http_mods/main/minimime/tests/
    branches/1.4/main/minimime/tests/Makefile
      - copied unchanged from r60567, team/group/http_mods/main/minimime/tests/Makefile
    branches/1.4/main/minimime/tests/create.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/tests/create.c
    branches/1.4/main/minimime/tests/messages/
      - copied from r60567, team/group/http_mods/main/minimime/tests/messages/
    branches/1.4/main/minimime/tests/messages/test1.txt
      - copied unchanged from r60567, team/group/http_mods/main/minimime/tests/messages/test1.txt
    branches/1.4/main/minimime/tests/messages/test2.txt
      - copied unchanged from r60567, team/group/http_mods/main/minimime/tests/messages/test2.txt
    branches/1.4/main/minimime/tests/messages/test3.txt
      - copied unchanged from r60567, team/group/http_mods/main/minimime/tests/messages/test3.txt
    branches/1.4/main/minimime/tests/messages/test4.txt
      - copied unchanged from r60567, team/group/http_mods/main/minimime/tests/messages/test4.txt
    branches/1.4/main/minimime/tests/messages/test5.txt
      - copied unchanged from r60567, team/group/http_mods/main/minimime/tests/messages/test5.txt
    branches/1.4/main/minimime/tests/messages/test6.txt
      - copied unchanged from r60567, team/group/http_mods/main/minimime/tests/messages/test6.txt
    branches/1.4/main/minimime/tests/messages/test7.txt
      - copied unchanged from r60567, team/group/http_mods/main/minimime/tests/messages/test7.txt
    branches/1.4/main/minimime/tests/parse.c
      - copied unchanged from r60567, team/group/http_mods/main/minimime/tests/parse.c
Modified:
    branches/1.4/Makefile.moddir_rules
    branches/1.4/configs/http.conf.sample
    branches/1.4/configure
    branches/1.4/configure.ac
    branches/1.4/include/asterisk/autoconfig.h.in
    branches/1.4/include/asterisk/compat.h
    branches/1.4/include/asterisk/manager.h
    branches/1.4/main/Makefile
    branches/1.4/main/http.c
    branches/1.4/main/manager.c
    branches/1.4/main/strcompat.c

Modified: branches/1.4/Makefile.moddir_rules
URL: http://svn.digium.com/view/asterisk/branches/1.4/Makefile.moddir_rules?view=diff&rev=60603&r1=60602&r2=60603
==============================================================================
--- branches/1.4/Makefile.moddir_rules (original)
+++ branches/1.4/Makefile.moddir_rules Fri Apr  6 15:58:43 2007
@@ -12,7 +12,9 @@
 #
 
 ifneq ($(findstring MALLOC_DEBUG,$(MENUSELECT_CFLAGS)),)
+ ifeq ($(findstring astmm.h,$(ASTCFLAGS)),)
   ASTCFLAGS+=-include $(ASTTOPDIR)/include/asterisk/astmm.h
+ endif
 endif
 
 ifeq ($(findstring LOADABLE_MODULES,$(MENUSELECT_CFLAGS)),)

Modified: branches/1.4/configs/http.conf.sample
URL: http://svn.digium.com/view/asterisk/branches/1.4/configs/http.conf.sample?view=diff&rev=60603&r1=60602&r2=60603
==============================================================================
--- branches/1.4/configs/http.conf.sample (original)
+++ branches/1.4/configs/http.conf.sample Fri Apr  6 15:58:43 2007
@@ -26,3 +26,15 @@
 ; requests must begin with /asterisk
 ;
 ;prefix=asterisk
+
+; The post_mappings section maps URLs to real paths on the filesystem.  If a
+; POST is done from within an authenticated manager session to one of the
+; configured POST mappings, then any files in the POST will be placed in the
+; configured directory.
+;
+;[post_mappings]
+;
+; In this example, if the prefix option is set to "asterisk", then using the
+; POST URL: /asterisk/uploads will put files in /var/lib/asterisk/uploads/.
+;uploads = /var/lib/asterisk/uploads/
+;

Modified: branches/1.4/configure
URL: http://svn.digium.com/view/asterisk/branches/1.4/configure?view=diff&rev=60603&r1=60602&r2=60603
==============================================================================
--- branches/1.4/configure (original)
+++ branches/1.4/configure Fri Apr  6 15:58:43 2007
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.ac Revision: 58955 .
+# From configure.ac Revision: 59202 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.60.
 #
@@ -15763,7 +15763,9 @@
 
 
 
-for ac_func in asprintf atexit bzero dup2 endpwent floor ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday inet_ntoa isascii localtime_r memchr memmove memset mkdir munmap pow putenv re_comp regcomp rint select setenv socket sqrt strcasecmp strcasestr strchr strcspn strdup strerror strncasecmp strndup strnlen strrchr strsep strspn strstr strtol strtoq unsetenv utime vasprintf
+
+
+for ac_func in asprintf atexit bzero dup2 endpwent floor ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday inet_ntoa isascii localtime_r memchr memmove memset mkdir munmap pow putenv re_comp regcomp rint select setenv socket sqrt strcasecmp strcasestr strchr strcspn strdup strerror strlcat strlcpy strncasecmp strndup strnlen strrchr strsep strspn strstr strtol strtoq unsetenv utime vasprintf
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
 { echo "$as_me:$LINENO: checking for $ac_func" >&5

Modified: branches/1.4/configure.ac
URL: http://svn.digium.com/view/asterisk/branches/1.4/configure.ac?view=diff&rev=60603&r1=60602&r2=60603
==============================================================================
--- branches/1.4/configure.ac (original)
+++ branches/1.4/configure.ac Fri Apr  6 15:58:43 2007
@@ -258,7 +258,7 @@
 AC_FUNC_STRTOD
 AC_FUNC_UTIME_NULL
 AC_FUNC_VPRINTF
-AC_CHECK_FUNCS([asprintf atexit bzero dup2 endpwent floor ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday inet_ntoa isascii localtime_r memchr memmove memset mkdir munmap pow putenv re_comp regcomp rint select setenv socket sqrt strcasecmp strcasestr strchr strcspn strdup strerror strncasecmp strndup strnlen strrchr strsep strspn strstr strtol strtoq unsetenv utime vasprintf])
+AC_CHECK_FUNCS([asprintf atexit bzero dup2 endpwent floor ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday inet_ntoa isascii localtime_r memchr memmove memset mkdir munmap pow putenv re_comp regcomp rint select setenv socket sqrt strcasecmp strcasestr strchr strcspn strdup strerror strlcat strlcpy strncasecmp strndup strnlen strrchr strsep strspn strstr strtol strtoq unsetenv utime vasprintf])
 
 AC_MSG_CHECKING(for PTHREAD_RWLOCK_INITIALIZER)
 AC_LINK_IFELSE(

Modified: branches/1.4/include/asterisk/autoconfig.h.in
URL: http://svn.digium.com/view/asterisk/branches/1.4/include/asterisk/autoconfig.h.in?view=diff&rev=60603&r1=60602&r2=60603
==============================================================================
--- branches/1.4/include/asterisk/autoconfig.h.in (original)
+++ branches/1.4/include/asterisk/autoconfig.h.in Fri Apr  6 15:58:43 2007
@@ -360,6 +360,12 @@
 
 /* Define to 1 if you have the <string.h> header file. */
 #undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strlcat' function. */
+#undef HAVE_STRLCAT
+
+/* Define to 1 if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
 
 /* Define to 1 if you have the `strncasecmp' function. */
 #undef HAVE_STRNCASECMP

Modified: branches/1.4/include/asterisk/compat.h
URL: http://svn.digium.com/view/asterisk/branches/1.4/include/asterisk/compat.h?view=diff&rev=60603&r1=60602&r2=60603
==============================================================================
--- branches/1.4/include/asterisk/compat.h (original)
+++ branches/1.4/include/asterisk/compat.h Fri Apr  6 15:58:43 2007
@@ -61,6 +61,14 @@
 int vasprintf(char **strp, const char *fmt, va_list ap);
 #endif
 
+#ifndef HAVE_STRLCAT
+size_t strlcat(char *dst, const char *src, size_t siz);
+#endif
+
+#ifndef HAVE_STRLCPY
+size_t strlcpy(char *dst, const char *src, size_t siz);
+#endif
+
 #ifdef SOLARIS
 #define __BEGIN_DECLS
 #define __END_DECLS

Modified: branches/1.4/include/asterisk/manager.h
URL: http://svn.digium.com/view/asterisk/branches/1.4/include/asterisk/manager.h?view=diff&rev=60603&r1=60602&r2=60603
==============================================================================
--- branches/1.4/include/asterisk/manager.h (original)
+++ branches/1.4/include/asterisk/manager.h Fri Apr  6 15:58:43 2007
@@ -105,6 +105,22 @@
 */
 int ast_manager_unregister( char *action );
 
+/*! 
+ * \brief Verify a session's read permissions against a permission mask.  
+ * \param ident session identity
+ * \param perm permission mask to verify
+ * \returns 1 if the session has the permission mask capabilities, otherwise 0
+ */
+int astman_verify_session_readpermissions(unsigned long ident, int perm);
+
+/*!
+ * \brief Verify a session's write permissions against a permission mask.  
+ * \param ident session identity
+ * \param perm permission mask to verify
+ * \returns 1 if the session has the permission mask capabilities, otherwise 0
+ */
+int astman_verify_session_writepermissions(unsigned long ident, int perm);
+
 /*! External routines may send asterisk manager events this way */
 /*! 	\param category	Event category, matches manager authorization
 	\param event	Event name

Modified: branches/1.4/main/Makefile
URL: http://svn.digium.com/view/asterisk/branches/1.4/main/Makefile?view=diff&rev=60603&r1=60602&r2=60603
==============================================================================
--- branches/1.4/main/Makefile (original)
+++ branches/1.4/main/Makefile Fri Apr  6 15:58:43 2007
@@ -127,7 +127,10 @@
   H323LDLIBS=
 endif
 
-asterisk: $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS)
+minimime/libmmime.a:
+	@cd minimime && $(MAKE) libmmime.a
+
+asterisk: $(OBJS) editline/libedit.a db1-ast/libdb1.a minimime/libmmime.a $(AST_EMBED_LDSCRIPTS)
 	@$(ASTTOPDIR)/build_tools/make_build_h > $(ASTTOPDIR)/include/asterisk/build.h.tmp
 	@if cmp -s $(ASTTOPDIR)/include/asterisk/build.h.tmp $(ASTTOPDIR)/include/asterisk/build.h ; then echo ; else \
 		mv $(ASTTOPDIR)/include/asterisk/build.h.tmp $(ASTTOPDIR)/include/asterisk/build.h ; \
@@ -144,3 +147,6 @@
 	@if [ -f editline/Makefile ]; then $(MAKE) -C editline distclean ; fi
 	@$(MAKE) -C db1-ast clean
 	@$(MAKE) -C stdtime clean
+	@$(MAKE) -C minimime clean
+
+.PHONY: minimime/libmmime.a

Modified: branches/1.4/main/http.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/main/http.c?view=diff&rev=60603&r1=60602&r2=60603
==============================================================================
--- branches/1.4/main/http.c (original)
+++ branches/1.4/main/http.c Fri Apr  6 15:58:43 2007
@@ -21,8 +21,9 @@
  * \brief http server for AMI access
  *
  * \author Mark Spencer <markster at digium.com>
- * This program implements a tiny http server supporting the "get" method
- * only and was inspired by micro-httpd by Jef Poskanzer 
+ *
+ * This program implements a tiny http server
+ * and was inspired by micro-httpd by Jef Poskanzer 
  * 
  * \ref AstHTTP - AMI over the http protocol
  */
@@ -47,6 +48,8 @@
 #include <fcntl.h>
 #include <pthread.h>
 
+#include "minimime/mm.h"
+
 #include "asterisk/cli.h"
 #include "asterisk/http.h"
 #include "asterisk/utils.h"
@@ -54,6 +57,7 @@
 #include "asterisk/options.h"
 #include "asterisk/config.h"
 #include "asterisk/version.h"
+#include "asterisk/manager.h"
 
 #define MAX_PREFIX 80
 #define DEFAULT_PREFIX "/asterisk"
@@ -67,6 +71,14 @@
 
 AST_RWLOCK_DEFINE_STATIC(uris_lock);
 static struct ast_http_uri *uris;
+
+struct ast_http_post_mapping {
+	AST_RWLIST_ENTRY(ast_http_post_mapping) entry;
+	char *from;
+	char *to;
+};
+
+static AST_RWLIST_HEAD_STATIC(post_mappings, ast_http_post_mapping);
 
 static int httpfd = -1;
 static pthread_t master = AST_PTHREADT_NULL;
@@ -285,6 +297,225 @@
 		prev = prev->next;
 	}
 	ast_rwlock_unlock(&uris_lock);
+}
+
+/*! \note This assumes that the post_mappings list is locked */
+static struct ast_http_post_mapping *find_post_mapping(const char *uri)
+{
+	struct ast_http_post_mapping *post_map;
+
+	if (!ast_strlen_zero(prefix) && strncmp(prefix, uri, strlen(prefix))) {
+		ast_log(LOG_DEBUG, "URI %s does not have prefix %s\n", uri, prefix);
+		return NULL;
+	}
+
+	uri += strlen(prefix);
+	if (*uri == '/')
+		uri++;
+	
+	AST_RWLIST_TRAVERSE(&post_mappings, post_map, entry) {
+		if (!strcmp(uri, post_map->from))
+			return post_map;
+	}
+
+	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)
+{
+	char filename[PATH_MAX];
+	FILE *f;
+	const char *body;
+	size_t body_len;
+
+	snprintf(filename, sizeof(filename), "%s/%s", post_dir, fn);
+
+	if (option_debug)
+		ast_log(LOG_DEBUG, "Posting raw data to %s\n", filename);
+
+	if (!(f = fopen(filename, "w"))) {
+		ast_log(LOG_WARNING, "Unable to open %s for writing file from a POST!\n", filename);
+		return;
+	}
+
+	if (!(body = mm_mimepart_getbody(part, 0))) {
+		if (option_debug)
+			ast_log(LOG_DEBUG, "Couldn't get the mimepart body\n");
+		fclose(f);
+		return;
+	}
+	body_len = mm_mimepart_getlength(part);
+
+	if (option_debug)
+		ast_log(LOG_DEBUG, "Body length is %ld\n", body_len);
+
+	fwrite(body, 1, body_len, f);
+
+	fclose(f);
+}
+
+static char *handle_post(struct ast_http_server_instance *ser, char *uri, 
+	int *status, char **title, int *contentlength, struct ast_variable *headers,
+	struct ast_variable *cookies)
+{
+	char buf;
+	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;
+
+	for (var = cookies; var; var = var->next) {
+		if (strcasecmp(var->name, "mansession_id"))
+			continue;
+
+		if (sscanf(var->value, "%lx", &ident) != 1) {
+			*status = 400;
+			*title = ast_strdup("Bad Request");
+			return ast_http_error(400, "Bad Request", NULL, "The was an error parsing the request.");
+		}
+
+		if (!astman_verify_session_writepermissions(ident, EVENT_FLAG_CONFIG)) {
+			*status = 401;
+			*title = ast_strdup("Unauthorized");
+			return ast_http_error(401, "Unauthorized", NULL, "You are not authorized to make this request.");
+		}
+
+		break;
+	}
+	if (!var) {
+		*status = 401;
+		*title = ast_strdup("Unauthorized");
+		return ast_http_error(401, "Unauthorized", NULL, "You are not authorized to make this request.");
+	}
+
+	if (!(f = tmpfile()))
+		return NULL;
+
+	for (var = headers; var; var = var->next) {
+		if (!strcasecmp(var->name, "Content-Length")) {
+			if ((sscanf(var->value, "%u", &content_len)) != 1) {
+				ast_log(LOG_ERROR, "Invalid Content-Length in POST request!\n");
+				fclose(f);
+				return NULL;
+			}
+			if (option_debug)
+				ast_log(LOG_DEBUG, "Got a Content-Length of %d\n", content_len);
+		} else if (!strcasecmp(var->name, "Content-Type"))
+			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;
+	}
+
+	if (fseek(f, SEEK_SET, 0)) {
+		if (option_debug)
+			ast_log(LOG_DEBUG, "Failed to seek temp file back to beginning.\n");
+		fclose(f);
+		return NULL;
+	}
+
+	AST_RWLIST_RDLOCK(&post_mappings);
+	if (!(post_map = find_post_mapping(uri))) {
+		if (option_debug)
+			ast_log(LOG_DEBUG, "%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.");
+	}
+	post_dir = ast_strdupa(post_map->to);
+	post_map = NULL;
+	AST_RWLIST_UNLOCK(&post_mappings);
+
+	if (option_debug)
+		ast_log(LOG_DEBUG, "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) {
+		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) {
+		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_log(LOG_DEBUG, "Found %d MIME parts\n", mm_res - 1);
+		else
+			ast_log(LOG_DEBUG, "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))) {
+			if (option_debug)
+				ast_log(LOG_DEBUG, "Failed to get mime part num %d\n", i);
+			continue;
+		}
+
+		if (get_filename(part, fn, sizeof(fn))) {
+			if (option_debug)
+				ast_log(LOG_DEBUG, "Failed to retrieve a filename for part num %d\n", i);
+			continue;
+		}
+	
+		if (!part->type) {
+			if (option_debug)
+				ast_log(LOG_DEBUG, "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_strdup("");
 }
 
 static char *handle_uri(struct sockaddr_in *sin, char *uri, int *status, char **title, int *contentlength, struct ast_variable **cookies)
@@ -376,7 +607,7 @@
 	char cookie[4096];
 	char timebuf[256];
 	struct ast_http_server_instance *ser = data;
-	struct ast_variable *var, *prev=NULL, *vars=NULL;
+	struct ast_variable *var, *prev=NULL, *vars=NULL, *headers = NULL;
 	char *uri, *c, *title=NULL;
 	char *vname, *vval;
 	int status = 200, contentlength = 0;
@@ -459,12 +690,29 @@
 						}
 					}
 				}
+			} else {
+				char *name, *value;
+
+				value = ast_strdupa(cookie);
+				name = strsep(&value, ":");
+				if (!value)
+					continue;
+				value = ast_skip_blanks(value);
+				if (ast_strlen_zero(value))
+					continue;
+				var = ast_variable_new(name, value);
+				if (!var)
+					continue;
+				var->next = headers;
+				headers = var;
 			}
 		}
 
 		if (*uri) {
 			if (!strcasecmp(buf, "get")) 
 				c = handle_uri(&ser->requestor, uri, &status, &title, &contentlength, &vars);
+			else if (!strcasecmp(buf, "post")) 
+				c = handle_post(ser, uri, &status, &title, &contentlength, headers, vars);
 			else 
 				c = ast_http_error(501, "Not Implemented", NULL, "Attempt to use unimplemented / unsupported method");\
 		} else 
@@ -624,6 +872,47 @@
 	}
 }
 
+static void destroy_post_mapping(struct ast_http_post_mapping *post_map)
+{
+	if (post_map->from)
+		free(post_map->from);
+	if (post_map->to)
+		free(post_map->to);
+	free(post_map);
+}
+
+static void destroy_post_mappings(void)
+{
+	struct ast_http_post_mapping *post_map;
+
+	AST_RWLIST_WRLOCK(&post_mappings);
+	while ((post_map = AST_RWLIST_REMOVE_HEAD(&post_mappings, entry)))
+		destroy_post_mapping(post_map);
+	AST_RWLIST_UNLOCK(&post_mappings);
+}
+
+static void add_post_mapping(const char *from, const char *to)
+{
+	struct ast_http_post_mapping *post_map;
+
+	if (!(post_map = ast_calloc(1, sizeof(*post_map))))
+		return;
+
+	if (!(post_map->from = ast_strdup(from))) {
+		destroy_post_mapping(post_map);
+		return;
+	}
+
+	if (!(post_map->to = ast_strdup(to))) {
+		destroy_post_mapping(post_map);
+		return;
+	}
+
+	AST_RWLIST_WRLOCK(&post_mappings);
+	AST_RWLIST_INSERT_TAIL(&post_mappings, post_map, entry);
+	AST_RWLIST_UNLOCK(&post_mappings);
+}
+
 static int __ast_http_load(int reload)
 {
 	struct ast_config *cfg;
@@ -637,7 +926,11 @@
 
 	memset(&sin, 0, sizeof(sin));
 	sin.sin_port = htons(8088);
+
 	strcpy(newprefix, DEFAULT_PREFIX);
+
+	destroy_post_mappings();
+
 	cfg = ast_config_load("http.conf");
 	if (cfg) {
 		v = ast_variable_browse(cfg, "general");
@@ -665,6 +958,10 @@
 			}
 			v = v->next;
 		}
+
+		for (v = ast_variable_browse(cfg, "post_mappings"); v; v = v->next)
+			add_post_mapping(v->name, v->value);
+
 		ast_config_destroy(cfg);
 	}
 	if (enabled)
@@ -674,15 +971,21 @@
 		prefix_len = strlen(prefix);
 	}
 	enablestatic = newenablestatic;
+
 	http_server_start(&sin);
+
+
 	return 0;
 }
 
 static int handle_show_http(int fd, int argc, char *argv[])
 {
 	struct ast_http_uri *urih;
+	struct ast_http_post_mapping *post_map;
+
 	if (argc != 3)
 		return RESULT_SHOWUSAGE;
+
 	ast_cli(fd, "HTTP Server Status:\n");
 	ast_cli(fd, "Prefix: %s\n", prefix);
 	if (oldsin.sin_family)
@@ -701,6 +1004,14 @@
 	if (!uris)
 		ast_cli(fd, "None.\n");
 	ast_rwlock_unlock(&uris_lock);
+
+	ast_cli(fd, "\nPOST mappings:\n");
+	AST_RWLIST_RDLOCK(&post_mappings);
+	AST_LIST_TRAVERSE(&post_mappings, post_map, entry)
+		ast_cli(fd, "%s/%s => %s\n", prefix, post_map->from, post_map->to);
+	ast_cli(fd, "%s\n", AST_LIST_EMPTY(&post_mappings) ? "None.\n" : "");
+	AST_RWLIST_UNLOCK(&post_mappings);
+
 	return RESULT_SUCCESS;
 }
 
@@ -721,8 +1032,12 @@
 
 int ast_http_init(void)
 {
+	mm_library_init();
+	mm_codec_registerdefaultcodecs();
+
 	ast_http_uri_link(&statusuri);
 	ast_http_uri_link(&staticuri);
 	ast_cli_register_multiple(cli_http, sizeof(cli_http) / sizeof(struct ast_cli_entry));
+
 	return __ast_http_load(0);
 }

Modified: branches/1.4/main/manager.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/main/manager.c?view=diff&rev=60603&r1=60602&r2=60603
==============================================================================
--- branches/1.4/main/manager.c (original)
+++ branches/1.4/main/manager.c Fri Apr  6 15:58:43 2007
@@ -2448,6 +2448,43 @@
 	return s;
 }
 
+int astman_verify_session_readpermissions(unsigned long ident, int perm)
+{
+	int result = 0;
+	struct mansession *s;
+
+	AST_LIST_LOCK(&sessions);
+	AST_LIST_TRAVERSE(&sessions, s, list) {
+		ast_mutex_lock(&s->__lock);
+		if ((s->managerid == ident) && (s->readperm & perm)) {
+			result = 1;
+			ast_mutex_unlock(&s->__lock);
+			break;
+		}
+		ast_mutex_unlock(&s->__lock);
+	}
+	AST_LIST_UNLOCK(&sessions);
+	return result;
+}
+
+int astman_verify_session_writepermissions(unsigned long ident, int perm)
+{
+	int result = 0;
+	struct mansession *s;
+
+	AST_LIST_LOCK(&sessions);
+	AST_LIST_TRAVERSE(&sessions, s, list) {
+		ast_mutex_lock(&s->__lock);
+		if ((s->managerid == ident) && (s->writeperm & perm)) {
+			result = 1;
+			ast_mutex_unlock(&s->__lock);
+			break;
+		}
+		ast_mutex_unlock(&s->__lock);
+	}
+	AST_LIST_UNLOCK(&sessions);
+	return result;
+}
 
 enum {
 	FORMAT_RAW,

Propchange: branches/1.4/main/minimime/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Fri Apr  6 15:58:43 2007
@@ -1,0 +1,1 @@
+*.o.d

Modified: branches/1.4/main/strcompat.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/main/strcompat.c?view=diff&rev=60603&r1=60602&r2=60603
==============================================================================
--- branches/1.4/main/strcompat.c (original)
+++ branches/1.4/main/strcompat.c Fri Apr  6 15:58:43 2007
@@ -341,3 +341,131 @@
 }
 #endif /* linux */
 #endif /* !HAVE_GETLOADAVG */
+
+
+/*
+ * For strlcat()
+ *
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller at courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left).  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+#ifndef HAVE_STRLCAT
+size_t strlcat(char *dst, const char *src, size_t siz)
+{
+	register char *d = dst;
+	register const char *s = src;
+	register size_t n = siz;
+	size_t dlen;
+
+	/* Find the end of dst and adjust bytes left but don't go past end */
+	while (n-- != 0 && *d != '\0')
+		d++;
+	dlen = d - dst;
+	n = siz - dlen;
+
+	if (n == 0)
+		return dlen + strlen(s);
+
+	while (*s != '\0') {
+		if (n != 1) {
+			*d++ = *s;
+			n--;
+		}
+		s++;
+	}
+	*d = '\0';
+
+	return dlen + (s - src);	/* count does not include NUL */
+}
+#endif /* HAVE_STRLCAT */
+
+/*
+ * For strlcpy()
+ *
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller at courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copy src to string dst of size siz.  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+#ifndef HAVE_STRLCPY
+size_t strlcpy(char *dst, const char *src, size_t siz)
+{
+	register char *d = dst;
+	register const char *s = src;
+	register size_t n = siz;
+
+	/* Copy as many bytes as will fit */
+	if (n != 0 && --n != 0) {
+		do {
+			if ((*d++ = *s++) == 0)
+				break;
+		} while (--n != 0);
+	}
+
+	/* Not enough room in dst, add NUL and traverse rest of src */
+	if (n == 0) {
+		if (siz != 0)
+			*d = '\0';		/* NUL-terminate dst */
+		while (*s++)
+			;
+	}
+
+	return s - src - 1;	/* count does not include NUL */
+}
+#endif /* HAVE_STRLCPY */



More information about the asterisk-commits mailing list