[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