[Freeswitch-svn] [commit] r6413 - in freeswitch/trunk/src: . include mod/endpoints/mod_alsa mod/endpoints/mod_portaudio mod/xml_int/mod_xml_rpc

Freeswitch SVN anthm at freeswitch.org
Tue Nov 27 14:25:16 EST 2007


Author: anthm
Date: Tue Nov 27 14:25:16 2007
New Revision: 6413

Modified:
   freeswitch/trunk/src/include/switch_utils.h
   freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c
   freeswitch/trunk/src/mod/endpoints/mod_portaudio/mod_portaudio.c
   freeswitch/trunk/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c
   freeswitch/trunk/src/switch_utils.c
   freeswitch/trunk/src/switch_xml.cpp

Log:
improve http support

Modified: freeswitch/trunk/src/include/switch_utils.h
==============================================================================
--- freeswitch/trunk/src/include/switch_utils.h	(original)
+++ freeswitch/trunk/src/include/switch_utils.h	Tue Nov 27 14:25:16 2007
@@ -56,6 +56,7 @@
 #endif
 
 SWITCH_DECLARE(switch_status_t) switch_b64_encode(unsigned char *in, switch_size_t ilen, unsigned char *out, switch_size_t olen);
+SWITCH_DECLARE(switch_status_t) switch_b64_decode(char *in, char *out, switch_size_t olen);
 
 static inline switch_bool_t switch_is_digit_string(const char *s) {
 

Modified: freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c	Tue Nov 27 14:25:16 2007
@@ -1566,6 +1566,8 @@
 		stream->write_function(stream, "</pre>");
 #endif
 
+		stream->write_function(stream, "Content-type: text/html\n\n");
+
 		wcmd = switch_str_nil(switch_event_get_header(stream->event, "wcmd"));
 		action = switch_event_get_header(stream->event, "action");
 

Modified: freeswitch/trunk/src/mod/endpoints/mod_portaudio/mod_portaudio.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_portaudio/mod_portaudio.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_portaudio/mod_portaudio.c	Tue Nov 27 14:25:16 2007
@@ -1673,6 +1673,8 @@
 
 
 	if (http) {
+		stream->write_function(stream, "Content-type: text/html\n\n");
+
 #if 0
 		switch_event_header_t *hp;
 		stream->write_function(stream, "<pre>");

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	Tue Nov 27 14:25:16 2007
@@ -41,6 +41,7 @@
 #include <xmlrpc-c/abyss.h>
 #include <xmlrpc-c/server.h>
 #include <xmlrpc-c/server_abyss.h>
+#include "../../libs/xmlrpc-c/lib/abyss/src/token.h"
 
 SWITCH_MODULE_LOAD_FUNCTION(mod_xml_rpc_load);
 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_rpc_shutdown);
@@ -137,27 +138,187 @@
 }
 
 
-abyss_bool HandleHook(TSession * r)
+static abyss_bool http_directory_auth(TSession *r, char *domain_name) 
 {
-	char *m = "text/html";
+    char *p, *x;
+    char z[80], t[80];
+	char user[512];
+	char *pass;
+	const char *mypass1 = NULL, *mypass2 = NULL;
+	switch_xml_t x_domain, x_domain_root = NULL, x_user, x_params, x_param;
+
+    p = RequestHeaderValue(r, "authorization");
+
+    if (p) {
+        NextToken(&p);
+        x = GetToken(&p);
+        if (x) {
+            if (!strcasecmp(x,"basic")) {
+
+
+                NextToken(&p);
+				switch_b64_decode(p, user, sizeof(user));
+				if ((pass = strchr(user, ':'))) {
+					*pass++ = '\0';
+				}
+				
+				if (switch_xml_locate_user(user, domain_name, NULL, &x_domain_root, &x_domain, &x_user, NULL) != SWITCH_STATUS_SUCCESS) {
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "can't find user [%s@%s]\n", user, domain_name);
+					goto fail;
+				}
+
+				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");
+                    
+                    if (!strcasecmp(var, "password")) {
+                        mypass1 = val;
+                    } else if (!strcasecmp(var, "vm-password")) {
+                        mypass2 = val;
+                    } else if (!strncasecmp(var, "http-", 5)) {
+						ResponseAddField(r, (char *)var, (char *)val);
+                    } 
+				}
+
+				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 (!strcmp(p, t)) {
+                    r->user=strdup(user);
+					goto authed;
+				}
+				
+				goto fail;
+
+
+			authed:
+				
+				if (x_domain_root) {
+					switch_xml_free(x_domain_root);
+				}
+				
+				return TRUE;
+            }
+        }
+    }
+
+ fail:
+
+	if (x_domain_root) {
+		switch_xml_free(x_domain_root);
+	}
+
+    sprintf(z, "Basic realm=\"%s\"", domain_name);
+    ResponseAddField(r, "WWW-Authenticate", z);
+    ResponseStatus(r, 401);
+    return FALSE;
+}
+
+abyss_bool auth_hook(TSession * r)
+{
+	char *domain_name, *e;
+	abyss_bool ret = FALSE;
+
+
+
+	if (!strncmp(r->uri, "/domains/", 9)) {
+		domain_name = strdup(r->uri + 9);
+		assert(domain_name);
+		
+		if ((e = strchr(domain_name, '/'))) {
+			*e++ = '\0';
+		}
+
+		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;
+			}
+		}
+	}
+
+	return ret;
+}
+
+abyss_bool handler_hook(TSession * r)
+{
+	//char *mime = "text/html";
+	char buf[512] = "HTTP/1.1 200 OK\n";
 	switch_stream_handle_t stream = { 0 };
 	char *command;
+	int i, j = 0;
+	TTableItem *ti;
+	char *dup = NULL;
 
 	stream.data = r;
 	stream.write_function = http_stream_write;
 
-	if (globals.realm) {
-		if (!RequestAuth(r, globals.realm, globals.user, globals.pass)) {
-			return TRUE;
-		}
+	if ((command = strstr(r->uri, "/api/"))) {
+		command += 5;
+	} else {
+		return FALSE;
 	}
 
+	for (i=0;i<r->response_headers.size;i++) {
+		ti=&r->response_headers.item[i];
+		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;
+			}
 
-	if (strncmp(r->uri, "/api/", 5)) {
-		return FALSE;
+			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;
+				}
+			}
+
+			goto unauth;
+		}
+	}
+
+	if (r->user && !j) {
+		goto unauth;
 	}
 
+	goto auth;
+
+ unauth:
+	ResponseStatus(r, 403);
+	ResponseError(r);
+	switch_safe_free(dup);
+
+	return TRUE;
+
+ auth:
+
+
 	if (switch_event_create(&stream.event, SWITCH_EVENT_API) == SWITCH_STATUS_SUCCESS) {
 		const char * const content_length = RequestHeaderValue(r, "content-length");
 			
@@ -258,14 +419,40 @@
 		}
 	}
 
-	command = r->uri + 5;
 
-	ResponseChunked(r);
-	ResponseStatus(r, 200);
-	ResponseContentType(r, m);
-	ResponseWrite(r);
-	switch_api_execute(command, r->query, NULL, &stream);
-	HTTPWriteEnd(r);
+
+	//ResponseChunked(r);
+	
+	//ResponseContentType(r, mime);
+	//ResponseWrite(r);
+
+	HTTPWrite(r, buf, (uint32_t) strlen(buf));
+
+	/* generation of the date field */
+	if (DateToString(&r->date, buf)) {
+		ResponseAddField(r,"Date", buf);
+	}
+	
+	/* Generation of the server field */
+	ResponseAddField(r,"Server", SERVER_HVERSION);
+
+	for (i=0;i<r->response_headers.size;i++) {
+		ti=&r->response_headers.item[i];
+		ConnWrite(r->conn,ti->name,strlen(ti->name));
+		ConnWrite(r->conn,": ",2);
+		ConnWrite(r->conn,ti->value,strlen(ti->value));
+		ConnWrite(r->conn,CRLF,2);
+	}
+
+	
+	if (switch_api_execute(command, r->query, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
+		r->done = TRUE;
+	} else {
+		ResponseStatus(r, 404);
+		ResponseError(r);
+	} 
+	
+	//HTTPWriteEnd(r);
 	return TRUE;
 }
 
@@ -387,8 +574,9 @@
 		return SWITCH_STATUS_TERM;
 	}
 
-	ServerAddHandler(&abyssServer, HandleHook);
 
+	ServerAddHandler(&abyssServer, handler_hook);
+	ServerAddHandler(&abyssServer, auth_hook);
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Starting HTTP Port %d, DocRoot [%s]\n", globals.port, SWITCH_GLOBAL_dirs.htdocs_dir);
 	while (globals.running) {
 		ServerRunOnce2(&abyssServer, ABYSS_FOREGROUND);

Modified: freeswitch/trunk/src/switch_utils.c
==============================================================================
--- freeswitch/trunk/src/switch_utils.c	(original)
+++ freeswitch/trunk/src/switch_utils.c	Tue Nov 27 14:25:16 2007
@@ -91,6 +91,46 @@
 }
 
 
+SWITCH_DECLARE(switch_status_t) switch_b64_decode(char *in, char *out, switch_size_t olen)
+{
+
+	char l64[256];
+	int b = 0, c, l = 0, i;
+	char *ip, *op = out;
+	size_t ol = 0;
+
+	for (i=0; i<256; i++) {
+		l64[i] = -1;
+	}
+
+	for (i=0; i<64; i++) {
+		l64[(int)switch_b64_table[i]] = i;
+	}
+
+	for (ip = in; ip && *ip; ip++) {
+		c = l64[(int)*ip];
+		if (c == -1) {
+			continue;
+		}
+
+		b = (b << 6) + c;
+		l += 6;
+
+		while (l >= 8) {
+			op[ol++] = (b >> (l -= 8)) % 256;
+			if (ol >= olen -2) {
+				goto end;
+			}
+		}
+	}
+
+ end:
+
+	op[ol++] = '\0';
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
 
 static int write_buf(int fd, const char *buf)
 {

Modified: freeswitch/trunk/src/switch_xml.cpp
==============================================================================
--- freeswitch/trunk/src/switch_xml.cpp	(original)
+++ freeswitch/trunk/src/switch_xml.cpp	Tue Nov 27 14:25:16 2007
@@ -1316,6 +1316,7 @@
 	} else {
 		snprintf(params, sizeof(params), "user=%s&domain=%s&ip=%s", 
 				 switch_str_nil(user_name), switch_str_nil(domain_name), switch_str_nil(ip));
+		xtra_params = "";
 	}
 	if ((status = switch_xml_locate_domain(domain_name, params, root, domain)) != SWITCH_STATUS_SUCCESS) {
 		return status;
@@ -1328,11 +1329,17 @@
 	} 
 
 	if (user_name) {
-		if (!(*user = switch_xml_find_child(*domain, "user", "id", user_name)) && strstr(xtra_params, "mailbox") && 
-			!(*user = switch_xml_find_child(*domain, "user", "mailbox", user_name))) {
-			return SWITCH_STATUS_FALSE;
+		
+		if (strstr(xtra_params, "mailbox")) {
+			if ((*user = switch_xml_find_child(*domain, "user", "mailbox", user_name))) {
+				return SWITCH_STATUS_SUCCESS;
+			}
 		}
-		return SWITCH_STATUS_SUCCESS;
+
+		if ((*user = switch_xml_find_child(*domain, "user", "id", user_name))) {
+			return SWITCH_STATUS_SUCCESS;
+		}
+		
 	}
 
 	return SWITCH_STATUS_FALSE;



More information about the Freeswitch-svn mailing list