[Freeswitch-svn] [commit] r10705 - freeswitch/trunk/src/mod/applications/mod_http

FreeSWITCH SVN ericdc at freeswitch.org
Wed Dec 10 13:43:26 PST 2008


Author: ericdc
Date: Wed Dec 10 16:43:26 2008
New Revision: 10705

Log:
Initial upload.



Added:
   freeswitch/trunk/src/mod/applications/mod_http/Makefile
   freeswitch/trunk/src/mod/applications/mod_http/arraylist.c
   freeswitch/trunk/src/mod/applications/mod_http/arraylist.h
   freeswitch/trunk/src/mod/applications/mod_http/bits.h
   freeswitch/trunk/src/mod/applications/mod_http/config.h
   freeswitch/trunk/src/mod/applications/mod_http/debug.c
   freeswitch/trunk/src/mod/applications/mod_http/debug.h
   freeswitch/trunk/src/mod/applications/mod_http/http_req.c
   freeswitch/trunk/src/mod/applications/mod_http/http_req.h
   freeswitch/trunk/src/mod/applications/mod_http/json.h
   freeswitch/trunk/src/mod/applications/mod_http/json_object.c
   freeswitch/trunk/src/mod/applications/mod_http/json_object.h
   freeswitch/trunk/src/mod/applications/mod_http/json_object_private.h
   freeswitch/trunk/src/mod/applications/mod_http/json_tokener.c
   freeswitch/trunk/src/mod/applications/mod_http/json_tokener.h
   freeswitch/trunk/src/mod/applications/mod_http/json_util.c
   freeswitch/trunk/src/mod/applications/mod_http/json_util.h
   freeswitch/trunk/src/mod/applications/mod_http/linkhash.c
   freeswitch/trunk/src/mod/applications/mod_http/linkhash.h
   freeswitch/trunk/src/mod/applications/mod_http/mod_http.c
   freeswitch/trunk/src/mod/applications/mod_http/printbuf.c
   freeswitch/trunk/src/mod/applications/mod_http/printbuf.h
   freeswitch/trunk/src/mod/applications/mod_http/url_encoding.c
   freeswitch/trunk/src/mod/applications/mod_http/url_encoding.h

Added: freeswitch/trunk/src/mod/applications/mod_http/Makefile
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/Makefile	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,5 @@
+BASE=../../../..
+LOCAL_SOURCES=arraylist.c debug.c json_object.c json_tokener.c json_util.c linkhash.c printbuf.c url_encoding.c http_req.c
+LOCAL_OBJS=arraylist.o debug.o json_object.o json_tokener.o json_util.o linkhash.o printbuf.o url_encoding.o http_req.o
+include $(BASE)/build/modmake.rules
+

Added: freeswitch/trunk/src/mod/applications/mod_http/arraylist.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/arraylist.c	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,93 @@
+/*
+ * $Id: arraylist.c,v 1.4 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#include "config.h"
+
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <string.h>
+#endif /* STDC_HEADERS */
+
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+
+#include "bits.h"
+#include "arraylist.h"
+
+struct array_list*
+array_list_new(array_list_free_fn *free_fn)
+{
+  struct array_list *this;
+
+  if(!(this = calloc(1, sizeof(struct array_list)))) return NULL;
+  this->size = ARRAY_LIST_DEFAULT_SIZE;
+  this->length = 0;
+  this->free_fn = free_fn;
+  if(!(this->array = calloc(sizeof(void*), this->size))) {
+    free(this);
+    return NULL;
+  }
+  return this;
+}
+
+extern void
+array_list_free(struct array_list *this)
+{
+  int i;
+  for(i = 0; i < this->length; i++)
+    if(this->array[i]) this->free_fn(this->array[i]);
+  free(this->array);
+  free(this);
+}
+
+void*
+array_list_get_idx(struct array_list *this, int i)
+{
+  if(i >= this->length) return NULL;
+  return this->array[i];
+}
+
+static int array_list_expand_internal(struct array_list *this, int max)
+{
+  void *t;
+  int new_size;
+
+  if(max < this->size) return 0;
+  new_size = max(this->size << 1, max);
+  if(!(t = realloc(this->array, new_size*sizeof(void*)))) return -1;
+  this->array = t;
+  (void)memset(this->array + this->size, 0, (new_size-this->size)*sizeof(void*));
+  this->size = new_size;
+  return 0;
+}
+
+int
+array_list_put_idx(struct array_list *this, int idx, void *data)
+{
+  if(array_list_expand_internal(this, idx)) return -1;
+  if(this->array[idx]) this->free_fn(this->array[idx]);
+  this->array[idx] = data;
+  if(this->length <= idx) this->length = idx + 1;
+  return 0;
+}
+
+int
+array_list_add(struct array_list *this, void *data)
+{
+  return array_list_put_idx(this, this->length, data);
+}
+
+int
+array_list_length(struct array_list *this)
+{
+  return this->length;
+}

Added: freeswitch/trunk/src/mod/applications/mod_http/arraylist.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/arraylist.h	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,45 @@
+/*
+ * $Id: arraylist.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _arraylist_h_
+#define _arraylist_h_
+
+#define ARRAY_LIST_DEFAULT_SIZE 32
+
+typedef void (array_list_free_fn) (void *data);
+
+struct array_list
+{
+  void **array;
+  int length;
+  int size;
+  array_list_free_fn *free_fn;
+};
+
+extern struct array_list*
+array_list_new(array_list_free_fn *free_fn);
+
+extern void
+array_list_free(struct array_list *al);
+
+extern void*
+array_list_get_idx(struct array_list *al, int i);
+
+extern int
+array_list_put_idx(struct array_list *al, int i, void *data);
+
+extern int
+array_list_add(struct array_list *al, void *data);
+
+extern int
+array_list_length(struct array_list *al);
+
+#endif

Added: freeswitch/trunk/src/mod/applications/mod_http/bits.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/bits.h	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,27 @@
+/*
+ * $Id: bits.h,v 1.10 2006/01/30 23:07:57 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _bits_h_
+#define _bits_h_
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef max
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+#define hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9)
+#define error_ptr(error) ((void*)error)
+#define is_error(ptr) ((unsigned long)ptr > (unsigned long)-4000L)
+
+#endif

Added: freeswitch/trunk/src/mod/applications/mod_http/config.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/config.h	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,118 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+   to 0 otherwise. */
+#define HAVE_MALLOC 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `open' function. */
+#define HAVE_OPEN 1
+
+/* Define to 1 if your system has a GNU libc compatible `realloc' function,
+   and to 0 otherwise. */
+#define HAVE_REALLOC 1
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the `strndup' function. */
+#define HAVE_STRNDUP 1
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `vasprintf' function. */
+#define HAVE_VASPRINTF 1
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
+
+/* Define to 1 if you have the `vsyslog' function. */
+#define HAVE_VSYSLOG 1
+
+/* Name of package */
+#define PACKAGE ""
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "michael at metaparadigm.com"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "JSON C Library"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "JSON C Library 0.3"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "json-c"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.3"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "0.3"
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to rpl_malloc if the replacement function should be used. */
+/* #undef malloc */
+
+/* Define to rpl_realloc if the replacement function should be used. */
+/* #undef realloc */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */

Added: freeswitch/trunk/src/mod/applications/mod_http/debug.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/debug.c	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,94 @@
+/*
+ * $Id: debug.c,v 1.5 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#if HAVE_SYSLOG_H
+# include <syslog.h>
+#endif /* HAVE_SYSLOG_H */
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif /* HAVE_SYS_PARAM_H */
+
+#include "debug.h"
+
+static int _syslog = 0;
+static int _debug = 0;
+
+void mc_set_debug(int debug) { _debug = debug; }
+int mc_get_debug() { return _debug; }
+
+extern void mc_set_syslog(int syslog)
+{
+  _syslog = syslog;
+}
+
+void mc_abort(const char *msg, ...)
+{
+  va_list ap;
+  va_start(ap, msg);
+#if HAVE_VSYSLOG
+  if(_syslog) {
+	  vsyslog(LOG_ERR, msg, ap);
+  } else
+#endif
+	  vprintf(msg, ap);
+  exit(1);
+}
+
+
+void mc_debug(const char *msg, ...)
+{
+  va_list ap;
+  if(_debug) {
+    va_start(ap, msg);
+#if HAVE_VSYSLOG
+    if(_syslog) {
+		vsyslog(LOG_DEBUG, msg, ap);
+	} else
+#endif
+		vprintf(msg, ap);
+  }
+}
+
+void mc_error(const char *msg, ...)
+{
+  va_list ap;
+  va_start(ap, msg);
+#if HAVE_VSYSLOG
+    if(_syslog) {
+		vsyslog(LOG_ERR, msg, ap);
+	} else
+#endif
+		vfprintf(stderr, msg, ap);
+}
+
+void mc_info(const char *msg, ...)
+{
+  va_list ap;
+  va_start(ap, msg);
+#if HAVE_VSYSLOG
+    if(_syslog) {
+		vsyslog(LOG_INFO, msg, ap);
+	} else 
+#endif
+		vfprintf(stderr, msg, ap);
+}

Added: freeswitch/trunk/src/mod/applications/mod_http/debug.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/debug.h	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,24 @@
+/*
+ * $Id: debug.h,v 1.5 2006/01/30 23:07:57 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _DEBUG_H_
+#define _DEBUG_H_
+
+extern void mc_set_debug(int debug);
+extern int mc_get_debug();
+
+extern void mc_set_syslog(int syslog);
+extern void mc_abort(const char *msg, ...);
+extern void mc_debug(const char *msg, ...);
+extern void mc_error(const char *msg, ...);
+extern void mc_info(const char *msg, ...);
+
+#endif

Added: freeswitch/trunk/src/mod/applications/mod_http/http_req.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/http_req.c	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,680 @@
+/* 
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2008, Eric des Courtis <eric.des.courtis at benbria.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Eric des Courtis <eric.des.courtis at benbria.com>
+ * Copyright (C) Benbria. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Eric des Courtis <eric.des.courtis at benbria.com>
+ *
+ *
+ * http_req.c -- HTTP client implementation
+ *
+ */
+
+#include "http_req.h"
+
+/*
+extern int dprintf(int, const char *, ...);
+extern int isblank(int);
+*/
+
+/* NOTE: v = version, header = h, status = s, newline = n, phrase = p */
+static accept_state_t state_start(char c, state_machine_t *sm);
+static accept_state_t state_shp  (char c, state_machine_t *sm);
+static accept_state_t state_n    (char c, state_machine_t *sm);
+static accept_state_t state_vhp_A(char c, state_machine_t *sm);
+static accept_state_t state_vhp_B(char c, state_machine_t *sm);
+static accept_state_t state_vhp_C(char c, state_machine_t *sm);
+static accept_state_t state_vhp_D(char c, state_machine_t *sm);
+static accept_state_t state_vhp_E(char c, state_machine_t *sm);
+static accept_state_t state_vhp_F(char c, state_machine_t *sm);
+static accept_state_t state_vhp_G(char c, state_machine_t *sm);
+static accept_state_t state_vhp_H(char c, state_machine_t *sm);
+static accept_state_t state_hp_A (char c, state_machine_t *sm);
+static accept_state_t state_hp_B (char c, state_machine_t *sm);
+static accept_state_t state_p    (char c, state_machine_t *sm);
+static accept_state_t state_error(char c, state_machine_t *sm);
+
+static int read_all(int s, char *buf, size_t len);
+
+#ifdef DEBUG
+int main(int argc, char *argv[])
+{
+    http_response_t response;
+    http_request_t request;
+    int ret;
+    int i;
+
+    if(argc != 2) return EXIT_FAILURE;
+
+    request.method = GET;
+    request.version = DEFAULT_HTTP_VERSION;
+    request.url = argv[1];
+    request.header_len = 0;
+    request.body_len = 0;
+
+    ret = http_req(&request, &response);
+    if(ret == ERROR) return EXIT_FAILURE;
+    
+    printf("Version     : %s\n", response.version);
+    printf("Status Code : %d\n", response.status_code);
+    printf("Phrase      : %s\n", response.phrase);
+    
+    for(i = 0; i < response.header_len; i++){
+        printf(
+            "Header      : key = [%s] value = [%s]\n", 
+            response.headers[i].field_name, response.headers[i].value
+        );
+    }
+
+    fflush(stdout);
+    write(STDOUT_FILENO, response.body, response.body_len);
+    printf("\n");
+
+    free_http_response(&response);
+
+    return EXIT_SUCCESS;
+}
+#endif
+
+int http_req(http_request_t *req, http_response_t *res)
+{
+    uint32_t addr;
+    int s;
+    int ret;
+    uint16_t port = 0;
+    size_t len;
+    struct sockaddr_in sck;
+    struct hostent *hst;
+    char *hostname;
+    char *method;
+    char *buf;
+    int buf_len;
+    ssize_t i;
+    int j;
+    int l;
+    int m;
+    int p;
+    int q = 0;
+    char f = HTTP_FALSE;
+    char port_s[MAX_PORT_LEN];
+    sighandler_t sig;
+    struct timeval tv;
+
+    tv.tv_sec  = 1;
+    tv.tv_usec = 0;
+
+
+    (void)memset(&sck, 0, sizeof(sck));
+
+    sig = signal(SIGPIPE, SIG_IGN);
+    if(sig == SIG_ERR){
+        fprintf(stderr, "Cannot ignore SIGPIPE signal\n");
+        return ERROR;
+    }
+ 
+    s = socket(PF_INET, SOCK_STREAM, 0);
+    if(s == ERROR){
+        perror("Could not create socket");
+        return ERROR;
+    }
+
+    (void)setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+    (void)setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
+
+    len = strlen(req->url);
+    hostname = (char *)malloc(len * sizeof(char) + 1);
+    if(hostname == NULL){
+        perror("Could not allocate memory for hostname");
+        close(s);
+        return ERROR;
+    }
+    
+    EMPTY_STRING(hostname);
+
+    l = strlen(req->url) + 1;
+    m = strlen("http://");
+    for(p = 0, j = m; j < l; j++){
+        if(req->url[j] == ':'){
+            strncpy(hostname, req->url + m, j - m);
+            hostname[j - m] = '\0';
+            f = HTTP_TRUE;
+            p = j;
+            continue;
+        }
+
+        if((req->url[j] == '/' || req->url[j] == '\0')  && f == HTTP_TRUE){
+            if((j - p) < MAX_PORT_LEN){
+                strncpy(port_s, req->url + p + 1, j - p);
+                port_s[j - p] = '\0';
+                port = (uint16_t)atoi(port_s);
+            }else port = 0;
+            q = j;
+            break;
+        }
+
+        if((req->url[j] == '/' || req->url[j] == '\0') && f == HTTP_FALSE){
+            strncpy(hostname, req->url + m, j - m);
+            hostname[j - m] = '\0';
+            port = DEFAULT_HTTP_PORT;
+            q = j;
+            break;
+        }
+    }
+
+    if(port == 0 || hostname[0] == '\0'){
+        fprintf(stderr, "Invalid URL\n");
+        close(s);
+        free(hostname);
+        return ERROR;
+    }
+
+    l = strlen(hostname);
+    for(j = 0; j < l; j++){
+        if(hostname[j] == '/'){
+            hostname[j] = '\0';
+            break;
+        }
+    }
+
+    hst = gethostbyname(hostname);
+    if(hst == NULL){
+        herror("Could not find host");
+        close(s);
+        free(hostname);
+        return ERROR;
+    }
+
+    addr = *((uint32_t *)hst->h_addr_list[0]);
+    
+    sck.sin_family = AF_INET;
+    sck.sin_port = htons(port);
+    sck.sin_addr.s_addr = addr;
+
+    ret = connect(s, (struct sockaddr *)&sck, sizeof(sck));
+    if(ret == ERROR){
+        perror("Could not connect to host");
+        close(s);
+        free(hostname);
+        return ERROR;
+    }
+    
+    switch(req->method){
+    case GET:
+        method = HTTP_GET_METHOD;
+        break;
+    case HEAD:
+        method = HTTP_HEAD_METHOD;
+        break;
+    case POST:
+        method = HTTP_POST_METHOD;
+        break;
+    case DELETE:
+	method = HTTP_DELETE_METHOD;
+	break;
+    case PUT:
+	method = HTTP_PUT_METHOD;
+	break;
+    default:
+        method = HTTP_GET_METHOD;
+    }
+   
+    if(req->url[q] == '/'){ 
+        dprintf(s, "%s %s HTTP/%s\r\n", method, req->url + q, req->version);
+    }else{
+        dprintf(s, "%s /%s HTTP/%s\r\n", method, req->url + q, req->version);
+    }
+    
+    if(port != DEFAULT_HTTP_PORT)
+        dprintf(s, "Host: %s:%d\r\n", hostname, port);   
+    else dprintf(s, "Host: %s\r\n", hostname);   
+    dprintf(s, "Connection: close\r\n");
+    dprintf(s, "Content-Length: %d\r\n", req->body_len); 
+
+    for(i = 0; i < req->header_len; i++){
+        dprintf(
+            s, 
+            "%s: %s\r\n", 
+            req->headers[i].field_name,
+            req->headers[i].value
+        );
+    }
+
+    dprintf(s, "\r\n");
+
+    
+    if(req->body != NULL && req->body_len != 0){
+        ret = write(s, req->body, req->body_len);
+        if(ret == ERROR){
+            perror("Could not write body to socket");
+            free(hostname);
+            return ERROR;
+        }
+    }
+
+    buf = (char *)malloc(RECV_BUFF_SIZE * sizeof(char));
+    if(buf == NULL){
+        perror("Could not allocate memory for buffer");
+        close(s);
+        free(hostname);
+        return ERROR;
+    }
+
+    buf_len = read_all(s, buf, RECV_BUFF_SIZE -1);
+    if(buf_len == ERROR){
+        perror("Could not read into buffer");
+        free(hostname);
+        return ERROR;
+    }
+    buf[buf_len] = '\0';
+   
+    close(s);
+   
+    (void)signal(SIGPIPE, sig);
+    free(hostname);
+    return http_parse_response(buf, buf_len, res);
+}
+
+int http_parse_response(char *buf, ssize_t buf_len, http_response_t *response)
+{
+    token_t token;
+    state_machine_t sm;
+    int pos;
+    ssize_t size;
+    char buff[STATUS_CODE_LEN];
+    int old_pos;
+    int nt;
+    int i;
+    int j;
+    int f;
+
+    INIT_STATE_MACHINE(&sm);
+    
+    sm.buf = buf;
+    sm.buf_len = buf_len;
+
+    pos = sm.pos;
+    token = get_next_token(&sm);
+    if(token != VERSION){
+        fprintf(stderr, "ERROR %d-%d\n", VERSION, token);
+        return ERROR;
+    }
+    
+    size = sm.pos - pos;
+    response->version = (char *)malloc((size + 1) * sizeof(char));
+    if(response->version == NULL){
+        perror("Cannot allocate memory for version number");
+        return ERROR;
+    }
+    strncpy(response->version, sm.buf + pos, size);
+    response->version[size] = '\0';
+
+    pos = sm.pos;
+    token = get_next_token(&sm);
+    if(token != STATUS_CODE){
+        fprintf(stderr, "ERROR %d-%d\n", STATUS_CODE, token);
+        return ERROR;
+    }
+
+    size = sm.pos - pos;
+
+    buff[STATUS_CODE_LEN - 1] = '\0';
+    strncpy(buff, sm.buf + pos, STATUS_CODE_LEN - 1);
+
+    response->status_code = atoi(buff);
+
+    pos = sm.pos;
+    token = get_next_token(&sm);
+    if(token != PHRASE){
+        fprintf(stderr, "ERROR %d-%d\n", PHRASE, token);
+        return ERROR;
+    }
+
+    size = sm.pos - pos - 2;
+    response->phrase = (char *)malloc((size + 1) * sizeof(char));
+    if(response->phrase == NULL){
+        perror("Cannot allocate memory for phrase");
+        return ERROR;
+    }
+    strncpy(response->phrase, sm.buf + pos, size);
+    response->phrase[size] = '\0';
+
+    old_pos = sm.pos;
+    nt = 0;
+    f = HTTP_FALSE;
+    do{
+        token = get_next_token(&sm);
+        switch(token){
+        case PHRASE:
+        case STATUS_CODE:
+            f = HTTP_FALSE;
+        case VERSION:
+        case NEWLINE:
+            break;
+        case HEADER:
+            if(f == HTTP_FALSE){
+                nt++;
+                f = HTTP_TRUE;
+            }
+            else f = HTTP_FALSE;
+            break;
+        case SYNTAX_ERROR:
+            return ERROR; 
+        }
+    
+        if(token != HEADER && token != PHRASE && token != STATUS_CODE) break;
+    }while(token != SYNTAX_ERROR);
+ 
+    if(nt != 0){ 
+        response->headers = (http_header_t *)malloc(sizeof(http_header_t)*nt);
+        if(response->headers == NULL){
+            perror("Could not allocate memory for headers");
+            return ERROR;
+        }
+    }else response->headers = NULL;
+
+    response->header_len = nt;
+
+    sm.pos = old_pos;
+    for(i = 0; i < nt; i++){
+        pos = sm.pos;
+        sm.state = state_start;
+        sm.stop = HTTP_FALSE;
+        token = get_next_token(&sm);
+        size = sm.pos - pos;
+        size -= 2;
+
+        response->headers[i].field_name = 
+            (char *)malloc((size + 1) * sizeof(char));
+
+        if(response->headers[i].field_name == NULL){
+            perror("Could not allocate memory for header");
+            return ERROR;
+        }
+
+        strncpy(response->headers[i].field_name, sm.buf + pos, size);
+        response->headers[i].field_name[size] = '\0';
+
+        pos = sm.pos;
+        token = get_next_token(&sm);
+        if(token == HEADER || token == STATUS_CODE){
+            for(j = 0; 
+                ((sm.buf + pos)[j] == '\r' 
+                    && (sm.buf + pos)[j + 1] == '\n') == 0; 
+                j++
+            );
+            size = j;
+            sm.pos = j + 2;
+        }else size = sm.pos - pos - 2;
+
+        response->headers[i].value = 
+            (char *)malloc((size + 1) * sizeof(char));
+
+        if(response->headers[i].value == NULL){
+            perror("Could not allocate memory for header");
+            return ERROR;
+        }
+        strncpy(response->headers[i].value, sm.buf + pos, size);
+        response->headers[i].value[size] = '\0';
+        
+    }
+
+    pos = sm.pos;
+    token = get_next_token(&sm);
+    if(token != NEWLINE){
+        fprintf(stderr, "ERROR %d-%d\n", NEWLINE, token);
+        return ERROR;
+    }
+
+
+    response->body = (char *)malloc((buf_len - sm.pos + 1) * sizeof(char));
+    if(response->body == NULL){
+        perror("Could not allocate memory for body");
+        return ERROR;
+    }
+
+    response->body_len = buf_len - sm.pos;
+    response->body[response->body_len] = '\0';
+
+    (void)memcpy(response->body, buf + sm.pos, response->body_len);
+
+    return SUCCESS;
+}
+
+void free_http_response(http_response_t *response)
+{
+    free(response->version);
+    free(response->phrase);
+    if(response->headers != NULL) free(response->headers);
+    if(response->body != NULL)    free(response->body);
+}
+
+token_t get_next_token(state_machine_t *sm)
+{
+    char c;
+    accept_state_t accept;
+
+    while(sm->stop != HTTP_TRUE){
+        c = sm->buf[sm->pos];
+        accept = sm->state(c, sm);
+        switch(accept){
+        case NOAS:
+        case ASNR:
+            sm->pos++;
+        case ASWR:
+            break;
+        }
+
+        switch(accept){
+        case ASNR:
+        case ASWR:
+            sm->state = state_start;
+            return sm->token;
+        case NOAS:
+            break;
+        }
+        
+        if(sm->pos >= sm->buf_len){
+            sm->stop = HTTP_TRUE;
+            break;
+        }
+    }
+    
+    return SYNTAX_ERROR;
+}
+
+static accept_state_t state_start(char c, state_machine_t *sm)
+{
+    if(toupper(c) == 'H')               sm->state = state_vhp_A;
+    else if(isdigit(c))                 sm->state = state_shp;
+    else if(c == '\r' || c == '\n')     sm->state = state_n;
+    else if(isprint(c))                 sm->state = state_hp_A;
+    else                                sm->state = state_error;
+
+    return NOAS;
+}
+
+static accept_state_t state_shp(char c, state_machine_t *sm)
+{
+    if(isdigit(c))                      sm->state = state_shp;
+    else if(isblank(c)){
+        sm->token = STATUS_CODE;
+        return ASNR;
+    }else if(c == ':')                  sm->state = state_hp_B;
+    else if(c == '\r' || c == '\n')     sm->state = state_p;
+    else if(isprint(c))                 sm->state = state_hp_A;
+    else                                sm->state = state_error;
+    
+    return NOAS;
+}
+
+static accept_state_t state_n(char c, state_machine_t *sm)
+{
+    if(c == '\r' || c == '\n'){
+        sm->token = NEWLINE;
+        return ASNR;
+    }else if(c == ':')                  sm->state = state_hp_B;
+    else if(isprint(c))                 sm->state = state_hp_A;
+    else                                sm->state = state_error;
+
+    return NOAS;
+}
+
+static accept_state_t state_vhp_A(char c, state_machine_t *sm)
+{
+    if(toupper(c) == 'T')               sm->state = state_vhp_B;
+    else if(isprint(c))                 sm->state = state_hp_A;
+    else if(c == '\n' || c == '\r')     sm->state = state_p;
+    else                                sm->state = state_error;
+
+    return NOAS;
+}
+
+static accept_state_t state_vhp_B(char c, state_machine_t *sm)
+{
+    if(toupper(c) == 'T')               sm->state = state_vhp_C;
+    else if(isprint(c))                 sm->state = state_hp_A;
+    else if(c == '\n' || c == '\r')     sm->state = state_p;
+    else                                sm->state = state_error;
+
+    return NOAS;
+}
+
+static accept_state_t state_vhp_C(char c, state_machine_t *sm)
+{
+    if(toupper(c) == 'P')               sm->state = state_vhp_D;
+    else if(isprint(c))                 sm->state = state_hp_A;
+    else if(c == '\n' || c == '\r')     sm->state = state_p;
+    else                                sm->state = state_error;
+    
+    return NOAS;
+}
+
+static accept_state_t state_vhp_D(char c, state_machine_t *sm)
+{
+    if(toupper(c) == '/')               sm->state = state_vhp_E;
+    else if(isprint(c))                 sm->state = state_hp_A;
+    else if(c == '\n' || c == '\r')     sm->state = state_p;
+    else                                sm->state = state_error;
+    
+    return NOAS;
+}
+
+static accept_state_t state_vhp_E(char c, state_machine_t *sm)
+{
+    if(isdigit(c))                      sm->state = state_vhp_F;
+    else if(isprint(c))                 sm->state = state_hp_A;
+    else if(c == '\n' || c == '\r')     sm->state = state_p;
+    else                                sm->state = state_error;
+    
+    return NOAS;
+}
+
+static accept_state_t state_vhp_F(char c, state_machine_t *sm)
+{
+    if(isdigit(c))                      sm->state = state_vhp_F;
+    else if(c == '.')                   sm->state = state_vhp_G;
+    else if(isprint(c))                 sm->state = state_hp_A;
+    else if(c == '\n' || c == '\r')     sm->state = state_p;
+    else                                sm->state = state_error;
+    
+    return NOAS;
+}
+
+static accept_state_t state_vhp_G(char c, state_machine_t *sm)
+{
+    if(isdigit(c))                      sm->state = state_vhp_H;
+    else if(isprint(c))                 sm->state = state_hp_A;
+    else if(c == '\n' || c == '\r')     sm->state = state_p;
+    else                                sm->state = state_error;
+    
+    return NOAS;
+}
+
+static accept_state_t state_vhp_H(char c, state_machine_t *sm)
+{
+    if(isdigit(c))                      sm->state = state_vhp_H;
+    else if(isblank(c)){
+        sm->token = VERSION;
+        return ASNR;
+
+    }else if(isprint(c))                sm->state = state_hp_A;
+
+    return NOAS;
+}
+
+static accept_state_t state_hp_A(char c, state_machine_t *sm)
+{
+    if(c == ':')                        sm->state = state_hp_B;
+    else if(c == '\r' || c == '\n')     sm->state = state_p;
+    else if(isprint(c))                 sm->state = state_hp_A;
+    else                                sm->state = state_error;
+
+    return NOAS;
+}
+
+static accept_state_t state_hp_B(char c, state_machine_t *sm)
+{
+    if(isblank(c)){
+        sm->token = HEADER;
+        return ASNR;
+    } else if(c == '\r' || c == '\n')   sm->state = state_p;
+    else if(c == ':')                   sm->state = state_hp_B;
+    else if(isprint(c))                 sm->state = state_hp_A;
+    else                                sm->state = state_error;
+
+    return NOAS;
+}
+
+static accept_state_t state_p(char c, state_machine_t *sm)
+{
+    if(c == '\r' || c == '\n'){
+        sm->token = PHRASE;
+        return ASNR;
+    }else if(c == ':')          sm->state = state_hp_B; 
+    else if(isprint(c))         sm->state = state_hp_A;
+    else                        sm->state = state_error;
+
+    return NOAS;
+}
+
+static accept_state_t state_error(char c, state_machine_t *sm)
+{
+    c = 0;
+    sm->token = SYNTAX_ERROR;
+
+    return ASNR;
+}
+
+static int read_all(int s, char *buf, size_t len)
+{
+    size_t t;
+    size_t r = ERROR;
+ 
+    for(t = 0; t < len && r != 0;){
+        r = read(s, buf + t, len - t);
+        if((int)r == ERROR){
+            return ERROR;
+        }else{
+            t += r;
+        }
+    }
+
+    return (int)t;
+}
+

Added: freeswitch/trunk/src/mod/applications/mod_http/http_req.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/http_req.h	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,138 @@
+/* 
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2008, Eric des Courtis <eric.des.courtis at benbria.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Eric des Courtis <eric.des.courtis at benbria.com>
+ * Copyright (C) Benbria. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Eric des Courtis <eric.des.courtis at benbria.com>
+ *
+ *
+ * http_req.h -- HTTP client implementation
+ *
+ */
+
+#ifndef __HTTP_REQ_H__
+#define __HTTP_REQ_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <signal.h>
+#include <errno.h>
+
+#define ERROR -1
+#define SUCCESS 0
+#define EMPTY_STRING(s) s[0] = '\0'
+
+#define DEFAULT_HTTP_VERSION "1.1"
+#define DEFAULT_HTTP_PORT 80
+
+#define HTTP_GET_METHOD "GET"
+#define HTTP_HEAD_METHOD "HEAD"
+#define HTTP_POST_METHOD "POST"
+#define HTTP_DELETE_METHOD "DELETE"
+#define HTTP_PUT_METHOD "PUT"
+
+#define MAX_PORT_LEN 6
+
+#define RECV_BUFF_SIZE 65536
+
+#define HTTP_TRUE 1
+#define HTTP_FALSE 0
+
+#define INIT_STATE_MACHINE(m) \
+do {\
+    (m)->pos = 0;\
+    (m)->buf = NULL;\
+    (m)->token = SYNTAX_ERROR;\
+    (m)->stop = HTTP_FALSE;\
+    (m)->state = state_start;\
+} while(0)
+
+#define STATUS_CODE_LEN 4
+
+typedef enum tokens {
+    VERSION,
+    STATUS_CODE,
+    PHRASE,
+    HEADER,
+    NEWLINE,
+    SYNTAX_ERROR
+} token_t;
+
+typedef enum accept_states {
+    ASWR,
+    ASNR,
+    NOAS
+} accept_state_t;
+
+typedef struct state_machines {
+    accept_state_t (*state)(char, struct state_machines *);
+    int pos;
+    char *buf;
+    ssize_t buf_len;
+    int stop;
+    token_t token;
+} state_machine_t;
+
+typedef enum http_methods {
+    GET,
+    HEAD,
+    POST,
+    DELETE,
+    PUT
+} http_method_t;
+
+typedef struct http_headers {
+    char *field_name;
+    char *value;
+} http_header_t;
+
+typedef struct http_requests {
+    http_method_t method;
+    char *version;
+    char *url;
+    http_header_t *headers;
+    ssize_t header_len;
+    char *body;
+    ssize_t body_len;
+} http_request_t;
+
+typedef struct http_responses {
+    char *version;
+    int status_code;
+    char *phrase;
+    http_header_t *headers;
+    ssize_t header_len;
+    char *body;
+    int body_len;
+} http_response_t;
+
+token_t get_next_token(state_machine_t *sm);
+int http_parse_response(char *buf, ssize_t buf_len, http_response_t *response);
+int http_req(http_request_t *req, http_response_t *res);
+void free_http_response(http_response_t *response);
+
+#endif

Added: freeswitch/trunk/src/mod/applications/mod_http/json.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/json.h	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,31 @@
+/*
+ * $Id: json.h,v 1.6 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _json_h_
+#define _json_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "bits.h"
+#include "debug.h"
+#include "linkhash.h"
+#include "arraylist.h"
+#include "json_util.h"
+#include "json_object.h"
+#include "json_tokener.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

Added: freeswitch/trunk/src/mod/applications/mod_http/json_object.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/json_object.c	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,510 @@
+/*
+ * $Id: json_object.c,v 1.17 2006/07/25 03:24:50 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "debug.h"
+#include "printbuf.h"
+#include "linkhash.h"
+#include "arraylist.h"
+#include "json_object.h"
+#include "json_object_private.h"
+#include "json_tokener.h"
+
+#if !HAVE_STRNDUP
+
+  char* strndup(const char* str, size_t n);
+
+#endif /* !HAVE_STRNDUP */
+
+/* #define REFCOUNT_DEBUG 1 */
+
+char *json_number_chars = "0123456789.+-e";
+char *json_hex_chars = "0123456789abcdef";
+
+#ifdef REFCOUNT_DEBUG
+static char* json_type_name[] = {
+  "null",
+  "boolean",
+  "double",
+  "int",
+  "object",
+  "array",
+  "string",
+};
+#endif /* REFCOUNT_DEBUG */
+
+static void json_object_generic_delete(struct json_object* this);
+static struct json_object* json_object_new(enum json_type o_type);
+
+
+/* ref count debugging */
+
+#ifdef REFCOUNT_DEBUG
+
+static struct lh_table *json_object_table;
+
+static void json_object_init() __attribute__ ((constructor));
+static void json_object_init() {
+  mc_debug("json_object_init: creating object table\n");
+  json_object_table = lh_kptr_table_new(128, "json_object_table", NULL);
+}
+
+static void json_object_fini() __attribute__ ((destructor));
+static void json_object_fini() {
+  struct lh_entry *ent;
+  if(mc_get_debug() && json_object_table->count) {
+    mc_debug("json_object_fini: %d referenced objects at exit\n",
+	     json_object_table->count);
+    lh_foreach(json_object_table, ent) {
+      struct json_object* obj = (struct json_object*)ent->v;
+      mc_debug("\t%s:%p\n", json_type_name[obj->o_type], obj);
+    }
+  }
+  mc_debug("json_object_fini: freeing object table\n");
+  lh_table_free(json_object_table);
+}
+#endif /* REFCOUNT_DEBUG */
+
+
+/* string escaping */
+
+static int json_escape_str(struct printbuf *pb, char *str)
+{
+  int pos = 0, start_offset = 0;
+  unsigned char c;
+  do {
+    c = str[pos];
+    switch(c) {
+    case '\0':
+      break;
+    case '\b':
+    case '\n':
+    case '\r':
+    case '\t':
+    case '"':
+    case '\\':
+    case '/':
+      if(pos - start_offset > 0)
+	printbuf_memappend(pb, str + start_offset, pos - start_offset);
+      if(c == '\b') printbuf_memappend(pb, "\\b", 2);
+      else if(c == '\n') printbuf_memappend(pb, "\\n", 2);
+      else if(c == '\r') printbuf_memappend(pb, "\\r", 2);
+      else if(c == '\t') printbuf_memappend(pb, "\\t", 2);
+      else if(c == '"') printbuf_memappend(pb, "\\\"", 2);
+      else if(c == '\\') printbuf_memappend(pb, "\\\\", 2);
+      else if(c == '/') printbuf_memappend(pb, "\\/", 2);
+      start_offset = ++pos;
+      break;
+    default:
+      if(c < ' ') {
+	if(pos - start_offset > 0)
+	  printbuf_memappend(pb, str + start_offset, pos - start_offset);
+	sprintbuf(pb, "\\u00%c%c",
+		  json_hex_chars[c >> 4],
+		  json_hex_chars[c & 0xf]);
+	start_offset = ++pos;
+      } else pos++;
+    }
+  } while(c);
+  if(pos - start_offset > 0)
+    printbuf_memappend(pb, str + start_offset, pos - start_offset);
+  return 0;
+}
+
+
+/* reference counting */
+
+extern struct json_object* json_object_get(struct json_object *this)
+{
+  if(this) {
+    this->_ref_count++;
+  }
+  return this;
+}
+
+extern void json_object_put(struct json_object *this)
+{
+  if(this) {
+    this->_ref_count--;
+    if(!this->_ref_count) this->_delete(this);
+  }
+}
+
+
+/* generic object construction and destruction parts */
+
+static void json_object_generic_delete(struct json_object* this)
+{
+#ifdef REFCOUNT_DEBUG
+  mc_debug("json_object_delete_%s: %p\n",
+	   json_type_name[this->o_type], this);
+  lh_table_delete(json_object_table, this);
+#endif /* REFCOUNT_DEBUG */
+  printbuf_free(this->_pb);
+  free(this);
+}
+
+static struct json_object* json_object_new(enum json_type o_type)
+{
+  struct json_object *this = calloc(sizeof(struct json_object), 1);
+  if(!this) return NULL;
+  this->o_type = o_type;
+  this->_ref_count = 1;
+  this->_delete = &json_object_generic_delete;
+#ifdef REFCOUNT_DEBUG
+  lh_table_insert(json_object_table, this, this);
+  mc_debug("json_object_new_%s: %p\n", json_type_name[this->o_type], this);
+#endif /* REFCOUNT_DEBUG */
+  return this;
+}
+
+
+/* type checking functions */
+
+int json_object_is_type(struct json_object *this, enum json_type type)
+{
+  return (this->o_type == type);
+}
+
+enum json_type json_object_get_type(struct json_object *this)
+{
+  return this->o_type;
+}
+
+
+/* json_object_to_json_string */
+
+char* json_object_to_json_string(struct json_object *this)
+{
+  if(!this) return "null";
+  if(!this->_pb) {
+    if(!(this->_pb = printbuf_new())) return NULL;
+  } else {
+    printbuf_reset(this->_pb);
+  }
+  if(this->_to_json_string(this, this->_pb) < 0) return NULL;
+  return this->_pb->buf;
+}
+
+
+/* json_object_object */
+
+static int json_object_object_to_json_string(struct json_object* this,
+					     struct printbuf *pb)
+{
+  int i=0;
+  struct json_object_iter iter;
+  sprintbuf(pb, "{");
+
+  /* CAW: scope operator to make ANSI correctness */
+  /* CAW: switched to json_object_object_foreachC which uses an iterator struct */
+	json_object_object_foreachC(this, iter) {
+			if(i) sprintbuf(pb, ",");
+			sprintbuf(pb, " \"");
+			json_escape_str(pb, iter.key);
+			sprintbuf(pb, "\": ");
+			if(iter.val == NULL) sprintbuf(pb, "null");
+			else iter.val->_to_json_string(iter.val, pb);
+			i++;
+	}
+
+  return sprintbuf(pb, " }");
+}
+
+static void json_object_lh_entry_free(struct lh_entry *ent)
+{
+  free(ent->k);
+  json_object_put((struct json_object*)ent->v);
+}
+
+static void json_object_object_delete(struct json_object* this)
+{
+  lh_table_free(this->o.c_object);
+  json_object_generic_delete(this);
+}
+
+struct json_object* json_object_new_object()
+{
+  struct json_object *this = json_object_new(json_type_object);
+  if(!this) return NULL;
+  this->_delete = &json_object_object_delete;
+  this->_to_json_string = &json_object_object_to_json_string;
+  this->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTIRES,
+					NULL, &json_object_lh_entry_free);
+  return this;
+}
+
+struct lh_table* json_object_get_object(struct json_object *this)
+{
+  if(!this) return NULL;
+  switch(this->o_type) {
+  case json_type_object:
+    return this->o.c_object;
+  default:
+    return NULL;
+  }
+}
+
+void json_object_object_add(struct json_object* this, char *key,
+			    struct json_object *val)
+{
+  lh_table_delete(this->o.c_object, key);
+  lh_table_insert(this->o.c_object, strdup(key), val);
+}
+
+struct json_object* json_object_object_get(struct json_object* this, char *key)
+{
+  return (struct json_object*) lh_table_lookup(this->o.c_object, key);
+}
+
+void json_object_object_del(struct json_object* this, char *key)
+{
+  lh_table_delete(this->o.c_object, key);
+}
+
+
+/* json_object_boolean */
+
+static int json_object_boolean_to_json_string(struct json_object* this,
+					      struct printbuf *pb)
+{
+  if(this->o.c_boolean) return sprintbuf(pb, "true");
+  else return sprintbuf(pb, "false");
+}
+
+struct json_object* json_object_new_boolean(boolean b)
+{
+  struct json_object *this = json_object_new(json_type_boolean);
+  if(!this) return NULL;
+  this->_to_json_string = &json_object_boolean_to_json_string;
+  this->o.c_boolean = b;
+  return this;
+}
+
+boolean json_object_get_boolean(struct json_object *this)
+{
+  if(!this) return FALSE;
+  switch(this->o_type) {
+  case json_type_boolean:
+    return this->o.c_boolean;
+  case json_type_int:
+    return (this->o.c_int != 0);
+  case json_type_double:
+    return (this->o.c_double != 0);
+  case json_type_string:
+    if(strlen(this->o.c_string)) return TRUE;
+  default:
+    return TRUE;
+  }
+}
+
+
+/* json_object_int */
+
+static int json_object_int_to_json_string(struct json_object* this,
+					  struct printbuf *pb)
+{
+  return sprintbuf(pb, "%d", this->o.c_int);
+}
+
+struct json_object* json_object_new_int(int i)
+{
+  struct json_object *this = json_object_new(json_type_int);
+  if(!this) return NULL;
+  this->_to_json_string = &json_object_int_to_json_string;
+  this->o.c_int = i;
+  return this;
+}
+
+int json_object_get_int(struct json_object *this)
+{
+  int cint;
+
+  if(!this) return 0;
+  switch(this->o_type) {
+  case json_type_int:
+    return this->o.c_int;
+  case json_type_double:
+    return (int)this->o.c_double;
+  case json_type_boolean:
+    return this->o.c_boolean;
+  case json_type_string:
+    if(sscanf(this->o.c_string, "%d", &cint) == 1) return cint;
+  default:
+    return 0;
+  }
+}
+
+
+/* json_object_double */
+
+static int json_object_double_to_json_string(struct json_object* this,
+					     struct printbuf *pb)
+{
+  return sprintbuf(pb, "%lf", this->o.c_double);
+}
+
+struct json_object* json_object_new_double(double d)
+{
+  struct json_object *this = json_object_new(json_type_double);
+  if(!this) return NULL;
+  this->_to_json_string = &json_object_double_to_json_string;
+  this->o.c_double = d;
+  return this;
+}
+
+double json_object_get_double(struct json_object *this)
+{
+  double cdouble;
+
+  if(!this) return 0.0;
+  switch(this->o_type) {
+  case json_type_double:
+    return this->o.c_double;
+  case json_type_int:
+    return this->o.c_int;
+  case json_type_boolean:
+    return this->o.c_boolean;
+  case json_type_string:
+    if(sscanf(this->o.c_string, "%lf", &cdouble) == 1) return cdouble;
+  default:
+    return 0.0;
+  }
+}
+
+
+/* json_object_string */
+
+static int json_object_string_to_json_string(struct json_object* this,
+					     struct printbuf *pb)
+{
+  sprintbuf(pb, "\"");
+  json_escape_str(pb, this->o.c_string);
+  sprintbuf(pb, "\"");
+  return 0;
+}
+
+static void json_object_string_delete(struct json_object* this)
+{
+  free(this->o.c_string);
+  json_object_generic_delete(this);
+}
+
+struct json_object* json_object_new_string(char *s)
+{
+  struct json_object *this = json_object_new(json_type_string);
+  if(!this) return NULL;
+  this->_delete = &json_object_string_delete;
+  this->_to_json_string = &json_object_string_to_json_string;
+  this->o.c_string = strdup(s);
+  return this;
+}
+
+struct json_object* json_object_new_string_len(char *s, int len)
+{
+  struct json_object *this = json_object_new(json_type_string);
+  if(!this) return NULL;
+  this->_delete = &json_object_string_delete;
+  this->_to_json_string = &json_object_string_to_json_string;
+  this->o.c_string = strndup(s, len);
+  return this;
+}
+
+char* json_object_get_string(struct json_object *this)
+{
+  if(!this) return NULL;
+  switch(this->o_type) {
+  case json_type_string:
+    return this->o.c_string;
+  default:
+    return json_object_to_json_string(this);
+  }
+}
+
+
+/* json_object_array */
+
+static int json_object_array_to_json_string(struct json_object* this,
+					    struct printbuf *pb)
+{
+  int i;
+  sprintbuf(pb, "[");
+  for(i=0; i < json_object_array_length(this); i++) {
+	  struct json_object *val;
+	  if(i) { sprintbuf(pb, ", "); }
+	  else { sprintbuf(pb, " "); }
+
+      val = json_object_array_get_idx(this, i);
+	  if(val == NULL) { sprintbuf(pb, "null"); }
+	  else { val->_to_json_string(val, pb); }
+  }
+  return sprintbuf(pb, " ]");
+}
+
+static void json_object_array_entry_free(void *data)
+{
+  json_object_put((struct json_object*)data);
+}
+
+static void json_object_array_delete(struct json_object* this)
+{
+  array_list_free(this->o.c_array);
+  json_object_generic_delete(this);
+}
+
+struct json_object* json_object_new_array()
+{
+  struct json_object *this = json_object_new(json_type_array);
+  if(!this) return NULL;
+  this->_delete = &json_object_array_delete;
+  this->_to_json_string = &json_object_array_to_json_string;
+  this->o.c_array = array_list_new(&json_object_array_entry_free);
+  return this;
+}
+
+struct array_list* json_object_get_array(struct json_object *this)
+{
+  if(!this) return NULL;
+  switch(this->o_type) {
+  case json_type_array:
+    return this->o.c_array;
+  default:
+    return NULL;
+  }
+}
+
+int json_object_array_length(struct json_object *this)
+{
+  return array_list_length(this->o.c_array);
+}
+
+int json_object_array_add(struct json_object *this,struct json_object *val)
+{
+  return array_list_add(this->o.c_array, val);
+}
+
+int json_object_array_put_idx(struct json_object *this, int idx,
+			      struct json_object *val)
+{
+  return array_list_put_idx(this->o.c_array, idx, val);
+}
+
+struct json_object* json_object_array_get_idx(struct json_object *this,
+					      int idx)
+{
+  return (struct json_object*)array_list_get_idx(this->o.c_array, idx);
+}
+

Added: freeswitch/trunk/src/mod/applications/mod_http/json_object.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/json_object.h	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,308 @@
+/*
+ * $Id: json_object.h,v 1.12 2006/01/30 23:07:57 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _json_object_h_
+#define _json_object_h_
+
+#define JSON_OBJECT_DEF_HASH_ENTIRES 16
+
+#undef FALSE
+#define FALSE ((boolean)0)
+
+#undef TRUE
+#define TRUE ((boolean)1)
+
+extern char *json_number_chars;
+extern char *json_hex_chars;
+
+/* forward structure definitions */
+
+typedef int boolean;
+struct printbuf;
+struct lh_table;
+struct array_list;
+struct json_object;
+struct json_object_iter;
+
+/* supported object types */
+
+enum json_type {
+  json_type_null,
+  json_type_boolean,
+  json_type_double,
+  json_type_int,
+  json_type_object,
+  json_type_array,
+  json_type_string
+};
+
+/* reference counting functions */
+
+/**
+ * Increment the reference count of json_object
+ * @param obj the json_object instance
+ */
+extern struct json_object* json_object_get(struct json_object *obj);
+
+/**
+ * Decrement the reference count of json_object and free if it reaches zero
+ * @param obj the json_object instance
+ */
+extern void json_object_put(struct json_object *obj);
+
+
+/**
+ * Check if the json_object is of a given type
+ * @param obj the json_object instance
+ * @param type one of:
+     json_type_boolean,
+     json_type_double,
+     json_type_int,
+     json_type_object,
+     json_type_array,
+     json_type_string,
+ */
+extern int json_object_is_type(struct json_object *obj, enum json_type type);
+
+/**
+ * Get the type of the json_object
+ * @param obj the json_object instance
+ * @returns type being one of:
+     json_type_boolean,
+     json_type_double,
+     json_type_int,
+     json_type_object,
+     json_type_array,
+     json_type_string,
+ */
+extern enum json_type json_object_get_type(struct json_object *obj);
+
+
+/** Stringify object to json format
+ * @param obj the json_object instance
+ * @returns a string in JSON format
+ */
+extern char* json_object_to_json_string(struct json_object *obj);
+
+
+/* object type methods */
+
+/** Create a new empty object
+ * @returns a json_object of type json_type_object
+ */
+extern struct json_object* json_object_new_object();
+
+/** Get the hashtable of a json_object of type json_type_object
+ * @param obj the json_object instance
+ * @returns a linkhash
+ */
+extern struct lh_table* json_object_get_object(struct json_object *obj);
+
+/** Add an object field to a json_object of type json_type_object
+ *
+ * The reference count will *not* be incremented. This is to make adding
+ * fields to objects in code more compact. If you want to retain a reference
+ * to an added object you must wrap the passed object with json_object_get
+ *
+ * @param obj the json_object instance
+ * @param key the object field name (a private copy will be duplicated)
+ * @param val a json_object or NULL member to associate with the given field
+ */
+extern void json_object_object_add(struct json_object* obj, char *key,
+				   struct json_object *val);
+
+/** Get the json_object associate with a given object field
+ * @param obj the json_object instance
+ * @param key the object field name
+ * @returns the json_object associated with the given field name
+ */
+extern struct json_object* json_object_object_get(struct json_object* obj,
+						  char *key);
+
+/** Delete the given json_object field
+ *
+ * The reference count will be decremented for the deleted object
+ *
+ * @param obj the json_object instance
+ * @param key the object field name
+ */
+extern void json_object_object_del(struct json_object* obj, char *key);
+
+/** Iterate through all keys and values of an object
+ * @param obj the json_object instance
+ * @param key the local name for the char* key variable defined in the body
+ * @param val the local name for the json_object* object variable defined in the body
+ */
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+
+# define json_object_object_foreach(obj,key,val) \
+ for(entry = json_object_get_object(obj)->head; ({ if(entry) { key = (char*)entry->k; val = (struct json_object*)entry->v; } ; entry; }); entry = entry->next )
+
+#else /* ANSI C or MSC */
+
+# define json_object_object_foreach(obj,key,val) \
+ for(entry = json_object_get_object(obj)->head; (entry ? (key = (char*)entry->k, val = (struct json_object*)entry->v, entry) : 0); entry = entry->next)
+
+#endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) */
+
+/** Iterate through all keys and values of an object (ANSI C Safe)
+ * @param obj the json_object instance
+ * @param iter the object iterator
+ */
+#define json_object_object_foreachC(obj,iter) \
+ for(iter.entry = json_object_get_object(obj)->head; (iter.entry ? (iter.key = (char*)iter.entry->k, iter.val = (struct json_object*)iter.entry->v, iter.entry) : 0); iter.entry = iter.entry->next)
+
+/* Array type methods */
+
+/** Create a new empty json_object of type json_type_array
+ * @returns a json_object of type json_type_array
+ */
+extern struct json_object* json_object_new_array();
+
+/** Get the arraylist of a json_object of type json_type_array
+ * @param obj the json_object instance
+ * @returns an arraylist
+ */
+extern struct array_list* json_object_get_array(struct json_object *obj);
+
+/** Get the length of a json_object of type json_type_array
+ * @param obj the json_object instance
+ * @returns an int
+ */
+extern int json_object_array_length(struct json_object *obj);
+
+/** Add an element to the end of a json_object of type json_type_array
+ *
+ * The reference count will *not* be incremented. This is to make adding
+ * fields to objects in code more compact. If you want to retain a reference
+ * to an added object you must wrap the passed object with json_object_get
+ *
+ * @param obj the json_object instance
+ * @param val the json_object to be added
+ */
+extern int json_object_array_add(struct json_object *obj,
+				 struct json_object *val);
+
+/** Insert or replace an element at a specified index in an array (a json_object of type json_type_array)
+ *
+ * The reference count will *not* be incremented. This is to make adding
+ * fields to objects in code more compact. If you want to retain a reference
+ * to an added object you must wrap the passed object with json_object_get
+ *
+ * The reference count of a replaced object will be decremented.
+ *
+ * The array size will be automatically be expanded to the size of the
+ * index if the index is larger than the current size.
+ *
+ * @param obj the json_object instance
+ * @param idx the index to insert the element at
+ * @param val the json_object to be added
+ */
+extern int json_object_array_put_idx(struct json_object *obj, int idx,
+				     struct json_object *val);
+
+/** Get the element at specificed index of the array (a json_object of type json_type_array)
+ * @param obj the json_object instance
+ * @param idx the index to get the element at
+ * @returns the json_object at the specified index (or NULL)
+ */
+extern struct json_object* json_object_array_get_idx(struct json_object *obj,
+						     int idx);
+
+/* boolean type methods */
+
+/** Create a new empty json_object of type json_type_boolean
+ * @param b a boolean TRUE or FALSE (0 or 1)
+ * @returns a json_object of type json_type_boolean
+ */
+extern struct json_object* json_object_new_boolean(boolean b);
+
+/** Get the boolean value of a json_object
+ *
+ * The type is coerced to a boolean if the passed object is not a boolean.
+ * integer and double objects will return FALSE if there value is zero
+ * or TRUE otherwise. If the passed object is a string it will return
+ * TRUE if it has a non zero length. If any other object type is passed
+ * TRUE will be returned if the object is not NULL.
+ *
+ * @param obj the json_object instance
+ * @returns a boolean
+ */
+extern boolean json_object_get_boolean(struct json_object *obj);
+
+
+/* int type methods */
+
+/** Create a new empty json_object of type json_type_int
+ * @param i the integer
+ * @returns a json_object of type json_type_int
+ */
+extern struct json_object* json_object_new_int(int i);
+
+/** Get the int value of a json_object
+ *
+ * The type is coerced to a int if the passed object is not a int.
+ * double objects will return their integer conversion. Strings will be
+ * parsed as an integer. If no conversion exists then 0 is returned.
+ *
+ * @param obj the json_object instance
+ * @returns an int
+ */
+extern int json_object_get_int(struct json_object *obj);
+
+
+/* double type methods */
+
+/** Create a new empty json_object of type json_type_double
+ * @param d the double
+ * @returns a json_object of type json_type_double
+ */
+extern struct json_object* json_object_new_double(double d);
+
+/** Get the double value of a json_object
+ *
+ * The type is coerced to a double if the passed object is not a double.
+ * integer objects will return their dboule conversion. Strings will be
+ * parsed as a double. If no conversion exists then 0.0 is returned.
+ *
+ * @param obj the json_object instance
+ * @returns an double
+ */
+extern double json_object_get_double(struct json_object *obj);
+
+
+/* string type methods */
+
+/** Create a new empty json_object of type json_type_string
+ *
+ * A copy of the string is made and the memory is managed by the json_object
+ *
+ * @param s the string
+ * @returns a json_object of type json_type_string
+ */
+extern struct json_object* json_object_new_string(char *s);
+
+extern struct json_object* json_object_new_string_len(char *s, int len);
+
+/** Get the string value of a json_object
+ *
+ * If the passed object is not of type json_type_string then the JSON
+ * representation of the object is returned.
+ *
+ * The returned string memory is managed by the json_object and will
+ * be freed when the reference count of the json_object drops to zero.
+ *
+ * @param obj the json_object instance
+ * @returns a string
+ */
+extern char* json_object_get_string(struct json_object *obj);
+
+#endif

Added: freeswitch/trunk/src/mod/applications/mod_http/json_object_private.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/json_object_private.h	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,44 @@
+/*
+ * $Id: json_object_private.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _json_object_private_h_
+#define _json_object_private_h_
+
+typedef void (json_object_delete_fn)(struct json_object *o);
+typedef int (json_object_to_json_string_fn)(struct json_object *o,
+					    struct printbuf *pb);
+
+struct json_object
+{
+  enum json_type o_type;
+  json_object_delete_fn *_delete;
+  json_object_to_json_string_fn *_to_json_string;
+  int _ref_count;
+  struct printbuf *_pb;
+  union data {
+    boolean c_boolean;
+    double c_double;
+    int c_int;
+    struct lh_table *c_object;
+    struct array_list *c_array;
+    char *c_string;
+  } o;
+};
+
+/* CAW: added for ANSI C iteration correctness */
+struct json_object_iter
+{
+	char *key;
+	struct json_object *val;
+	struct lh_entry *entry;
+};
+
+#endif

Added: freeswitch/trunk/src/mod/applications/mod_http/json_tokener.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/json_tokener.c	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,520 @@
+/*
+ * $Id: json_tokener.c,v 1.20 2006/07/25 03:24:50 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "bits.h"
+#include "debug.h"
+#include "printbuf.h"
+#include "arraylist.h"
+#include "json_object.h"
+#include "json_tokener.h"
+
+
+#if !HAVE_STRNCASECMP && defined(_MSC_VER)
+  /* MSC has the version as _strnicmp */
+# define strncasecmp _strnicmp
+#elif !HAVE_STRNCASECMP
+# error You do not have strncasecmp on your system.
+#endif /* HAVE_STRNCASECMP */
+
+
+static const char* json_null_str = "null";
+static const char* json_true_str = "true";
+static const char* json_false_str = "false";
+
+const char* json_tokener_errors[] = {
+  "success",
+  "continue",
+  "nesting to deep",
+  "unexpected end of data",
+  "unexpected character",
+  "null expected",
+  "boolean expected",
+  "number expected",
+  "array value separator ',' expected",
+  "quoted object property name expected",
+  "object property name separator ':' expected",
+  "object value separator ',' expected",
+  "invalid string sequence",
+  "expected comment",
+};
+
+
+struct json_tokener* json_tokener_new()
+{
+  struct json_tokener *tok = calloc(1, sizeof(struct json_tokener));
+  tok->pb = printbuf_new();
+  json_tokener_reset(tok);
+  return tok;
+}
+
+void json_tokener_free(struct json_tokener *tok)
+{
+  json_tokener_reset(tok);
+  if(tok) printbuf_free(tok->pb);
+  free(tok);
+}
+
+static void json_tokener_reset_level(struct json_tokener *tok, int depth)
+{
+  tok->stack[depth].state = json_tokener_state_eatws;
+  tok->stack[depth].saved_state = json_tokener_state_start;
+  json_object_put(tok->stack[depth].current);
+  tok->stack[depth].current = NULL;
+  free(tok->stack[depth].obj_field_name);
+  tok->stack[depth].obj_field_name = NULL;
+}
+
+void json_tokener_reset(struct json_tokener *tok)
+{
+  int i;
+  for(i = tok->depth; i >= 0; i--)
+    json_tokener_reset_level(tok, i);
+  tok->depth = 0;
+  tok->err = json_tokener_success;
+}
+
+struct json_object* json_tokener_parse(char *str)
+{
+  struct json_tokener* tok;
+  struct json_object* obj;
+
+  tok = json_tokener_new();
+  obj = json_tokener_parse_ex(tok, str, -1);
+  if(tok->err != json_tokener_success)
+    obj = error_ptr(-tok->err);
+  json_tokener_free(tok);
+  return obj;
+}
+
+
+#if !HAVE_STRNDUP
+/* CAW: compliant version of strndup() */
+char* strndup(const char* str, size_t n)
+{
+  if(str) {
+    size_t len = strlen(str);
+    size_t nn = min(len,n);
+    char* s = (char*)malloc(sizeof(char) * (nn + 1));
+
+    if(s) {
+      memcpy(s, str, nn);
+      s[nn] = '\0';
+    }
+
+    return s;
+  }
+
+  return NULL;
+}
+#endif
+
+
+#define state  tok->stack[tok->depth].state
+#define saved_state  tok->stack[tok->depth].saved_state
+#define current tok->stack[tok->depth].current
+#define obj_field_name tok->stack[tok->depth].obj_field_name
+
+struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
+					  char *str, int len)
+{
+  struct json_object *obj = NULL;
+  char c;
+
+  tok->char_offset = 0;
+  tok->err = json_tokener_success;
+
+  do {
+    if(tok->char_offset == len) {
+      if(tok->depth == 0 && state == json_tokener_state_eatws &&
+	 saved_state == json_tokener_state_finish)
+	tok->err = json_tokener_success;
+      else
+	tok->err = json_tokener_continue;
+      goto out;
+    }
+
+    c = *str;
+  redo_char:
+    switch(state) {
+
+    case json_tokener_state_eatws:
+      if(isspace(c)) {
+	/* okay */
+      } else if(c == '/') {
+	printbuf_reset(tok->pb);
+	printbuf_memappend(tok->pb, &c, 1);
+	state = json_tokener_state_comment_start;
+      } else {
+	state = saved_state;
+	goto redo_char;
+      }
+      break;
+
+    case json_tokener_state_start:
+      switch(c) {
+      case '{':
+	state = json_tokener_state_eatws;
+	saved_state = json_tokener_state_object_field_start;
+	current = json_object_new_object();
+	break;
+      case '[':
+	state = json_tokener_state_eatws;
+	saved_state = json_tokener_state_array;
+	current = json_object_new_array();
+	break;
+      case 'N':
+      case 'n':
+	state = json_tokener_state_null;
+	printbuf_reset(tok->pb);
+	tok->st_pos = 0;
+	goto redo_char;
+      case '"':
+      case '\'':
+	state = json_tokener_state_string;
+	printbuf_reset(tok->pb);
+	tok->quote_char = c;
+	break;
+      case 'T':
+      case 't':
+      case 'F':
+      case 'f':
+	state = json_tokener_state_boolean;
+	printbuf_reset(tok->pb);
+	tok->st_pos = 0;
+	goto redo_char;
+/*
+#if defined(__GNUC__)
+	  case '0' ... '9':
+#else
+*/
+	  case '0':
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9':
+/*
+#endif
+*/
+      case '-':
+	state = json_tokener_state_number;
+	printbuf_reset(tok->pb);
+	tok->is_double = 0;
+	goto redo_char;
+      default:
+	tok->err = json_tokener_error_parse_unexpected;
+	goto out;
+      }
+      break;
+
+    case json_tokener_state_finish:
+      if(tok->depth == 0) goto out;
+      obj = json_object_get(current);
+      json_tokener_reset_level(tok, tok->depth);
+      tok->depth--;
+      goto redo_char;
+
+    case json_tokener_state_null:
+      printbuf_memappend(tok->pb, &c, 1);
+      if(strncasecmp(json_null_str, tok->pb->buf,
+		     min(tok->st_pos+1, strlen(json_null_str))) == 0) {
+	if(tok->st_pos == strlen(json_null_str)) {
+	  current = NULL;
+	  saved_state = json_tokener_state_finish;
+	  state = json_tokener_state_eatws;
+	  goto redo_char;
+	}
+      } else {
+	tok->err = json_tokener_error_parse_null;
+	goto out;
+      }
+      tok->st_pos++;
+      break;
+
+    case json_tokener_state_comment_start:
+      if(c == '*') {
+	state = json_tokener_state_comment;
+      } else if(c == '/') {
+	state = json_tokener_state_comment_eol;
+      } else {
+	tok->err = json_tokener_error_parse_comment;
+	goto out;
+      }
+      printbuf_memappend(tok->pb, &c, 1);
+      break;
+
+    case json_tokener_state_comment:
+      if(c == '*') state = json_tokener_state_comment_end;
+      printbuf_memappend(tok->pb, &c, 1);
+      break;
+
+    case json_tokener_state_comment_eol:
+      if(c == '\n') {
+	mc_debug("json_tokener_comment: %s\n", tok->pb->buf);
+	state = json_tokener_state_eatws;
+      } else {
+	printbuf_memappend(tok->pb, &c, 1);
+      }
+      break;
+
+    case json_tokener_state_comment_end:
+      printbuf_memappend(tok->pb, &c, 1);
+      if(c == '/') {
+	mc_debug("json_tokener_comment: %s\n", tok->pb->buf);
+	state = json_tokener_state_eatws;
+      } else {
+	state = json_tokener_state_comment;
+      }
+      break;
+
+    case json_tokener_state_string:
+      if(c == tok->quote_char) {
+	current = json_object_new_string(tok->pb->buf);
+	saved_state = json_tokener_state_finish;
+	state = json_tokener_state_eatws;
+      } else if(c == '\\') {
+	saved_state = json_tokener_state_string;
+	state = json_tokener_state_string_escape;
+      } else {
+	printbuf_memappend(tok->pb, &c, 1);
+      }
+      break;
+
+    case json_tokener_state_string_escape:
+      switch(c) {
+      case '"':
+      case '\\':
+      case '/':
+	printbuf_memappend(tok->pb, &c, 1);
+	state = saved_state;
+	break;
+      case 'b':
+      case 'n':
+      case 'r':
+      case 't':
+	if(c == 'b') printbuf_memappend(tok->pb, "\b", 1);
+	else if(c == 'n') printbuf_memappend(tok->pb, "\n", 1);
+	else if(c == 'r') printbuf_memappend(tok->pb, "\r", 1);
+	else if(c == 't') printbuf_memappend(tok->pb, "\t", 1);
+	state = saved_state;
+	break;
+      case 'u':
+	tok->ucs_char = 0;
+	tok->st_pos = 0;
+	state = json_tokener_state_escape_unicode;
+	break;
+      default:
+	tok->err = json_tokener_error_parse_string;
+	goto out;
+      }
+      break;
+
+    case json_tokener_state_escape_unicode:
+      if(strchr(json_hex_chars, c)) {
+	tok->ucs_char += ((unsigned int)hexdigit(c) << ((3-tok->st_pos++)*4));
+	if(tok->st_pos == 4) {
+	  unsigned char utf_out[3];
+	  if (tok->ucs_char < 0x80) {
+	    utf_out[0] = tok->ucs_char;
+	    printbuf_memappend(tok->pb, (char*)utf_out, 1);
+	  } else if (tok->ucs_char < 0x800) {
+	    utf_out[0] = 0xc0 | (tok->ucs_char >> 6);
+	    utf_out[1] = 0x80 | (tok->ucs_char & 0x3f);
+	    printbuf_memappend(tok->pb, (char*)utf_out, 2);
+	  } else {
+	    utf_out[0] = 0xe0 | (tok->ucs_char >> 12);
+	    utf_out[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
+	    utf_out[2] = 0x80 | (tok->ucs_char & 0x3f);
+	    printbuf_memappend(tok->pb, (char*)utf_out, 3);
+	  }
+	  state = saved_state;
+	}
+      } else {
+	tok->err = json_tokener_error_parse_string;
+	goto out;
+      }
+      break;
+
+    case json_tokener_state_boolean:
+      printbuf_memappend(tok->pb, &c, 1);
+      if(strncasecmp(json_true_str, tok->pb->buf,
+		     min(tok->st_pos+1, strlen(json_true_str))) == 0) {
+	if(tok->st_pos == strlen(json_true_str)) {
+	  current = json_object_new_boolean(1);
+	  saved_state = json_tokener_state_finish;
+	  state = json_tokener_state_eatws;
+	  goto redo_char;
+	}
+      } else if(strncasecmp(json_false_str, tok->pb->buf,
+			    min(tok->st_pos+1, strlen(json_false_str))) == 0) {
+	if(tok->st_pos == strlen(json_false_str)) {
+	  current = json_object_new_boolean(0);
+	  saved_state = json_tokener_state_finish;
+	  state = json_tokener_state_eatws;
+	  goto redo_char;
+	}
+      } else {
+	tok->err = json_tokener_error_parse_boolean;
+	goto out;
+      }
+      tok->st_pos++;
+      break;
+
+    case json_tokener_state_number:
+      if(c && strchr(json_number_chars, c)) {
+	printbuf_memappend(tok->pb, &c, 1);	
+	if(c == '.' || c == 'e') tok->is_double = 1;
+      } else {
+	int numi;
+	double numd;
+	if(!tok->is_double && sscanf(tok->pb->buf, "%d", &numi) == 1) {
+	  current = json_object_new_int(numi);
+	} else if(tok->is_double && sscanf(tok->pb->buf, "%lf", &numd) == 1) {
+	  current = json_object_new_double(numd);
+	} else {
+	  tok->err = json_tokener_error_parse_number;
+	  goto out;
+	}
+	saved_state = json_tokener_state_finish;
+	state = json_tokener_state_eatws;
+	goto redo_char;
+      }
+      break;
+
+    case json_tokener_state_array:
+      if(c == ']') {
+	saved_state = json_tokener_state_finish;
+	state = json_tokener_state_eatws;
+      } else {
+	if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
+	  tok->err = json_tokener_error_depth;
+	  goto out;
+	}
+	state = json_tokener_state_array_add;
+	tok->depth++;
+	json_tokener_reset_level(tok, tok->depth);
+	goto redo_char;
+      }
+      break;
+
+    case json_tokener_state_array_add:
+      json_object_array_add(current, obj);
+      saved_state = json_tokener_state_array_sep;
+      state = json_tokener_state_eatws;
+      goto redo_char;
+
+    case json_tokener_state_array_sep:
+      if(c == ']') {
+	saved_state = json_tokener_state_finish;
+	state = json_tokener_state_eatws;
+      } else if(c == ',') {
+	saved_state = json_tokener_state_array;
+	state = json_tokener_state_eatws;
+      } else {
+	tok->err = json_tokener_error_parse_array;
+	goto out;
+      }
+      break;
+
+    case json_tokener_state_object_field_start:
+      if(c == '}') {
+	saved_state = json_tokener_state_finish;
+	state = json_tokener_state_eatws;
+      } else if (c == '"' || c == '\'') {
+	tok->quote_char = c;
+	printbuf_reset(tok->pb);
+	state = json_tokener_state_object_field;
+      } else {
+	tok->err = json_tokener_error_parse_object_key_name;
+	goto out;
+      }
+      break;
+
+    case json_tokener_state_object_field:
+      if(c == tok->quote_char) {
+	obj_field_name = strdup(tok->pb->buf);
+	saved_state = json_tokener_state_object_field_end;
+	state = json_tokener_state_eatws;
+      } else if(c == '\\') {
+	saved_state = json_tokener_state_object_field;
+	state = json_tokener_state_string_escape;
+      } else {
+	printbuf_memappend(tok->pb, &c, 1);
+      }
+      break;
+
+    case json_tokener_state_object_field_end:
+      if(c == ':') {
+	saved_state = json_tokener_state_object_value;
+	state = json_tokener_state_eatws;
+      } else {
+	tok->err = json_tokener_error_parse_object_key_sep;
+	goto out;
+      }
+      break;
+
+    case json_tokener_state_object_value:
+      if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
+	tok->err = json_tokener_error_depth;
+	goto out;
+      }
+      state = json_tokener_state_object_value_add;
+      tok->depth++;
+      json_tokener_reset_level(tok, tok->depth);
+      goto redo_char;
+
+    case json_tokener_state_object_value_add:
+      json_object_object_add(current, obj_field_name, obj);
+      free(obj_field_name);
+      obj_field_name = NULL;
+      saved_state = json_tokener_state_object_sep;
+      state = json_tokener_state_eatws;
+      goto redo_char;
+
+    case json_tokener_state_object_sep:
+      if(c == '}') {
+	saved_state = json_tokener_state_finish;
+	state = json_tokener_state_eatws;
+      } else if(c == ',') {
+	saved_state = json_tokener_state_object_field_start;
+	state = json_tokener_state_eatws;
+      } else {
+	tok->err = json_tokener_error_parse_object_value_sep;
+	goto out;
+      }
+      break;
+
+    }
+    str++;
+    tok->char_offset++;
+  } while(c);
+
+  if(state != json_tokener_state_finish &&
+     saved_state != json_tokener_state_finish)
+    tok->err = json_tokener_error_parse_eof;
+
+ out:
+  if(tok->err == json_tokener_success) return json_object_get(current);
+  mc_debug("json_tokener_parse_ex: error %s at offset %d\n",
+	   json_tokener_errors[tok->err], tok->char_offset);
+  return NULL;
+}

Added: freeswitch/trunk/src/mod/applications/mod_http/json_tokener.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/json_tokener.h	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,89 @@
+/*
+ * $Id: json_tokener.h,v 1.10 2006/07/25 03:24:50 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _json_tokener_h_
+#define _json_tokener_h_
+
+#include "json_object.h"
+
+enum json_tokener_error {
+  json_tokener_success,
+  json_tokener_continue,
+  json_tokener_error_depth,
+  json_tokener_error_parse_eof,
+  json_tokener_error_parse_unexpected,
+  json_tokener_error_parse_null,
+  json_tokener_error_parse_boolean,
+  json_tokener_error_parse_number,
+  json_tokener_error_parse_array,
+  json_tokener_error_parse_object_key_name,
+  json_tokener_error_parse_object_key_sep,
+  json_tokener_error_parse_object_value_sep,
+  json_tokener_error_parse_string,
+  json_tokener_error_parse_comment
+};
+
+enum json_tokener_state {
+  json_tokener_state_eatws,
+  json_tokener_state_start,
+  json_tokener_state_finish,
+  json_tokener_state_null,
+  json_tokener_state_comment_start,
+  json_tokener_state_comment,
+  json_tokener_state_comment_eol,
+  json_tokener_state_comment_end,
+  json_tokener_state_string,
+  json_tokener_state_string_escape,
+  json_tokener_state_escape_unicode,
+  json_tokener_state_boolean,
+  json_tokener_state_number,
+  json_tokener_state_array,
+  json_tokener_state_array_add,
+  json_tokener_state_array_sep,
+  json_tokener_state_object_field_start,
+  json_tokener_state_object_field,
+  json_tokener_state_object_field_end,
+  json_tokener_state_object_value,
+  json_tokener_state_object_value_add,
+  json_tokener_state_object_sep
+};
+
+struct json_tokener_srec
+{
+  enum json_tokener_state state, saved_state;
+  struct json_object *obj;
+  struct json_object *current;
+  char *obj_field_name;
+};
+
+#define JSON_TOKENER_MAX_DEPTH 32
+
+struct json_tokener
+{
+  char *str;
+  struct printbuf *pb;
+  int depth, is_double, st_pos, char_offset;
+  enum json_tokener_error err;
+  unsigned int ucs_char;
+  char quote_char;
+  struct json_tokener_srec stack[JSON_TOKENER_MAX_DEPTH];
+};
+
+extern const char* json_tokener_errors[];
+
+extern struct json_tokener* json_tokener_new();
+extern void json_tokener_free(struct json_tokener *tok);
+extern void json_tokener_reset(struct json_tokener *tok);
+extern struct json_object* json_tokener_parse(char *str);
+extern struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
+						 char *str, int len);
+
+#endif

Added: freeswitch/trunk/src/mod/applications/mod_http/json_util.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/json_util.c	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,121 @@
+/*
+ * $Id: json_util.c,v 1.4 2006/01/30 23:07:57 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif /* HAVE_SYS_TYPES_H */
+
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif /* HAVE_SYS_STAT_H */
+
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif /* HAVE_FCNTL_H */
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#ifdef WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include <io.h>
+#endif /* defined(WIN32) */
+
+#if !HAVE_OPEN && defined(WIN32)
+# define open _open
+#endif
+
+
+#include "bits.h"
+#include "debug.h"
+#include "printbuf.h"
+#include "json_object.h"
+#include "json_tokener.h"
+#include "json_util.h"
+
+struct json_object* json_object_from_file(char *filename)
+{
+  struct printbuf *pb;
+  struct json_object *obj;
+  char buf[JSON_FILE_BUF_SIZE];
+  int fd, ret;
+
+  if((fd = open(filename, O_RDONLY)) < 0) {
+    mc_error("json_object_from_file: error reading file %s: %s\n",
+	     filename, strerror(errno));
+    return error_ptr(-1);
+  }
+  if(!(pb = printbuf_new())) {
+    mc_error("json_object_from_file: printbuf_new failed\n");
+    return error_ptr(-1);
+  }
+  while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
+    printbuf_memappend(pb, buf, ret);
+  }
+  close(fd);
+  if(ret < 0) {
+    mc_abort("json_object_from_file: error reading file %s: %s\n",
+	     filename, strerror(errno));
+    printbuf_free(pb);
+    return error_ptr(-1);
+  }
+  obj = json_tokener_parse(pb->buf);
+  printbuf_free(pb);
+  return obj;
+}
+
+int json_object_to_file(char *filename, struct json_object *obj)
+{
+  char *json_str;
+  int fd, ret;
+  unsigned int wpos, wsize;
+
+  if(!obj) {
+    mc_error("json_object_to_file: object is null\n");
+    return -1;
+  }
+
+  if((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
+    mc_error("json_object_to_file: error opening file %s: %s\n",
+	     filename, strerror(errno));
+    return -1;
+  }
+
+  if(!(json_str = json_object_to_json_string(obj))) { return -1; }
+
+
+  wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */
+  wpos = 0;
+  while(wpos < wsize) {
+    if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) {
+      close(fd);
+      mc_error("json_object_to_file: error writing file %s: %s\n",
+	     filename, strerror(errno));
+      return -1;
+    }
+
+	/* because of the above check for ret < 0, we can safely cast and add */
+    wpos += (unsigned int)ret;
+  }
+
+  close(fd);
+  return 0;
+}

Added: freeswitch/trunk/src/mod/applications/mod_http/json_util.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/json_util.h	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,23 @@
+/*
+ * $Id: json_util.h,v 1.4 2006/01/30 23:07:57 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _json_util_h_
+#define _json_util_h_
+
+#include "json_object.h"
+
+#define JSON_FILE_BUF_SIZE 4096
+
+/* utlitiy functions */
+extern struct json_object* json_object_from_file(char *filename);
+extern int json_object_to_file(char *filename, struct json_object *obj);
+
+#endif

Added: freeswitch/trunk/src/mod/applications/mod_http/linkhash.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/linkhash.c	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,217 @@
+/*
+ * $Id: linkhash.c,v 1.4 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <limits.h>
+
+#include "linkhash.h"
+
+void lh_abort(const char *msg, ...)
+{
+	va_list ap;
+	va_start(ap, msg);
+	vprintf(msg, ap);
+	exit(1);
+}
+
+unsigned long lh_ptr_hash(void *k)
+{
+	/* CAW: refactored to be 64bit nice */
+	return (unsigned long)((((ptrdiff_t)k * LH_PRIME) >> 4) & ULONG_MAX);
+}
+
+int lh_ptr_equal(void *k1, void *k2)
+{
+	return (k1 == k2);
+}
+
+unsigned long lh_char_hash(void *k)
+{
+	unsigned int h = 0;
+	const char* data = k;
+ 
+	while( *data!=0 ) h = h*129 + (unsigned int)(*data++) + LH_PRIME;
+
+	return h;
+}
+
+int lh_char_equal(void *k1, void *k2)
+{
+	return (strcmp((char*)k1, (char*)k2) == 0);
+}
+
+struct lh_table* lh_table_new(int size, char *name,
+			      lh_entry_free_fn *free_fn,
+			      lh_hash_fn *hash_fn,
+			      lh_equal_fn *equal_fn)
+{
+	int i;
+	struct lh_table *t;
+
+	t = calloc(1, sizeof(struct lh_table));
+	if(!t) lh_abort("lh_table_new: calloc failed\n");
+	t->count = 0;
+	t->size = size;
+	t->name = name;
+	t->table = calloc(size, sizeof(struct lh_entry));
+	if(!t->table) lh_abort("lh_table_new: calloc failed\n");
+	t->free_fn = free_fn;
+	t->hash_fn = hash_fn;
+	t->equal_fn = equal_fn;
+	for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY;
+	return t;
+}
+
+struct lh_table* lh_kchar_table_new(int size, char *name,
+				    lh_entry_free_fn *free_fn)
+{
+	return lh_table_new(size, name, free_fn, lh_char_hash, lh_char_equal);
+}
+
+struct lh_table* lh_kptr_table_new(int size, char *name,
+				   lh_entry_free_fn *free_fn)
+{
+	return lh_table_new(size, name, free_fn, lh_ptr_hash, lh_ptr_equal);
+}
+
+void lh_table_resize(struct lh_table *t, int new_size)
+{
+	struct lh_table *new_t;
+	struct lh_entry *ent;
+
+	new_t = lh_table_new(new_size, t->name, NULL, t->hash_fn, t->equal_fn);
+	ent = t->head;
+	while(ent) {
+		lh_table_insert(new_t, ent->k, ent->v);
+		ent = ent->next;
+	}
+	free(t->table);
+	t->table = new_t->table;
+	t->size = new_size;
+	t->head = new_t->head;
+	t->tail = new_t->tail;
+	t->resizes++;
+	free(new_t);
+}
+
+void lh_table_free(struct lh_table *t)
+{
+	struct lh_entry *c;
+	for(c = t->head; c != NULL; c = c->next) {
+		if(t->free_fn) {
+			t->free_fn(c);
+		}
+	}
+	free(t->table);
+	free(t);
+}
+
+
+int lh_table_insert(struct lh_table *t, void *k, void *v)
+{
+	unsigned long h, n;
+
+	t->inserts++;
+	if(t->count > t->size * 0.66) lh_table_resize(t, t->size * 2);
+
+	h = t->hash_fn(k);
+	n = h % t->size;
+
+	while( 1 ) {
+		if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) break;
+		t->collisions++;
+		if(++n == t->size) n = 0;
+	}
+
+	t->table[n].k = k;
+	t->table[n].v = v;
+	t->count++;
+
+	if(t->head == NULL) {
+		t->head = t->tail = &t->table[n];
+		t->table[n].next = t->table[n].prev = NULL;
+	} else {
+		t->tail->next = &t->table[n];
+		t->table[n].prev = t->tail;
+		t->table[n].next = NULL;
+		t->tail = &t->table[n];
+	}
+
+	return 0;
+}
+
+
+struct lh_entry* lh_table_lookup_entry(struct lh_table *t, void *k)
+{
+	unsigned long h = t->hash_fn(k);
+	unsigned long n = h % t->size;
+
+	t->lookups++;
+	while( 1 ) {
+		if(t->table[n].k == LH_EMPTY) return NULL;
+		if(t->table[n].k != LH_FREED &&
+		   t->equal_fn(t->table[n].k, k)) return &t->table[n];
+		if(++n == t->size) n = 0;
+	}
+	return NULL;
+}
+
+
+void* lh_table_lookup(struct lh_table *t, void *k)
+{
+	struct lh_entry *e = lh_table_lookup_entry(t, k);
+	if(e) return e->v;
+	return NULL;
+}
+
+
+int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e)
+{
+	ptrdiff_t n = (ptrdiff_t)(e - t->table); /* CAW: fixed to be 64bit nice, still need the crazy negative case... */
+
+	/* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */
+	if(n < 0) { return -2; }
+
+	if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) return -1;
+	t->count--;
+	if(t->free_fn) t->free_fn(e);
+	t->table[n].v = NULL;
+	t->table[n].k = LH_FREED;
+	if(t->tail == &t->table[n] && t->head == &t->table[n]) {
+		t->head = t->tail = NULL;
+	} else if (t->head == &t->table[n]) {
+		t->head->next->prev = NULL;
+		t->head = t->head->next;
+	} else if (t->tail == &t->table[n]) {
+		t->tail->prev->next = NULL;
+		t->tail = t->tail->prev;
+	} else {
+		t->table[n].prev->next = t->table[n].next;
+		t->table[n].next->prev = t->table[n].prev;
+	}
+	t->table[n].next = t->table[n].prev = NULL;
+	return 0;
+}
+
+
+int lh_table_delete(struct lh_table *t, void *k)
+{
+	struct lh_entry *e = lh_table_lookup_entry(t, k);
+	if(!e) return -1;
+	return lh_table_delete_entry(t, e);
+}
+

Added: freeswitch/trunk/src/mod/applications/mod_http/linkhash.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/linkhash.h	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,261 @@
+/*
+ * $Id: linkhash.h,v 1.6 2006/01/30 23:07:57 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+ 
+#ifndef _linkhash_h_
+#define _linkhash_h_
+
+/**
+ * golden prime used in hash functions
+ */
+#define LH_PRIME 0x9e370001UL
+
+/**
+ * sentinel pointer value for empty slots
+ */
+#define LH_EMPTY (void*)-1
+
+/**
+ * sentinel pointer value for freed slots
+ */
+#define LH_FREED (void*)-2
+
+struct lh_entry;
+
+/**
+ * callback function prototypes
+ */
+typedef void (lh_entry_free_fn) (struct lh_entry *e);
+/**
+ * callback function prototypes
+ */
+typedef unsigned long (lh_hash_fn) (void *k);
+/**
+ * callback function prototypes
+ */
+typedef int (lh_equal_fn) (void *k1, void *k2);
+
+/**
+ * An entry in the hash table
+ */
+struct lh_entry {
+	/**
+	 * The key.
+	 */
+	void *k;
+	/**
+	 * The value.
+	 */
+	void *v;
+	/**
+	 * The next entry
+	 */
+	struct lh_entry *next;
+	/**
+	 * The previous entry.
+	 */
+	struct lh_entry *prev;
+};
+
+
+/**
+ * The hash table structure.
+ */
+struct lh_table {
+	/**
+	 * Size of our hash.
+	 */
+	int size;
+	/**
+	 * Numbers of entries.
+	 */
+	int count;
+
+	/**
+	 * Number of collisions.
+	 */
+	int collisions;
+
+	/**
+	 * Number of resizes.
+	 */
+	int resizes;
+
+	/**
+	 * Number of lookups.
+	 */
+	int lookups;
+
+	/**
+	 * Number of inserts.
+	 */
+	int inserts;
+
+	/**
+	 * Number of deletes.
+	 */
+	int deletes;
+
+	/**
+	 * Name of the hash table.
+	 */
+	char *name;
+
+	/**
+	 * The first entry.
+	 */
+	struct lh_entry *head;
+
+	/**
+	 * The last entry.
+	 */
+	struct lh_entry *tail;
+
+	struct lh_entry *table;
+
+	/**
+	 * A pointer onto the function responsible for freeing an entry.
+	 */
+	lh_entry_free_fn *free_fn;
+	lh_hash_fn *hash_fn;
+	lh_equal_fn *equal_fn;
+};
+
+
+/**
+ * Pre-defined hash and equality functions
+ */
+extern unsigned long lh_ptr_hash(void *k);
+extern int lh_ptr_equal(void *k1, void *k2);
+
+extern unsigned long lh_char_hash(void *k);
+extern int lh_char_equal(void *k1, void *k2);
+
+
+/**
+ * Convenience list iterator.
+ */
+#define lh_foreach(table, entry) \
+for(entry = table->head; entry; entry = entry->next)
+
+/**
+ * lh_foreach_safe allows calling of deletion routine while iterating.
+ */
+#define lh_foreach_safe(table, entry, tmp) \
+for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp)
+
+
+
+/**
+ * Create a new linkhash table.
+ * @param size initial table size. The table is automatically resized
+ * although this incurs a performance penalty.
+ * @param name the table name.
+ * @param free_fn callback function used to free memory for entries
+ * when lh_table_free or lh_table_delete is called.
+ * If NULL is provided, then memory for keys and values
+ * must be freed by the caller.
+ * @param hash_fn  function used to hash keys. 2 standard ones are defined:
+ * lh_ptr_hash and lh_char_hash for hashing pointer values
+ * and C strings respectively.
+ * @param equal_fn comparison function to compare keys. 2 standard ones defined:
+ * lh_ptr_hash and lh_char_hash for comparing pointer values
+ * and C strings respectively.
+ * @return a pointer onto the linkhash table.
+ */
+extern struct lh_table* lh_table_new(int size, char *name,
+				     lh_entry_free_fn *free_fn,
+				     lh_hash_fn *hash_fn,
+				     lh_equal_fn *equal_fn);
+
+/**
+ * Convenience function to create a new linkhash
+ * table with char keys.
+ * @param size initial table size.
+ * @param name table name.
+ * @param free_fn callback function used to free memory for entries.
+ * @return a pointer onto the linkhash table.
+ */
+extern struct lh_table* lh_kchar_table_new(int size, char *name,
+					   lh_entry_free_fn *free_fn);
+
+
+/**
+ * Convenience function to create a new linkhash
+ * table with ptr keys.
+ * @param size initial table size.
+ * @param name table name.
+ * @param free_fn callback function used to free memory for entries.
+ * @return a pointer onto the linkhash table.
+ */
+extern struct lh_table* lh_kptr_table_new(int size, char *name,
+					  lh_entry_free_fn *free_fn);
+
+
+/**
+ * Free a linkhash table.
+ * If a callback free function is provided then it is called for all
+ * entries in the table.
+ * @param t table to free.
+ */
+extern void lh_table_free(struct lh_table *t);
+
+
+/**
+ * Insert a record into the table.
+ * @param t the table to insert into.
+ * @param k a pointer to the key to insert.
+ * @param v a pointer to the value to insert.
+ */
+extern int lh_table_insert(struct lh_table *t, void *k, void *v);
+
+
+/**
+ * Lookup a record into the table.
+ * @param t the table to lookup
+ * @param k a pointer to the key to lookup
+ * @return a pointer to the record structure of the value or NULL if it does not exist.
+ */
+extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, void *k);
+
+/**
+ * Lookup a record into the table
+ * @param t the table to lookup
+ * @param k a pointer to the key to lookup
+ * @return a pointer to the found value or NULL if it does not exist.
+ */
+extern void* lh_table_lookup(struct lh_table *t, void *k);
+
+
+/**
+ * Delete a record from the table.
+ * If a callback free function is provided then it is called for the
+ * for the item being deleted.
+ * @param t the table to delete from.
+ * @param e a pointer to the entry to delete.
+ * @return 0 if the item was deleted.
+ * @return -1 if it was not found.
+ */
+extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e);
+
+
+/**
+ * Delete a record from the table.
+ * If a callback free function is provided then it is called for the
+ * for the item being deleted.
+ * @param t the table to delete from.
+ * @param k a pointer to the key to delete.
+ * @return 0 if the item was deleted.
+ * @return -1 if it was not found.
+ */
+extern int lh_table_delete(struct lh_table *t, void *k);
+
+
+#endif

Added: freeswitch/trunk/src/mod/applications/mod_http/mod_http.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/mod_http.c	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,356 @@
+/* 
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2008, Eric des Courtis <eric.des.courtis at benbria.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Eric des Courtis <eric.des.courtis at benbria.com>
+ * Copyright (C) Benbria. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Eric des Courtis <eric.des.courtis at benbria.com>
+ *
+ *
+ * mod_http.c -- HTTP client implementation for FreeSWITCH
+ * 
+ * The purpose is to provide laguages like LUA with a _fast_ HTTP
+ * client implementation.
+ *
+ * Support for SSL will be provided in future versions.
+ * Initial release does not include win32 support.
+ *
+ */
+
+#include <switch.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/queue.h>
+#include "json.h"
+
+#include "http_req.h"
+#include "url_encoding.h"
+
+#define HTTP_SYNTAX "<http_method> <url> <urlejson_headers> [urlejson_body]"
+#define HTTP_PARAMS 4
+#define HTTP_BUFFER_SIZE (256 * 1024)
+
+/* SWITCH_STANDARD_API(http_api_main); */
+
+#define MAX_MEMLOCS 512
+#define GARBAGE_TYPES_INIT() \
+typedef struct memloc{\
+    void *p;\
+    LIST_ENTRY(memloc) memlocs;\
+} memloc_t
+
+#define GARBAGE_CLEANUP() \
+do{\
+    for(memloc_p = head.lh_first; memloc_p != NULL; \
+        memloc_p = memloc_p->memlocs.le_next){\
+        free(memloc_p->p);\
+    }\
+}while(0)
+
+#define GARBAGE_ADD(a) \
+do {\
+    if(memloc_i >= MAX_MEMLOCS){\
+	switch_safe_free(ccmd);\
+	GARBAGE_CLEANUP();\
+	stream->write_function(stream, "-ERR\n");\
+	return SWITCH_STATUS_SUCCESS;\
+    }\
+    memloc_a[memloc_i].p = (void *)a;\
+    LIST_INSERT_HEAD(&head, memloc_a + memloc_i, memlocs);\
+    memloc_i++;\
+}while(0)
+
+#define GARBAGE_INIT() \
+    LIST_HEAD(listhead, memloc) head;\
+    memloc_t memloc_a[MAX_MEMLOCS];\
+    memloc_t *memloc_p;\
+    size_t memloc_i;\
+    LIST_INIT(&head);\
+    memloc_i = 0
+
+GARBAGE_TYPES_INIT();
+
+SWITCH_STANDARD_API(http_api_main)
+{
+    char *ccmd;
+    int argc;
+    char *argv[HTTP_PARAMS];
+    char *buf;
+    char *method;
+    char *url;
+    char *headers_str;
+    char *value;
+    char *body;
+    char *body_dec;
+    char *t;
+    char *json_response;
+    struct json_object *json_http_headers;
+    char *key;
+    struct json_object *val;
+    struct lh_entry *entry;
+    int i;
+    int j;
+    int f;
+    size_t l;
+    size_t m;
+    size_t a = 0;
+    int ret;
+
+    http_header_t *headers;
+    http_request_t request;
+    http_response_t response;
+
+    GARBAGE_INIT();
+    
+    (void)memset(&response, 0, sizeof(response));
+
+    if(cmd == NULL){
+        stream->write_function(stream, "-USAGE: %s\n", HTTP_SYNTAX);
+        return SWITCH_STATUS_SUCCESS;
+    }
+
+    ccmd = strdup(cmd);
+    argc = switch_separate_string(ccmd, ' ', argv, HTTP_PARAMS);
+
+    if(argc != HTTP_PARAMS && argc != (HTTP_PARAMS - 1)){
+        switch_safe_free(ccmd);
+        stream->write_function(stream, "-ERR\n");
+        return SWITCH_STATUS_SUCCESS;
+    }
+    
+    method = argv[0];
+    url = argv[1];
+    headers_str = argv[2];
+    if(argc == HTTP_PARAMS){
+        body = argv[3];
+    }else{
+        body = (char *)malloc(1 * sizeof(char));
+	if(body == NULL){
+            switch_safe_free(ccmd);
+            stream->write_function(stream, "-ERR\n");
+            return SWITCH_STATUS_SUCCESS;
+	}
+	body[0] = '\0';
+        GARBAGE_ADD(body);
+    }
+
+    buf = (char *)malloc(HTTP_BUFFER_SIZE * sizeof(char));
+    if(buf == NULL){
+        switch_safe_free(ccmd);
+        stream->write_function(stream, "-ERR\n");
+        GARBAGE_CLEANUP();
+        return SWITCH_STATUS_SUCCESS;
+    }
+    
+    GARBAGE_ADD(buf);   
+ 
+    request.version = DEFAULT_HTTP_VERSION;
+    l = strlen(url);
+    request.url = (char *)malloc((l + 1) * sizeof(char));
+    if(request.url == NULL){
+        switch_safe_free(ccmd);
+        stream->write_function(stream, "-ERR\n");
+        GARBAGE_CLEANUP();
+        return SWITCH_STATUS_SUCCESS;
+    } 
+       
+    GARBAGE_ADD(request.url);
+    strcpy(request.url, url); 
+    json_http_headers = json_tokener_parse(headers_str);
+
+    i = 0;
+    json_object_object_foreach(json_http_headers, key, val){ 
+        i++; 
+    }
+    
+    request.header_len = i;
+    headers = (http_header_t *)malloc(i * sizeof(http_header_t));
+    GARBAGE_ADD(headers);
+
+    i = 0;
+    json_object_object_foreach(json_http_headers, key, val){
+        l = strlen(key);
+        request.headers[i].field_name = (char *)malloc((l + 1) * sizeof(char));
+        if(request.headers[i].field_name == NULL){
+            switch_safe_free(ccmd);
+            stream->write_function(stream, "-ERR\n");
+            GARBAGE_CLEANUP();
+            return SWITCH_STATUS_SUCCESS;
+        }
+        GARBAGE_ADD(request.headers[i].field_name);
+        strcpy(request.headers[i].field_name, key);
+        a += strlen(key);
+
+        value = json_object_to_json_string(val);
+        l = strlen(value);
+        request.headers[i].value = (char *)malloc((l + 1) * sizeof(char));
+        if(request.headers[i].value == NULL){
+            switch_safe_free(ccmd);
+            stream->write_function(stream, "-ERR\n");
+            GARBAGE_CLEANUP();
+            return SWITCH_STATUS_SUCCESS;
+        }
+        GARBAGE_ADD(request.headers[i].value);
+        strcpy(request.headers[i].value, value);
+        a += strlen(value);
+        i++;
+    }
+
+    if(argc == HTTP_PARAMS){
+        l = strlen(body);
+        body_dec = url_decode(body, l);
+        GARBAGE_ADD(body_dec);
+        l = strlen(body_dec);
+        request.body_len = l;
+        request.body = body_dec;
+    }else request.body_len = 0;
+
+    ret = http_req(&request, &response);
+    if(response.version != NULL) GARBAGE_ADD(response.version);
+    if(response.phrase  != NULL) GARBAGE_ADD(response.phrase);
+    if(response.headers != NULL) GARBAGE_ADD(response.headers);
+    if(response.body    != NULL) GARBAGE_ADD(response.body);
+    for(i = 0; i < response.header_len; i++){
+        GARBAGE_ADD(response.headers[i].field_name);
+        GARBAGE_ADD(response.headers[i].value);
+    }
+    
+    
+    if(ret == ERROR){
+        switch_safe_free(ccmd);
+        stream->write_function(stream, "-ERR\n");
+        GARBAGE_CLEANUP();
+        return SWITCH_STATUS_SUCCESS;
+    }
+
+    /* This is evil and should be changed in the future */
+    l = 128 + (256 * response.header_len) + (a * 2)
+        + strlen("version") + strlen(response.version)
+        + strlen("status_code") + 3
+        + strlen("phrase") + strlen(response.phrase) 
+        + strlen("body") + (response.body_len * 3) + 1
+	+ strlen("headers")
+        + 1;
+
+    /* to be safe */
+    l <<= 2;
+    
+    json_response = (char *)malloc(l * sizeof(char));
+    if(json_response == NULL){
+        switch_safe_free(ccmd);
+        stream->write_function(stream, "-ERR\n");
+        GARBAGE_CLEANUP();
+        return SWITCH_STATUS_SUCCESS;
+    }
+    GARBAGE_ADD(json_response);
+    
+    if(response.body_len != 0){
+        t = (char *)malloc((response.body_len + 1) * sizeof(char));
+        if(t == NULL){
+            switch_safe_free(ccmd);
+            stream->write_function(stream, "-ERR\n");
+            GARBAGE_CLEANUP();
+            return SWITCH_STATUS_SUCCESS;
+        }
+        GARBAGE_ADD(t);
+        (void)memcpy(t, response.body, response.body_len);
+        t[response.body_len] = '\0';
+        response.body = url_encode(t, response.body_len);
+        GARBAGE_ADD(response.body);
+    }
+    
+
+    m = snprintf(json_response, l,
+        "{"
+        "\"version\": \"%s\","
+        "\"status_code\": \"%3d\","
+        "\"phrase\": \"%s\","
+        "\"body\": \"%s\","
+        "\"headers\": [",
+        response.version,
+        response.status_code,
+        response.phrase,
+        ((response.body_len <= 0)? "":response.body)
+    );
+
+
+    for(f = HTTP_FALSE, j = 0; j < response.header_len; j++){
+        if(f != HTTP_FALSE){
+            m += snprintf(json_response + m, l - m,
+                ","
+            );
+        }else f = HTTP_TRUE;
+
+        m += snprintf(json_response + m, l - m, 
+            "{\"key\": \"%s\",\"value\": \"%s\"}",
+            response.headers[j].field_name,
+            response.headers[j].value
+        );
+    }
+
+
+    m += snprintf(json_response + m, l - m, "]}");
+    json_response[m] = '\0';
+
+
+    switch_log_printf(
+        SWITCH_CHANNEL_LOG,
+        SWITCH_LOG_NOTICE,
+        "RESERVED %d BYTES, USED %d BYTES, HTTP Response as JSON: %s\n",
+        l, 
+        m,
+        json_response
+    );
+
+
+    stream->write_function(stream, "%s\n", json_response);
+
+    switch_safe_free(ccmd);
+    GARBAGE_CLEANUP();
+    return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_http_load);
+SWITCH_MODULE_DEFINITION(mod_http, mod_http_load, NULL, NULL);
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_http_load)
+{
+    switch_api_interface_t *api_interface;
+
+    *module_interface =
+        switch_loadable_module_create_module_interface(pool, modname);
+
+    switch_log_printf(
+        SWITCH_CHANNEL_LOG,
+        SWITCH_LOG_NOTICE,
+        "HTTP request mod enabled\n"
+    );
+
+    SWITCH_ADD_API(
+        api_interface, 
+        "http", 
+        "Make HTTP requests",
+        http_api_main,
+        HTTP_SYNTAX
+    );
+
+    return SWITCH_STATUS_SUCCESS;
+}
+

Added: freeswitch/trunk/src/mod/applications/mod_http/printbuf.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/printbuf.c	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,144 @@
+/*
+ * $Id: printbuf.c,v 1.5 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_STDARG_H
+# include <stdarg.h>
+#else /* !HAVE_STDARG_H */
+# error Not enough var arg support!
+#endif /* HAVE_STDARG_H */
+
+#include "bits.h"
+#include "debug.h"
+#include "printbuf.h"
+
+struct printbuf* printbuf_new()
+{
+  struct printbuf *p;
+
+  if(!(p = calloc(1, sizeof(struct printbuf)))) return NULL;
+  p->size = 32;
+  p->bpos = 0;
+  if(!(p->buf = malloc(p->size))) {
+    free(p);
+    return NULL;
+  }
+  return p;
+}
+
+
+int printbuf_memappend(struct printbuf *p, char *buf, int size)
+{
+  char *t;
+  if(p->size - p->bpos <= size) {
+    int new_size = max(p->size * 2, p->bpos + size + 8);
+#ifdef PRINTBUF_DEBUG
+    mc_debug("printbuf_memappend: realloc "
+	     "bpos=%d wrsize=%d old_size=%d new_size=%d\n",
+	     p->bpos, size, p->size, new_size);
+#endif /* PRINTBUF_DEBUG */
+    if(!(t = realloc(p->buf, new_size))) return -1;
+    p->size = new_size;
+    p->buf = t;
+  }
+  memcpy(p->buf + p->bpos, buf, size);
+  p->bpos += size;
+  p->buf[p->bpos]= '\0';
+  return size;
+}
+
+#if !HAVE_VSNPRINTF && defined(WIN32)
+# define vsnprintf _vsnprintf
+#elif !HAVE_VSNPRINTF /* !HAVE_VSNPRINTF */
+# error Need vsnprintf!
+#endif /* !HAVE_VSNPRINTF && defined(WIN32) */
+
+#if !HAVE_VASPRINTF
+/* CAW: compliant version of vasprintf */
+static int vasprintf(char **buf, const char *fmt, va_list ap)
+{
+#ifndef WIN32
+	static char _T_emptybuffer = '\0';
+#endif /* !defined(WIN32) */
+	int chars;
+	char *b;
+
+	if(!buf) { return -1; }
+
+#ifdef WIN32
+	chars = _vscprintf(fmt, ap)+1;
+#else /* !defined(WIN32) */
+	/* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite
+	   our buffer like on some 64bit sun systems.... but hey, its time to move on */
+	chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1;
+	if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this problem */
+#endif /* defined(WIN32) */
+
+	b = (char*)malloc(sizeof(char)*chars);
+	if(!b) { return -1; }
+
+	if((chars = vsprintf(b, fmt, ap)) < 0)
+	{
+		free(b);
+	} else {
+		*buf = b;
+	}
+
+	return chars;
+}
+#endif /* !HAVE_VASPRINTF */
+
+int sprintbuf(struct printbuf *p, const char *msg, ...)
+{
+  va_list ap;
+  char *t;
+  int size;
+  char buf[128];
+
+  /* user stack buffer first */
+  va_start(ap, msg);
+  size = vsnprintf(buf, 128, msg, ap);
+  va_end(ap);
+  /* if string is greater than stack buffer, then use dynamic string
+     with vasprintf.  Note: some implementation of vsnprintf return -1
+     if output is truncated whereas some return the number of bytes that
+     would have been writen - this code handles both cases. */
+  if(size == -1 || size > 127) {
+    int ret;
+    va_start(ap, msg);
+    if((size = vasprintf(&t, msg, ap)) == -1) return -1;
+    va_end(ap);
+    ret = printbuf_memappend(p, t, size);
+    free(t);
+    return ret;
+  } else {
+    return printbuf_memappend(p, buf, size);
+  }
+}
+
+void printbuf_reset(struct printbuf *p)
+{
+  p->buf[0] = '\0';
+  p->bpos = 0;
+}
+
+void printbuf_free(struct printbuf *p)
+{
+  if(p) {
+    free(p->buf);
+    free(p);
+  }
+}

Added: freeswitch/trunk/src/mod/applications/mod_http/printbuf.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/printbuf.h	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,38 @@
+/*
+ * $Id: printbuf.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _printbuf_h_
+#define _printbuf_h_
+
+#undef PRINTBUF_DEBUG
+
+struct printbuf {
+  char *buf;
+  int bpos;
+  int size;
+};
+
+extern struct printbuf*
+printbuf_new();
+
+extern int
+printbuf_memappend(struct printbuf *p, char *buf, int size);
+
+extern int
+sprintbuf(struct printbuf *p, const char *msg, ...);
+
+extern void
+printbuf_reset(struct printbuf *p);
+
+extern void
+printbuf_free(struct printbuf *p);
+
+#endif

Added: freeswitch/trunk/src/mod/applications/mod_http/url_encoding.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/url_encoding.c	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,125 @@
+/* 
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2008, Eric des Courtis <eric.des.courtis at benbria.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Eric des Courtis <eric.des.courtis at benbria.com>
+ * Copyright (C) Benbria. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Eric des Courtis <eric.des.courtis at benbria.com>
+ *
+ *
+ * url_encoding.c -- url encoding/decoding
+ *
+ */
+#include "url_encoding.h"
+
+#ifdef DEBUG
+int main(int argc, char *argv[])
+{
+    char *buf1;
+    char *buf2;
+    
+
+    buf1 = url_encode("This is a test #$ ");
+    buf2 = url_decode(buf1);
+
+    printf("%s\n", buf2);
+    
+    free(buf1);
+    free(buf2);
+    return EXIT_FAILURE;
+}
+
+#endif
+
+char *url_encode(char *url, size_t l)
+{
+    int i;
+    int j;
+    char *buf;
+    unsigned char c;
+
+    buf = (char *)malloc((l * 3) + 1);
+    if(buf == NULL){
+        perror("Could not allocate memory url encoding");
+        return NULL;
+    }
+
+    for(i = 0, j = 0; i < l; i++){
+        c = (unsigned char)url[i];
+        if(c <= 31 || c >= 127 
+            || c == '$' || c == '&' || c == '+' || c == ',' || c == '/' 
+            || c == ':' || c == ';' || c == '=' || c == '?' || c == '@'
+            || c == ' ' || c == '"' || c == '<' || c == '>' || c == '#'
+            || c == '%' || c == '{' || c == '}' || c == '|' || c == '\\'
+            || c == '^' || c == '~' || c == '[' || c == ']' || c == '`'){
+            
+            (void)sprintf(buf + j, "%%%X%X", c >> 4, c & 0x0F);
+            j += 3;
+        }else{
+            buf[j] = url[i];
+            j++;
+        }
+    }
+    
+    buf[j] = '\0';
+
+    return buf;
+}
+
+char *url_decode(char *url, size_t l)
+{
+    int i;
+    int j;
+    char *buf;
+    char c;
+    char d0;
+    char d1;
+
+    buf = (char *)malloc((l + 1) * sizeof(char));
+    if(buf == NULL){
+        perror("Could not allocate memory for decoding");
+        return NULL;
+    }
+
+    for(i = 0, j = 0; i < l; j++){
+        c = url[i];
+        if(c == '%'){
+            d0 = url[i + 2];
+            d1 = url[i + 1];
+            d0 = toupper(d0);
+            d1 = toupper(d1);
+
+            if(d0 >= 'A' && d0 <= 'F') d0 = d0 - 'A' + 10;
+            else if(d0 >= '0' && d0 <= '9') d0 = d0 - '0';
+            if(d1 >= 'A' && d1 <= 'F') d1 = d1 - 'A' + 10;
+            else if(d1 >= '0' && d1 <= '9') d1 = d1 - '0';
+
+            buf[j] = (d1 << 4) + d0;
+            i += 3;
+        }else{
+            buf[j] = url[i];
+            i++;
+        }
+    }
+
+    buf[j] = '\0';
+
+    return buf;
+}
+
+

Added: freeswitch/trunk/src/mod/applications/mod_http/url_encoding.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_http/url_encoding.h	Wed Dec 10 16:43:26 2008
@@ -0,0 +1,42 @@
+/* 
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2008, Eric des Courtis <eric.des.courtis at benbria.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Eric des Courtis <eric.des.courtis at benbria.com>
+ * Copyright (C) Benbria. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Eric des Courtis <eric.des.courtis at benbria.com>
+ *
+ *
+ * url_encoding.h -- url encoding/decoding
+ *
+ */
+
+#ifndef __URL_ENCODING_H__
+#define __URL_ENCODING_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+char *url_encode(char *url, size_t l);
+char *url_decode(char *url, size_t l);
+
+#endif
+



More information about the Freeswitch-svn mailing list