[Freeswitch-trunk] [commit] r6417 - in freeswitch/trunk/src: . include mod/applications/mod_voicemail mod/languages/mod_spidermonkey mod/xml_int/mod_xml_rpc

Freeswitch SVN anthm at freeswitch.org
Wed Nov 28 14:56:26 EST 2007


Author: anthm
Date: Wed Nov 28 14:56:25 2007
New Revision: 6417

Modified:
   freeswitch/trunk/src/include/switch_apr.h
   freeswitch/trunk/src/include/switch_console.h
   freeswitch/trunk/src/include/switch_module_interfaces.h
   freeswitch/trunk/src/include/switch_types.h
   freeswitch/trunk/src/include/switch_utils.h
   freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c
   freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
   freeswitch/trunk/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c
   freeswitch/trunk/src/switch_apr.c
   freeswitch/trunk/src/switch_console.c
   freeswitch/trunk/src/switch_core.c
   freeswitch/trunk/src/switch_xml.cpp

Log:
rss feeds of your voicemail

Modified: freeswitch/trunk/src/include/switch_apr.h
==============================================================================
--- freeswitch/trunk/src/include/switch_apr.h	(original)
+++ freeswitch/trunk/src/include/switch_apr.h	Wed Nov 28 14:56:25 2007
@@ -763,6 +763,8 @@
 
 SWITCH_DECLARE(switch_status_t) switch_file_exists(const char *filename, switch_memory_pool_t *pool);
 
+SWITCH_DECLARE(switch_status_t) switch_directory_exists(const char *dirname, switch_memory_pool_t *pool);
+
 SWITCH_DECLARE(switch_status_t) switch_dir_make(const char *path, switch_fileperms_t perm,
 												switch_memory_pool_t *pool);
 SWITCH_DECLARE(switch_status_t) switch_dir_make_recursive(const char *path, switch_fileperms_t perm,

Modified: freeswitch/trunk/src/include/switch_console.h
==============================================================================
--- freeswitch/trunk/src/include/switch_console.h	(original)
+++ freeswitch/trunk/src/include/switch_console.h	Wed Nov 28 14:56:25 2007
@@ -49,6 +49,7 @@
 	s.end = s.data;														\
 	s.data_size = SWITCH_CMD_CHUNK_LEN;									\
 	s.write_function = switch_console_stream_write;						\
+	s.raw_write_function = switch_console_stream_raw_write;				\
 	s.alloc_len = SWITCH_CMD_CHUNK_LEN;									\
 	s.alloc_chunk = SWITCH_CMD_CHUNK_LEN
 
@@ -63,6 +64,8 @@
 SWITCH_DECLARE(void) switch_console_printf(switch_text_channel_t channel, const char *file, const char *func, int line,
 										   const char *fmt, ...) PRINTF_FUNCTION(5, 6);
 
+SWITCH_DECLARE(switch_status_t) switch_console_stream_raw_write(switch_stream_handle_t *handle, uint8_t *data, switch_size_t datalen);
+
 /*!
   \brief A method akin to printf for dealing with api streams
 */

Modified: freeswitch/trunk/src/include/switch_module_interfaces.h
==============================================================================
--- freeswitch/trunk/src/include/switch_module_interfaces.h	(original)
+++ freeswitch/trunk/src/include/switch_module_interfaces.h	Wed Nov 28 14:56:25 2007
@@ -81,6 +81,7 @@
 
 struct switch_stream_handle {
 	switch_stream_handle_write_function_t write_function;
+	switch_stream_handle_raw_write_function_t raw_write_function;
 	void *data;
 	void *end;
 	switch_size_t data_size;

Modified: freeswitch/trunk/src/include/switch_types.h
==============================================================================
--- freeswitch/trunk/src/include/switch_types.h	(original)
+++ freeswitch/trunk/src/include/switch_types.h	Wed Nov 28 14:56:25 2007
@@ -1090,6 +1090,7 @@
 typedef switch_status_t (*switch_state_handler_t) (switch_core_session_t *);
 typedef struct switch_stream_handle switch_stream_handle_t;
 typedef switch_status_t (*switch_stream_handle_write_function_t) (switch_stream_handle_t *handle, const char *fmt, ...);
+typedef switch_status_t (*switch_stream_handle_raw_write_function_t) (switch_stream_handle_t *handle, uint8_t *data, switch_size_t datalen);
 
 typedef switch_status_t (*switch_api_function_t) (const char *cmd, switch_core_session_t *session, switch_stream_handle_t *stream);
 

Modified: freeswitch/trunk/src/include/switch_utils.h
==============================================================================
--- freeswitch/trunk/src/include/switch_utils.h	(original)
+++ freeswitch/trunk/src/include/switch_utils.h	Wed Nov 28 14:56:25 2007
@@ -132,7 +132,7 @@
  */
 #define is_dtmf(key)  ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119)
 
-
+#define end_of(_s) *(_s + strlen(_s) - 1)
 /*!
   \brief Test for the existance of a flag on an arbitary object
   \param obj the object to test

Modified: freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c	Wed Nov 28 14:56:25 2007
@@ -2119,9 +2119,423 @@
 
 }
 
+#define VOICEMAIL_SYNTAX "rss [<host> <port> <uri> <user> <domain>]"
+
+struct holder {
+    vm_profile_t *profile;
+    switch_memory_pool_t *pool;
+	switch_stream_handle_t *stream;
+	switch_xml_t xml;
+    switch_xml_t x_item;
+    switch_xml_t x_channel;
+    int items;
+    char *user;
+    char *domain;
+    char *host;
+    char *port;
+    char *uri;
+};
+
+
+static int del_callback(void *pArg, int argc, char **argv, char **columnNames)
+{
+    if (argc > 8) {
+        unlink(argv[8]);
+    }
+    return 0;
+}
+
+static int play_callback(void *pArg, int argc, char **argv, char **columnNames)
+{
+    switch_file_t *fd;
+    struct holder *holder = (struct holder *) pArg;
+    char *fname, *ext;
+    switch_size_t flen;
+    uint8_t chunk[1024];
+	const char *mime_type = "audio/inline", *new_type;
+
+    if ((fname = strrchr(argv[8], '/'))) {
+        fname++;
+    } else {
+        fname = argv[8];
+    }
+
+    if ((ext = strrchr(fname, '.'))) {
+        ext++;
+        if ((new_type = switch_core_mime_ext2type(ext))) {
+            mime_type = new_type;
+        }
+    }
+
+    if (switch_file_open(&fd, argv[8], SWITCH_FOPEN_READ, SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE, holder->pool) == SWITCH_STATUS_SUCCESS) {
+        flen = switch_file_get_size(fd);
+        holder->stream->write_function(holder->stream, "Content-type: %s\n", mime_type);
+        holder->stream->write_function(holder->stream, "Content-length: %ld\n\n", (long)flen);
+        for(;;) {
+            switch_status_t status;
+
+            flen = sizeof(chunk);
+            status = switch_file_read(fd, chunk, &flen);
+            if (status != SWITCH_STATUS_SUCCESS || flen == 0) {
+                break;
+            }
+            
+            holder->stream->raw_write_function(holder->stream, chunk, flen);
+            
+        }
+        
+        switch_file_close(fd);
+    }
+    
+    return 0;
+}
+
+static void do_play(vm_profile_t *profile, char *user, char *domain, char *file, switch_stream_handle_t *stream)
+{
+    char *sql;
+    struct holder holder;
+
+    sql = switch_mprintf("update voicemail_data set read_epoch=%ld where user='%s' and domain='%s' and file_path like '%%%s'", 
+                         (long)time(NULL), user, domain, file);
+                         
+    vm_execute_sql(profile, sql, profile->mutex);
+    free(sql);
+
+    sql = switch_mprintf("select * from voicemail_data where user='%s' and domain='%s' and file_path like '%%%s'", user, domain, file);
+    memset(&holder, 0, sizeof(holder));
+    holder.profile = profile;
+    holder.stream = stream;
+    switch_core_new_memory_pool(&holder.pool);
+    vm_execute_sql_callback(profile, profile->mutex, sql, play_callback, &holder);
+    switch_core_destroy_memory_pool(&holder.pool);
+    switch_safe_free(sql);
+
+    
+}
+
+
+static void do_del(vm_profile_t *profile, char *user, char *domain, char *file, switch_stream_handle_t *stream)
+{
+    char *sql;
+    struct holder holder;
+    char *uri, *host, *port;
+
+    host = port = uri = NULL;
+
+    if (stream->event) {
+        host = switch_event_get_header(stream->event, "http-host");
+        port = switch_event_get_header(stream->event, "http-port");
+        uri = switch_event_get_header(stream->event, "http-uri");
+    }
+
+    sql = switch_mprintf("select * from voicemail_data where user='%s' and domain='%s' and file_path like '%%%s'", user, domain, file);
+    memset(&holder, 0, sizeof(holder));
+    holder.profile = profile;
+    holder.stream = stream;
+    vm_execute_sql_callback(profile, profile->mutex, sql, del_callback, &holder);
+
+    switch_safe_free(sql);
+    sql = switch_mprintf("delete from voicemail_data where user='%s' and domain='%s' and file_path like '%%%s'", user, domain, file);
+    vm_execute_sql(profile, sql, profile->mutex);
+    free(sql);
+
+    if (host && port && uri) {
+        stream->write_function(stream,"Content-type: text/html\n\n<h2>Message Deleted</h2>\n"
+                               "<META http-equiv=\"refresh\" content=\"1;URL=http://%s:%s%s/rss\">",  host, port, uri);
+    } 
+    
+}
+
+static int rss_callback(void *pArg, int argc, char **argv, char **columnNames)
+{
+    struct holder *holder = (struct holder *) pArg;
+    switch_xml_t x_tmp, x_link;
+    char *tmp, *del;
+    switch_time_exp_t tm;
+	char create_date[80] = "";
+	char read_date[80] = "";
+	char rss_date[80] = "";
+	switch_size_t retsize;
+	const char *mime_type = "audio/inline", *new_type;
+    char *ext;
+    char *fname;
+    switch_size_t flen;
+    switch_file_t *fd;
+    long l_created = 0;
+    long l_read = 0;
+    long l_duration = 0;
+    switch_core_time_duration_t duration;
+    char duration_str[80];
+    const char *fmt = "%a, %e %b %Y %T %z";
+    char heard[80];
+    
+    if (argc > 0) {
+        l_created = atol(argv[0]) * 1000000;
+    }
+
+    if (argc > 1) {
+        l_read = atol(argv[1]) * 1000000;
+    }
+
+    if (argc > 9) {
+        l_duration = atol(argv[9]) * 1000000;
+    }
+    
+	switch_core_measure_time(l_duration, &duration);
+    duration.day += duration.yr * 365;
+    duration.hr += duration.day * 24;
+
+    snprintf(duration_str, sizeof(duration_str), "%.2u:%.2u:%.2u", 
+             duration.hr,
+             duration.min,
+             duration.sec
+             );
+
+    if (l_created) {
+        switch_time_exp_lt(&tm, l_created);
+        switch_strftime(create_date, &retsize, sizeof(create_date), fmt, &tm);
+        switch_strftime(rss_date, &retsize, sizeof(create_date), fmt, &tm);
+    }
+
+    if (l_read) {
+        switch_time_exp_lt(&tm, l_read);
+        switch_strftime(read_date, &retsize, sizeof(read_date), fmt, &tm);
+    }
+
+    holder->x_item = switch_xml_add_child_d(holder->x_channel, "item", holder->items++);
+
+    x_tmp = switch_xml_add_child_d(holder->x_item, "title", 0);
+    tmp = switch_mprintf("Message from %s %s on %s", argv[5], argv[6], create_date);
+    switch_xml_set_txt_d(x_tmp, tmp);
+    free(tmp);
+
+    x_tmp = switch_xml_add_child_d(holder->x_item, "description", 0);
+
+    snprintf(heard, sizeof(heard), switch_strlen_zero(read_date) ? "never" : read_date);
+    
+    if ((fname = strrchr(argv[8], '/'))) {
+        fname++;
+    } else {
+        fname = argv[8];
+    }
+
+    del = switch_mprintf("http://%s:%s%s/del/%s", holder->host, holder->port, holder->uri, fname);
+    x_link = switch_xml_add_child_d(holder->x_item, "fsvm:rmlink", 0);
+    switch_xml_set_txt_d(x_link, del);
+
+
+    tmp = switch_mprintf("<![CDATA[Priority: %s<br>Last Heard: %s<br>Duration: %s<br><a href=%s>Delete This Message</a>]]>", 
+                         strcmp(argv[10], URGENT_FLAG_STRING) ? "normal" : "urgent", heard, duration_str, del);
+
+
+    switch_xml_set_txt_d(x_tmp, tmp);
+    free(tmp);
+    free(del);
+
+    x_tmp = switch_xml_add_child_d(holder->x_item, "pubDate", 0);
+    switch_xml_set_txt_d(x_tmp, rss_date);
+
+    x_tmp = switch_xml_add_child_d(holder->x_item, "itunes:duration", 0);
+    switch_xml_set_txt_d(x_tmp, duration_str);
+
+
+    tmp = switch_mprintf("http://%s:%s%s/get/%s", holder->host, holder->port, holder->uri, fname);
+
+    x_tmp = switch_xml_add_child_d(holder->x_item, "guid", 0);
+    switch_xml_set_txt_d(x_tmp, tmp);
+
+    x_link = switch_xml_add_child_d(holder->x_item, "link", 0);
+    switch_xml_set_txt_d(x_link, tmp);
+
+    x_tmp = switch_xml_add_child_d(holder->x_item, "enclosure", 0);
+    switch_xml_set_attr_d(x_tmp, "url", tmp);
+    free(tmp);
+
+    
+
+    if (switch_file_open(&fd, argv[8], SWITCH_FOPEN_READ, SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE, holder->pool) == SWITCH_STATUS_SUCCESS) {
+        flen = switch_file_get_size(fd);
+        tmp = switch_mprintf("%ld", (long) flen);
+        switch_xml_set_attr_d(x_tmp, "length", tmp);
+        free(tmp);
+        switch_file_close(fd);
+    }
+
+    if ((ext = strrchr(fname, '.'))) {
+        ext++;
+        if ((new_type = switch_core_mime_ext2type(ext))) {
+            mime_type = new_type;
+        }
+    }
+    switch_xml_set_attr_d(x_tmp, "type", mime_type);
+    
+    return 0;
+}
+
+
+static void do_rss(vm_profile_t *profile, char *user, char *domain, char *host, char *port, char *uri, switch_stream_handle_t *stream)
+{
+
+    struct holder holder;
+    switch_xml_t x_tmp;
+    char *sql, *xmlstr;
+    char *tmp = NULL;
+
+    stream->write_function(stream, "Content-type: text/xml\n\n");
+    memset(&holder, 0, sizeof(holder));
+    holder.profile = profile;
+    holder.stream = stream;
+    holder.xml = switch_xml_new("rss");
+    holder.user = user;
+    holder.domain = domain;
+    holder.host = host;
+    holder.port = port;
+    holder.uri = uri;
+
+    switch_core_new_memory_pool(&holder.pool);
+    assert(holder.xml);
+    
+    switch_xml_set_attr_d(holder.xml, "xmlns:itunes", "http://www.itunes.com/dtds/podcast-1.0.dtd");
+    switch_xml_set_attr_d(holder.xml, "xmlns:fsvm", "http://www.freeswitch.org/dtd/fsvm.dtd");
+    switch_xml_set_attr_d(holder.xml, "version", "2.0");
+    holder.x_channel = switch_xml_add_child_d(holder.xml, "channel", 0);
+    
+    x_tmp = switch_xml_add_child_d(holder.x_channel, "title", 0);
+    tmp = switch_mprintf("FreeSWITCH Voicemail for %s@%s", user, domain);
+    switch_xml_set_txt_d(x_tmp, tmp);
+    free(tmp);
+
+    x_tmp = switch_xml_add_child_d(holder.x_channel, "link", 0);
+    switch_xml_set_txt_d(x_tmp, "http://www.freeswitch.org");
+
+    x_tmp = switch_xml_add_child_d(holder.x_channel, "description", 0);
+    switch_xml_set_txt_d(x_tmp, "http://www.freeswitch.org");
+    
+    x_tmp = switch_xml_add_child_d(holder.x_channel, "ttl", 0);
+    switch_xml_set_txt_d(x_tmp, "15");
+    
+
+    sql = switch_mprintf("select * from voicemail_data where user='%s' and domain='%s' order by read_flags", user, domain);
+    vm_execute_sql_callback(profile, profile->mutex, sql, rss_callback, &holder);
+
+    xmlstr = switch_xml_toxml(holder.xml);
+
+    stream->write_function(stream, "%s", xmlstr);
+
+    switch_safe_free(sql);
+    switch_safe_free(xmlstr);
+    switch_xml_free(holder.xml);
+    switch_core_destroy_memory_pool(&holder.pool);
+}
+
+SWITCH_STANDARD_API(voicemail_api_function)
+{
+    int argc = 0;
+    char *mydata = NULL, *argv[6];
+    char *host = NULL, *port = NULL, *uri = NULL;
+    char *user = NULL, *domain = NULL;
+    int ct = 0;
+    vm_profile_t *profile = NULL;
+    char *path_info = NULL;
+    int rss = 0, xarg = 0;
+    
+    if (stream->event) {
+        host = switch_event_get_header(stream->event, "http-host");
+        port = switch_event_get_header(stream->event, "http-port");
+        uri = switch_event_get_header(stream->event, "http-uri");
+        user = switch_event_get_header(stream->event, "freeswitch-user");
+        domain = switch_event_get_header(stream->event, "freeswitch-domain");
+        path_info = switch_event_get_header(stream->event, "http-path-info");
+    }
+    
+    if (!switch_strlen_zero(cmd)) {
+        mydata = strdup(cmd);
+        assert(mydata);
+        argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+    }
+    
+    if (argc > 0) {
+        if (!strcasecmp(argv[0], "rss")) {
+            rss++;
+            xarg++;
+        }
+    }
+
+    if (!host) {
+        if (argc - rss < 5) {
+            goto error;
+        }
+        host = argv[xarg++];
+        port = argv[xarg++];
+        uri = argv[xarg++];
+        user = argv[xarg++];
+        domain = argv[xarg++];
+    }
+
+    if (!(host && port && uri && user && domain)) {
+        goto error;
+    }
+
+    profile = switch_core_hash_find(globals.profile_hash, domain);
+    
+    if (!profile) {
+        profile = switch_core_hash_find(globals.profile_hash, "default");
+    }
+    
+    if (!profile) {
+        switch_hash_index_t *hi;
+        void *val;
+        
+        for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
+            switch_hash_this(hi, NULL, NULL, &val);
+            profile = (vm_profile_t *) val;
+            break;
+        }
+    }
+
+    if (!profile) {
+        stream->write_function(stream, "Can't find profile.\n");
+        goto error;
+    }
+
+
+    if (path_info) {
+        if (!strncasecmp(path_info, "get/", 4)) {
+            do_play(profile, user, domain, path_info + 4, stream);        
+        } else if (!strncasecmp(path_info, "del/", 4)) {
+            do_del(profile, user, domain, path_info + 4, stream);        
+        }
+    }
+
+    if (rss || (path_info && !strncasecmp(path_info, "rss", 3))) {
+        do_rss(profile, user, domain, host, port, uri, stream);
+    }
+
+    goto done;
+
+ error:
+    if (host) {
+        if (!ct) {
+            stream->write_function(stream, "Content-type: text/html\n\n<h2>");
+        }
+    }
+    stream->write_function(stream, "Error: %s\n", VOICEMAIL_SYNTAX);
+    
+ done:
+
+    switch_safe_free(mydata);
+
+
+    return SWITCH_STATUS_SUCCESS;
+
+
+}
+
+
 SWITCH_MODULE_LOAD_FUNCTION(mod_voicemail_load)
 {
 	switch_application_interface_t *app_interface;
+    switch_api_interface_t *commands_api_interface;
     switch_status_t status;
 
     if ((status = load_config()) != SWITCH_STATUS_SUCCESS) {
@@ -2137,6 +2551,8 @@
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
 		return SWITCH_STATUS_GENERR;
 	}
+
+	SWITCH_ADD_API(commands_api_interface, "voicemail", "voicemail", voicemail_api_function, VOICEMAIL_SYNTAX);
     
 	/* indicate that the module should continue to be loaded */
 	return SWITCH_STATUS_NOUNLOAD;

Modified: freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c	(original)
+++ freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c	Wed Nov 28 14:56:25 2007
@@ -3339,7 +3339,16 @@
 SWITCH_STANDARD_API(jsapi_function)
 {
 	struct request_obj ro = {0};
+	char *path_info = NULL;
 
+    if (stream->event) {
+		path_info = switch_event_get_header(stream->event, "http-path-info");
+	}
+
+	if (switch_strlen_zero(cmd) && path_info) {
+		cmd = path_info;
+	}
+	
 	if (switch_strlen_zero(cmd)) {
 		stream->write_function(stream, "USAGE: %s\n", jsapi_interface.syntax);
 		return SWITCH_STATUS_SUCCESS;

Modified: freeswitch/trunk/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c
==============================================================================
--- freeswitch/trunk/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c	(original)
+++ freeswitch/trunk/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c	Wed Nov 28 14:56:25 2007
@@ -30,6 +30,7 @@
  *
  */
 #include <switch.h>
+#include <switch_version.h>
 #ifdef _MSC_VER
 #pragma warning(disable:4142)
 #endif
@@ -117,6 +118,14 @@
 }
 
 
+static switch_status_t http_stream_raw_write(switch_stream_handle_t *handle, uint8_t *data, switch_size_t datalen)
+{
+	TSession *r = handle->data;
+
+	return HTTPWrite(r, (char *)data, (uint32_t) datalen) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
+	
+}
+
 static switch_status_t http_stream_write(switch_stream_handle_t *handle, const char *fmt, ...)
 {
 	va_list ap;
@@ -146,7 +155,8 @@
 	char *pass;
 	const char *mypass1 = NULL, *mypass2 = NULL;
 	switch_xml_t x_domain, x_domain_root = NULL, x_user, x_params, x_param;
-
+	const char *box;
+	
     p = RequestHeaderValue(r, "authorization");
 
     if (p) {
@@ -162,16 +172,21 @@
 					*pass++ = '\0';
 				}
 				
-				if (switch_xml_locate_user(user, domain_name, NULL, &x_domain_root, &x_domain, &x_user, NULL) != SWITCH_STATUS_SUCCESS) {
+				if (switch_xml_locate_user(user, domain_name, NULL, &x_domain_root, &x_domain, &x_user, "mailbox=check") != SWITCH_STATUS_SUCCESS) {
 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "can't find user [%s@%s]\n", user, domain_name);
 					goto fail;
 				}
-
+				
+				ResponseAddField(r, "freeswitch-user", user);
+				ResponseAddField(r, "freeswitch-domain", domain_name);
+				
+				box = switch_xml_attr_soft(x_user, "mailbox");
+				
 				if (!(x_params = switch_xml_child(x_user, "params"))) {
 					goto authed;
                 }
 
-
+				
                 for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
                     const char *var = switch_xml_attr_soft(x_param, "name");
                     const char *val = switch_xml_attr_soft(x_param, "value");
@@ -184,23 +199,53 @@
 						ResponseAddField(r, (char *)var, (char *)val);
                     } 
 				}
-
-				sprintf(z, "%s:%s", user, mypass1);
-                Base64Encode(z, t);
 				
-				if (!strcmp(p, t)) {
-                    r->user=strdup(user);
+				if (!(mypass1 && mypass2)) {
+					r->user=strdup(user);
 					goto authed;
-				}
+				} else {
+					if (mypass1) {
+						sprintf(z, "%s:%s", user, mypass1);
+						Base64Encode(z, t);
+				
+						if (!strcmp(p, t)) {
+							r->user=strdup(user);
+							goto authed;
+						}
+					}
 
-				sprintf(z, "%s:%s", user, mypass2);
-                Base64Encode(z, t);
+					if (mypass2) {
+						sprintf(z, "%s:%s", user, mypass2);
+						Base64Encode(z, t);
 				
-				if (!strcmp(p, t)) {
-                    r->user=strdup(user);
-					goto authed;
+						if (!strcmp(p, t)) {
+							r->user=strdup(user);
+							goto authed;
+						}
+					}
+
+					if (box) {
+						if (mypass1) {
+							sprintf(z, "%s:%s", box, mypass1);
+							Base64Encode(z, t);
+					
+							if (!strcmp(p, t)) {
+								r->user=strdup(box);
+								goto authed;
+							}
+						}
+					
+						if (mypass2) {
+							sprintf(z, "%s:%s", box, mypass2);
+							Base64Encode(z, t);
+					
+							if (!strcmp(p, t)) {
+								r->user=strdup(box);
+								goto authed;
+							}
+						}
+					}
 				}
-				
 				goto fail;
 
 
@@ -242,15 +287,64 @@
 			*e++ = '\0';
 		}
 
+		if (!strcmp(domain_name, "this")) {
+			free(domain_name);
+			domain_name = strdup(r->host);
+		}
+
 		ret = !http_directory_auth(r, domain_name);
 
 		free(domain_name);
 	} else {
-		if (globals.realm) {
-			if (!RequestAuth(r, globals.realm, globals.user, globals.pass)) {
-				ret = TRUE;
+		char tmp[512];
+		const char *list[2] = {"index.html", "index.txt"};
+		int x;
+
+		if (!strncmp(r->uri, "/pub", 4)) {
+			char *p = r->uri;
+			char *new_uri = p + 4;
+			if (!new_uri) {
+				new_uri = "/";
+			}
+
+			snprintf(tmp, sizeof(tmp), "%s%s", 
+					 SWITCH_GLOBAL_dirs.htdocs_dir, 
+					 new_uri
+					 );
+			
+
+			if (switch_directory_exists(tmp, NULL) == SWITCH_STATUS_SUCCESS) {
+				for (x = 0; x < 2; x++) {
+					snprintf(tmp, sizeof(tmp), "%s%s%s%s", 
+							 SWITCH_GLOBAL_dirs.htdocs_dir, 
+							 new_uri,
+							 end_of(new_uri) == *SWITCH_PATH_SEPARATOR ? "" : SWITCH_PATH_SEPARATOR,
+							 list[x]
+							 );
+				
+					if (switch_file_exists(tmp, NULL) == SWITCH_STATUS_SUCCESS) {
+						snprintf(tmp, sizeof(tmp), "%s%s%s", 
+								 new_uri,
+								 end_of(new_uri) == '/' ? "" : "/",
+								 list[x]
+								 );
+						new_uri = tmp;
+						break;
+					}
+				}
+			}
+
+			r->uri = strdup(new_uri);
+			free(p);
+
+		} else {
+			if (globals.realm && strncmp(r->uri, "/pub", 4)) {
+				if (!RequestAuth(r, globals.realm, globals.user, globals.pass)) {
+					ret = TRUE;
+				}
 			}
 		}
+
 	}
 
 	return ret;
@@ -265,56 +359,71 @@
 	int i, j = 0;
 	TTableItem *ti;
 	char *dup = NULL;
+	int auth = 0;
+	char *fs_user = NULL, *fs_domain = NULL;
+	char *path_info = NULL;
+	abyss_bool ret = TRUE;
 
 	stream.data = r;
 	stream.write_function = http_stream_write;
+	stream.raw_write_function = http_stream_raw_write;
 
 	if ((command = strstr(r->uri, "/api/"))) {
 		command += 5;
 	} else {
-		return FALSE;
+		ret = FALSE;
+		goto end;
+	}
+
+	if ((path_info = strchr(command, '/'))) {
+		*path_info++ = '\0';
+	}
+	
+	if (strncmp(r->uri, "/domains/", 9)) {
+        goto auth;
 	}
 
 	for (i=0;i<r->response_headers.size;i++) {
 		ti=&r->response_headers.item[i];
-		if (!strcasecmp(ti->name, "http-allowed-api")) {
+		if (!strcasecmp(ti->name, "freeswitch-user")) {
+			fs_user = ti->value;
+		} else if (!strcasecmp(ti->name, "freeswitch-domain")) {
+			fs_domain = ti->value;
+		} else if (!strcasecmp(ti->name, "http-allowed-api")) {
 			int argc, x;
 			char *argv[256] = { 0 };
 			j++;
 			
 			if (!strcasecmp(ti->value, "any")) {
-				goto auth;
-			}
-
-			if (!strcasecmp(ti->value, "none")) {
-				goto unauth;
+				auth++;
 			}
 
 			dup = strdup(ti->value);
 			argc = switch_separate_string(dup, ',', argv, (sizeof(argv) / sizeof(argv[0])));
-
+			
 			for (x = 0; x < argc; x++) {
 				if (!strcasecmp(command, argv[x])) {
-					goto auth;
+					auth++;
 				}
 			}
-
-			goto unauth;
 		}
 	}
 
-	if (r->user && !j) {
-		goto unauth;
+	if (!switch_strlen_zero(r->user) && !j) {
+		auth = 0;
+	}
+	
+	if (auth) {
+		goto auth;
 	}
 
-	goto auth;
-
- unauth:
+	//unauth:
 	ResponseStatus(r, 403);
 	ResponseError(r);
 	switch_safe_free(dup);
 
-	return TRUE;
+	ret = TRUE;
+	goto end;
 
  auth:
 
@@ -322,7 +431,12 @@
 	if (switch_event_create(&stream.event, SWITCH_EVENT_API) == SWITCH_STATUS_SUCCESS) {
 		const char * const content_length = RequestHeaderValue(r, "content-length");
 			
-
+		if (fs_user)
+			switch_event_add_header(stream.event, SWITCH_STACK_BOTTOM, "FreeSWITCH-User", "%s", fs_user);
+		if (fs_domain)
+			switch_event_add_header(stream.event, SWITCH_STACK_BOTTOM, "FreeSWITCH-Domain", "%s", fs_domain);
+		if (path_info)
+			switch_event_add_header(stream.event, SWITCH_STACK_BOTTOM, "HTTP-Path-Info", "%s", path_info);
 		if (r->uri)
 			switch_event_add_header(stream.event, SWITCH_STACK_BOTTOM, "HTTP-URI", "%s", r->uri);
 		if (r->query)
@@ -434,7 +548,7 @@
 	}
 	
 	/* Generation of the server field */
-	ResponseAddField(r,"Server", SERVER_HVERSION);
+	ResponseAddField(r,"Server", "FreeSWITCH-" SWITCH_VERSION_FULL "-mod_xml_rpc");
 
 	for (i=0;i<r->response_headers.size;i++) {
 		ti=&r->response_headers.item[i];
@@ -453,7 +567,10 @@
 	} 
 	
 	//HTTPWriteEnd(r);
-	return TRUE;
+
+ end:
+
+	return ret;
 }
 
 

Modified: freeswitch/trunk/src/switch_apr.c
==============================================================================
--- freeswitch/trunk/src/switch_apr.c	(original)
+++ freeswitch/trunk/src/switch_apr.c	Wed Nov 28 14:56:25 2007
@@ -364,6 +364,28 @@
 	return apr_file_info_get(&finfo, APR_FINFO_SIZE, thefile) == SWITCH_STATUS_SUCCESS ? (switch_size_t)finfo.size : 0;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_directory_exists(const char *dirname, switch_memory_pool_t *pool)
+{
+	apr_dir_t *dir_handle;
+	switch_memory_pool_t *our_pool = NULL;
+	switch_status_t status;
+
+	if (!pool) {
+		switch_core_new_memory_pool(&our_pool);
+		pool = our_pool;
+	}
+
+	if ((status = apr_dir_open(&dir_handle, dirname, pool)) == APR_SUCCESS) {
+		apr_dir_close(dir_handle);
+	}
+	
+	if (our_pool) {
+		switch_core_destroy_memory_pool(&our_pool);
+	}
+
+	return status;
+}
+
 SWITCH_DECLARE(switch_status_t) switch_file_exists(const char *filename, switch_memory_pool_t *pool)
 {
 	int32_t wanted = APR_FINFO_TYPE;

Modified: freeswitch/trunk/src/switch_console.c
==============================================================================
--- freeswitch/trunk/src/switch_console.c	(original)
+++ freeswitch/trunk/src/switch_console.c	Wed Nov 28 14:56:25 2007
@@ -34,6 +34,17 @@
 #include <switch_version.h>
 #define CMD_BUFLEN 1024;
 
+SWITCH_DECLARE(switch_status_t) switch_console_stream_raw_write(switch_stream_handle_t *handle, uint8_t *data, switch_size_t datalen)
+{
+	FILE *out = switch_core_get_console();
+
+	if (out) {
+		fwrite(data, datalen, 1, out);
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	return SWITCH_STATUS_FALSE;
+}
 
 SWITCH_DECLARE(switch_status_t) switch_console_stream_write(switch_stream_handle_t *handle, const char *fmt, ...)
 {

Modified: freeswitch/trunk/src/switch_core.c
==============================================================================
--- freeswitch/trunk/src/switch_core.c	(original)
+++ freeswitch/trunk/src/switch_core.c	Wed Nov 28 14:56:25 2007
@@ -551,6 +551,9 @@
 
 SWITCH_DECLARE(const char *) switch_core_mime_ext2type(const char *ext)
 {
+	if (!ext) {
+		return NULL;
+	}
 	return (const char *) switch_core_hash_find(runtime.mime_types, ext);
 }
 

Modified: freeswitch/trunk/src/switch_xml.cpp
==============================================================================
--- freeswitch/trunk/src/switch_xml.cpp	(original)
+++ freeswitch/trunk/src/switch_xml.cpp	Wed Nov 28 14:56:25 2007
@@ -1457,7 +1457,8 @@
 static char *switch_xml_ampencode(const char *s, switch_size_t len, char **dst, switch_size_t *dlen, switch_size_t *max, short a)
 {
 	const char *e = NULL;
-
+	int immune = 0;
+	
 	if (len) {
 		e = s + len;
 	}
@@ -1466,13 +1467,24 @@
 		while (*dlen + 10 > *max)
 			*dst = (char *)realloc(*dst, *max += SWITCH_XML_BUFSIZE);
 
-		switch (*s) {
+		if (immune) {
+			if (*s == '\0') {
+				return *dst;
+			}
+			(*dst)[(*dlen)++] = *s;
+		} else 
+			switch (*s) {
 		case '\0':
 			return *dst;
 		case '&':
 			*dlen += sprintf(*dst + *dlen, "&amp;");
 			break;
 		case '<':
+			if (*(s+1) == '!') {
+				(*dst)[(*dlen)++] = *s;
+				immune++;
+				break;
+			}
 			*dlen += sprintf(*dst + *dlen, "&lt;");
 			break;
 		case '>':



More information about the Freeswitch-trunk mailing list