diff options
author | snowdrop | 2006-02-18 20:14:35 +0000 |
---|---|---|
committer | snowdrop | 2006-02-18 20:14:35 +0000 |
commit | d45b4bc26f330d2ce29e4a06ffdae74d82e8b43b (patch) | |
tree | d4b985c32b1246f5cde7c294b6654b27f71cc81b | |
parent | 29b034ec9c827c7311e69fcb5765ef4e43478c29 (diff) | |
download | csoap-d45b4bc26f330d2ce29e4a06ffdae74d82e8b43b.tar.gz csoap-d45b4bc26f330d2ce29e4a06ffdae74d82e8b43b.tar.bz2 |
added basic authentication and SOAP-Header capabilities for request objects
Thanks to Heiko Ronsdorf
-rw-r--r-- | config.h.in | 106 | ||||
-rw-r--r-- | configure.ac | 19 | ||||
-rw-r--r-- | examples/Makefile.am | 2 | ||||
-rw-r--r-- | examples/nanohttp/Makefile.am | 27 | ||||
-rw-r--r-- | libcsoap/soap-client.c | 4 | ||||
-rwxr-xr-x | libcsoap/soap-ctx.c | 9 | ||||
-rwxr-xr-x | libcsoap/soap-ctx.h | 8 | ||||
-rw-r--r-- | libcsoap/soap-env.h | 5 | ||||
-rw-r--r-- | libcsoap/soap-router.c | 34 | ||||
-rw-r--r-- | libcsoap/soap-router.h | 8 | ||||
-rw-r--r-- | libcsoap/soap-server.c | 361 | ||||
-rw-r--r-- | nanohttp/Makefile.am | 2 | ||||
-rw-r--r-- | nanohttp/nanohttp-client.c | 393 | ||||
-rw-r--r-- | nanohttp/nanohttp-client.h | 3 | ||||
-rw-r--r-- | nanohttp/nanohttp-common.c | 84 | ||||
-rw-r--r-- | nanohttp/nanohttp-common.h | 13 | ||||
-rwxr-xr-x | nanohttp/nanohttp-mime.c | 14 | ||||
-rwxr-xr-x | nanohttp/nanohttp-request.c | 15 | ||||
-rwxr-xr-x | nanohttp/nanohttp-response.c | 13 | ||||
-rw-r--r-- | nanohttp/nanohttp-server.c | 354 | ||||
-rw-r--r-- | nanohttp/nanohttp-server.h | 11 | ||||
-rw-r--r-- | nanohttp/nanohttp-socket.c | 217 | ||||
-rw-r--r-- | nanohttp/nanohttp-socket.h | 3 | ||||
-rw-r--r-- | nanohttp/nanohttp-ssl.c | 71 | ||||
-rwxr-xr-x | nanohttp/nanohttp-stream.c | 14 |
25 files changed, 873 insertions, 917 deletions
diff --git a/config.h.in b/config.h.in index 0356f7c..3117663 100644 --- a/config.h.in +++ b/config.h.in @@ -3,45 +3,133 @@ /* Define to 1 if you have the <arpa/inet.h> header file. */ #undef HAVE_ARPA_INET_H +/* Define to 1 if you have the <ctype.h> header file. */ +#undef HAVE_CTYPE_H + /* Define to 1 if you have the <dlfcn.h> header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ #undef HAVE_DOPRNT +/* Define to 1 if you have the <errno.h> header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if you have the <fcntl.h> header file. */ +#undef HAVE_FCNTL_H + /* Define to 1 if you have the `gethostbyname' function. */ #undef HAVE_GETHOSTBYNAME +/* Define to 1 if you have the `inet_ntoa' function. */ +#undef HAVE_INET_NTOA + /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H +/* Define to 1 if you have the <io.h> header file. */ +#undef HAVE_IO_H + +/* Define to 1 if you have the `localtime_r' function. */ +#undef HAVE_LOCALTIME_R + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC + +/* Define to 1 if you have the <malloc.h> header file. */ +#undef HAVE_MALLOC_H + +/* Define to 1 if you have the `memmove' function. */ +#undef HAVE_MEMMOVE + /* Define to 1 if you have the <memory.h> header file. */ #undef HAVE_MEMORY_H +/* Define to 1 if you have the `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if you have the `mkdir' function. */ +#undef HAVE_MKDIR + /* Define to 1 if you have the <netdb.h> header file. */ #undef HAVE_NETDB_H +/* Define to 1 if you have the <netinet/in.h> header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the <openssl/err.h> header file. */ +#undef HAVE_OPENSSL_ERR_H + +/* Define to 1 if you have the <openssl/rand.h> header file. */ +#undef HAVE_OPENSSL_RAND_H + +/* Define to 1 if you have the <pthread.h> header file. */ +#undef HAVE_PTHREAD_H + +/* Define to 1 if you have the `select' function. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the <signal.h> header file. */ +#undef HAVE_SIGNAL_H + /* Define to 1 if you have the `socket' function. */ #undef HAVE_SOCKET +/* Define to 1 if you have the <stdarg.h> header file. */ +#undef HAVE_STDARG_H + /* Define to 1 if you have the <stdint.h> header file. */ #undef HAVE_STDINT_H +/* Define to 1 if you have the <stdio.h> header file. */ +#undef HAVE_STDIO_H + /* Define to 1 if you have the <stdlib.h> header file. */ #undef HAVE_STDLIB_H +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the `strdup' function. */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the `strftime' function. */ +#undef HAVE_STRFTIME + /* Define to 1 if you have the <strings.h> header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the <string.h> header file. */ #undef HAVE_STRING_H +/* Define to 1 if you have the `strncasecmp' function. */ +#undef HAVE_STRNCASECMP + +/* Define to 1 if you have the `strpbrk' function. */ +#undef HAVE_STRPBRK + +/* Define to 1 if you have the `strspn' function. */ +#undef HAVE_STRSPN + +/* Define to 1 if you have the `strstr' function. */ +#undef HAVE_STRSTR + +/* Define to 1 if you have the `strtol' function. */ +#undef HAVE_STRTOL + +/* Define to 1 if you have the <sys/select.h> header file. */ +#undef HAVE_SYS_SELECT_H + /* Define to 1 if you have the <sys/socket.h> header file. */ #undef HAVE_SYS_SOCKET_H /* Define to 1 if you have the <sys/stat.h> header file. */ #undef HAVE_SYS_STAT_H +/* Define to 1 if you have the <sys/time.h> header file. */ +#undef HAVE_SYS_TIME_H + /* Define to 1 if you have the <sys/types.h> header file. */ #undef HAVE_SYS_TYPES_H @@ -66,6 +154,18 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* Define to the type of arg 1 for `select'. */ +#undef SELECT_TYPE_ARG1 + +/* Define to the type of args 2, 3 and 4 for `select'. */ +#undef SELECT_TYPE_ARG234 + +/* Define to the type of arg 5 for `select'. */ +#undef SELECT_TYPE_ARG5 + /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS @@ -78,5 +178,11 @@ /* 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 `unsigned' if <sys/types.h> does not define. */ +#undef size_t + /* Define to `int' if <sys/types.h> does not define. */ #undef ssize_t diff --git a/configure.ac b/configure.ac index 2f9cdae..5ad6b14 100644 --- a/configure.ac +++ b/configure.ac @@ -83,7 +83,6 @@ AC_SUBST(NANOHTTP_RELEASE) AC_SUBST(NANOHTTP_VERSION) - # Process this file with autoconf to produce a configure script. #AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS) #AC_INIT(src/csoap.c) @@ -93,24 +92,26 @@ AC_SUBST(NANOHTTP_VERSION) AC_PROG_CC AM_PROG_LIBTOOL -# Checks for libraries. - # Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS([arpa/inet.h netdb.h string.h sys/socket.h]) +AC_HEADER_TIME +AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h malloc.h netdb.h netinet/in.h stdint.h stdlib.h signal.h pthread.h string.h sys/socket.h sys/time.h unistd.h io.h stdio.h stdarg.h errno.h ctype.h openssl/rand.h openssl/err.h]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST -AC_HEADER_TIME AC_STRUCT_TM -dnl Checks for library functions. -#AC_FUNC_MALLOC -AC_FUNC_VPRINTF -AC_CHECK_FUNCS([gethostbyname socket]) +AC_TYPE_SIGNAL +AC_TYPE_SIZE_T AC_CHECK_TYPE(ssize_t, int) +AC_FUNC_MALLOC +AC_FUNC_VPRINTF +AC_FUNC_STRFTIME +AC_FUNC_SELECT_ARGTYPES +AC_CHECK_FUNCS([gethostbyname inet_ntoa localtime_r memmove memset mkdir select socket strchr strdup strncasecmp strpbrk strspn strstr strtol]) + # ------------------------------------------ dnl Check socket library (for Solaris) # ------------------------------------------ diff --git a/examples/Makefile.am b/examples/Makefile.am index c9c2f15..a79d5c7 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1 +1 @@ -SUBDIRS=csoap +SUBDIRS=csoap nanohttp diff --git a/examples/nanohttp/Makefile.am b/examples/nanohttp/Makefile.am index 8e4f7cc..21613ca 100644 --- a/examples/nanohttp/Makefile.am +++ b/examples/nanohttp/Makefile.am @@ -1,25 +1,28 @@ -bin_PROGRAMS=httpget httpgetcb httppost httpcpost postserver +bin_PROGRAMS=http_server +#bin_PROGRAMS=http_server httpget httpgetcb httppost httpcpost postserver INCLUDES=-I$(top_srcdir)/ nanohttp_LDFLAG=-L$(top_builddir)/nanohttp -lnanohttp-$(GENERIC_API_VERSION) \ $(LIBSOCKET) $(LIBNSL) -lpthread -httpget_SOURCES=httpget.c -httpget_LDFLAGS=$(nanohttp_LDFLAG) -httpgetcb_SOURCES=httpgetcb.c -httpgetcb_LDFLAGS=$(nanohttp_LDFLAG) +#simpleclient_SOURCES=simpleclient.c -httppost_SOURCES=httppost.c -httppost_LDFLAGS=$(nanohttp_LDFLAG) +http_server_SOURCES=http_server.c +http_server_LDFLAGS=$(nanohttp_LDFLAG) -httpcpost_SOURCES=httpcpost.c -httpcpost_LDFLAGS=$(nanohttp_LDFLAG) - -postserver_SOURCES=postserver.c -postserver_LDFLAGS=$(nanohttp_LDFLAG) +#httpget_SOURCES=httpget.c +#httpget_LDFLAGS=$(nanohttp_LDFLAG) +#httpgetcb_SOURCES=httpgetcb.c +#httpgetcb_LDFLAGS=$(nanohttp_LDFLAG) +#httppost_SOURCES=httppost.c +#httppost_LDFLAGS=$(nanohttp_LDFLAG) +#httpcpost_SOURCES=httpcpost.c +#httpcpost_LDFLAGS=$(nanohttp_LDFLAG) +#postserver_SOURCES=postserver.c +#postserver_LDFLAGS=$(nanohttp_LDFLAG) diff --git a/libcsoap/soap-client.c b/libcsoap/soap-client.c index 55fa6ca..f30018d 100644 --- a/libcsoap/soap-client.c +++ b/libcsoap/soap-client.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: soap-client.c,v 1.22 2006/02/08 11:13:14 snowdrop Exp $ +* $Id: soap-client.c,v 1.23 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A SOAP client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -95,7 +95,7 @@ soap_client_invoke(SoapCtx * call, SoapCtx ** response, const char *url, return herror_new("soap_client_invoke", SOAP_ERROR_CLIENT_INIT, "Unable to create SOAP client!"); } - conn->block = soap_client_get_blockmode(); + conn->sock.block = soap_client_get_blockmode(); /* Set soap action */ if (soap_action != NULL) diff --git a/libcsoap/soap-ctx.c b/libcsoap/soap-ctx.c index 7edefc3..dd68861 100755 --- a/libcsoap/soap-ctx.c +++ b/libcsoap/soap-ctx.c @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: soap-ctx.c,v 1.7 2006/01/10 11:29:04 snowdrop Exp $ + * $Id: soap-ctx.c,v 1.8 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A SOAP client/server library in C * Copyright (C) 2003-2004 Ferhat Ayaz @@ -21,16 +21,17 @@ * * Email: ferhatayaz@jprogrammer.net ******************************************************************/ -#include <libcsoap/soap-ctx.h> - #include <string.h> +#include <libcsoap/soap-ctx.h> + SoapCtx * soap_ctx_new(SoapEnv * env) /* should only be used internally */ { SoapCtx *ctx = (SoapCtx *) malloc(sizeof(SoapCtx)); ctx->env = env; ctx->attachments = NULL; + ctx->action = NULL; return ctx; } @@ -133,6 +134,8 @@ soap_ctx_free(SoapCtx * ctx) attachments_free(ctx->attachments); if (ctx->env) soap_env_free(ctx->env); + if (ctx->action) + free(ctx->action); free(ctx); } diff --git a/libcsoap/soap-ctx.h b/libcsoap/soap-ctx.h index 1baabba..a4784f5 100755 --- a/libcsoap/soap-ctx.h +++ b/libcsoap/soap-ctx.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: soap-ctx.h,v 1.7 2006/01/10 11:29:04 snowdrop Exp $ + * $Id: soap-ctx.h,v 1.8 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A SOAP client/server library in C * Copyright (C) 2003-2004 Ferhat Ayaz @@ -24,10 +24,10 @@ #ifndef cSOAP_CTX_H #define cSOAP_CTX_H - -#include <libcsoap/soap-env.h> #include <nanohttp/nanohttp-common.h> +#include <nanohttp/nanohttp-server.h> +#include <libcsoap/soap-env.h> #define SOAP_ERROR_NO_FILE_ATTACHED 4001 #define SOAP_ERROR_EMPTY_ATTACHMENT 4002 @@ -37,6 +37,8 @@ typedef struct _SoapCtx { SoapEnv *env; + char *action; + hrequest_t *http; attachments_t *attachments; } SoapCtx; diff --git a/libcsoap/soap-env.h b/libcsoap/soap-env.h index 36305e1..ee53f3a 100644 --- a/libcsoap/soap-env.h +++ b/libcsoap/soap-env.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: soap-env.h,v 1.12 2006/01/27 20:23:40 mrcsys Exp $ + * $Id: soap-env.h,v 1.13 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A SOAP client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -24,9 +24,10 @@ #ifndef cSOAP_ENV_H #define cSOAP_ENV_H +#include <nanohttp/nanohttp-stream.h> + #include <libcsoap/soap-xml.h> #include <libcsoap/soap-fault.h> -#include <nanohttp/nanohttp-stream.h> /** diff --git a/libcsoap/soap-router.c b/libcsoap/soap-router.c index 1e57850..fc26916 100644 --- a/libcsoap/soap-router.c +++ b/libcsoap/soap-router.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: soap-router.c,v 1.5 2006/01/10 11:29:04 snowdrop Exp $ +* $Id: soap-router.c,v 1.6 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A SOAP client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -21,22 +21,23 @@ * * Email: ayaz@jprogrammer.net ******************************************************************/ -#include <libcsoap/soap-router.h> #include <string.h> +#include <libcsoap/soap-router.h> + SoapRouter * -soap_router_new() +soap_router_new(void) { SoapRouter *router; router = (SoapRouter *) malloc(sizeof(SoapRouter)); router->service_head = NULL; router->service_tail = NULL; + router->default_service = NULL; return router; } - void soap_router_register_service(SoapRouter * router, SoapServiceFunc func, @@ -56,8 +57,31 @@ soap_router_register_service(SoapRouter * router, router->service_tail->next = soap_service_node_new(service, NULL); router->service_tail = router->service_tail->next; } + + return; } +void +soap_router_register_default_service(SoapRouter *router, SoapServiceFunc func, const char *method, const char *urn) { + + SoapService *service; + + service = soap_service_new(urn, method, func); + + if (router->service_tail == NULL) + { + router->service_head = router->service_tail = soap_service_node_new(service, NULL); + } + else + { + router->service_tail->next = soap_service_node_new(service, NULL); + router->service_tail = router->service_tail->next; + } + + router->default_service = service; + + return; +} SoapService * soap_router_find_service(SoapRouter * router, @@ -84,7 +108,7 @@ soap_router_find_service(SoapRouter * router, node = node->next; } - return NULL; + return router->default_service; } diff --git a/libcsoap/soap-router.h b/libcsoap/soap-router.h index 5b0c7ab..2a37117 100644 --- a/libcsoap/soap-router.h +++ b/libcsoap/soap-router.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: soap-router.h,v 1.4 2006/01/10 11:29:04 snowdrop Exp $ + * $Id: soap-router.h,v 1.5 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A SOAP client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -24,7 +24,6 @@ #ifndef cSOAP_ROUTER_H #define cSOAP_ROUTER_H - #include <libcsoap/soap-service.h> /** @@ -35,6 +34,7 @@ typedef struct _SoapRouter { SoapServiceNode *service_head; SoapServiceNode *service_tail; + SoapService *default_service; } SoapRouter; @@ -47,7 +47,7 @@ typedef struct _SoapRouter @returns Soap router @see soap_router_free */ -SoapRouter *soap_router_new(); +SoapRouter *soap_router_new(void); /** @@ -64,6 +64,8 @@ void soap_router_register_service(SoapRouter * router, SoapServiceFunc func, const char *method, const char *urn); +void soap_router_register_default_service(SoapRouter * router, SoapServiceFunc func, const char *method, const char *urn); + /** Searches for a registered soap service. diff --git a/libcsoap/soap-server.c b/libcsoap/soap-server.c index af1d808..68d6f16 100644 --- a/libcsoap/soap-server.c +++ b/libcsoap/soap-server.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: soap-server.c,v 1.16 2006/02/08 11:13:14 snowdrop Exp $ +* $Id: soap-server.c,v 1.17 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A SOAP client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -21,10 +21,11 @@ * * Email: ayaz@jprogrammer.net ******************************************************************/ -#include <libcsoap/soap-server.h> -#include <nanohttp/nanohttp-server.h> #include <string.h> +#include <nanohttp/nanohttp-server.h> + +#include <libcsoap/soap-server.h> typedef struct _SoapRouterNode { @@ -34,22 +35,139 @@ typedef struct _SoapRouterNode } SoapRouterNode; -SoapRouterNode *head = NULL; -SoapRouterNode *tail = NULL; +static SoapRouterNode *head = NULL; +static SoapRouterNode *tail = NULL; + +static void +_soap_server_send_env(http_output_stream_t * out, SoapEnv * env) +{ + xmlBufferPtr buffer; + if (env == NULL || env->root == NULL) + return; + + buffer = xmlBufferCreate(); + xmlNodeDump(buffer, env->root->doc, env->root, 1, 1); + http_output_stream_write_string(out, + (const char *) xmlBufferContent(buffer)); + xmlBufferFree(buffer); + +} + +static void +_soap_server_send_fault(httpd_conn_t * conn, hpair_t * header, + const char *errmsg) +{ + SoapEnv *envres; + herror_t err; + char buffer[45]; + + httpd_set_headers(conn, header); + + if ((err = httpd_send_header(conn, 500, "FAILED")) != H_OK) + { + /* WARNING: unhandled exception ! */ + log_error4("%s():%s [%d]", herror_func(err), herror_message(err), + herror_code(err)); + + herror_release(err); + return; + } + + err = soap_env_new_with_fault(Fault_Server, + errmsg ? errmsg : "General error", + "cSOAP_Server", NULL, &envres); + if (err != H_OK) + { + log_error1(herror_message(err)); + http_output_stream_write_string(conn->out, "<html><head></head><body>"); + http_output_stream_write_string(conn->out, "<h1>Error</h1><hr/>"); + http_output_stream_write_string(conn->out, + "Error while sending fault object:<br>Message: "); + http_output_stream_write_string(conn->out, herror_message(err)); + http_output_stream_write_string(conn->out, "<br />Function: "); + http_output_stream_write_string(conn->out, herror_func(err)); + http_output_stream_write_string(conn->out, "<br />Error code: "); + sprintf(buffer, "%d", herror_code(err)); + http_output_stream_write_string(conn->out, buffer); + http_output_stream_write_string(conn->out, "</body></html>"); + + herror_release(err); + return; + } + else + { + _soap_server_send_env(conn->out, envres); + } + return; +} + +static void +_soap_server_send_ctx(httpd_conn_t * conn, SoapCtx * ctx) +{ + xmlBufferPtr buffer; + static int counter = 1; + char strbuffer[150]; + part_t *part; + + if (ctx->env == NULL || ctx->env->root == NULL) + return; + + buffer = xmlBufferCreate(); +/* xmlIndentTreeOutput = 1;*/ + xmlThrDefIndentTreeOutput(1); +/* xmlKeepBlanksDefault(0);*/ + xmlNodeDump(buffer, ctx->env->root->doc, ctx->env->root, 1, 1); + + if (ctx->attachments) + { + sprintf(strbuffer, "000128590350940924234%d", counter++); + httpd_mime_send_header(conn, strbuffer, "", "text/xml", 200, "OK"); + httpd_mime_next(conn, strbuffer, "text/xml", "binary"); + http_output_stream_write_string(conn->out, + (const char *) xmlBufferContent(buffer)); + part = ctx->attachments->parts; + while (part) + { + httpd_mime_send_file(conn, part->id, part->content_type, + part->transfer_encoding, part->filename); + part = part->next; + } + httpd_mime_end(conn); + } + else + { + char buflen[100]; + xmlXPathContextPtr xpathCtx; + xmlXPathObjectPtr xpathObj; + xpathCtx = xmlXPathNewContext(ctx->env->root->doc); + xpathObj = xmlXPathEvalExpression("//Fault", xpathCtx); +#ifdef WIN32 +#define snprintf(buffer, num, s1, s2) sprintf(buffer, s1,s2) +#endif + snprintf(buflen, 100, "%d", + strlen((const char *) xmlBufferContent(buffer))); + httpd_set_header(conn, HEADER_CONTENT_LENGTH, buflen); + if ((xpathObj->nodesetval) ? xpathObj->nodesetval->nodeNr : 0) + { + httpd_send_header(conn, 500, "FAILED"); + } + else + { + httpd_send_header(conn, 200, "OK"); + } + + http_output_stream_write_string(conn->out, + (const char *) xmlBufferContent(buffer)); + xmlXPathFreeObject(xpathObj); + xmlXPathFreeContext(xpathCtx); -/*---------------------------------*/ -static void _soap_server_send_ctx(httpd_conn_t * conn, SoapCtx * ctxres); + } + xmlBufferFree(buffer); -void soap_server_entry(httpd_conn_t * conn, hrequest_t * req); -static void _soap_server_send_env(http_output_stream_t * out, SoapEnv * env); -static - void _soap_server_send_fault(httpd_conn_t * conn, hpair_t * header, - const char *errmsg); -/*---------------------------------*/ +} static SoapRouterNode * -router_node_new(SoapRouter * router, - const char *context, SoapRouterNode * next) +router_node_new(SoapRouter * router, const char *context, SoapRouterNode * next) { SoapRouterNode *node; const char *noname = "/lost_found"; @@ -88,68 +206,7 @@ router_find(const char *context) return NULL; } -herror_t -soap_server_init_args(int argc, char *argv[]) -{ - return httpd_init(argc, argv); -} - - -int -soap_server_register_router(SoapRouter * router, const char *context) -{ - - if (!httpd_register(context, soap_server_entry)) - { - return 0; - } - - if (tail == NULL) - { - head = tail = router_node_new(router, context, NULL); - } - else - { - tail->next = router_node_new(router, context, NULL); - tail = tail->next; - } - - return 1; -} - - -herror_t -soap_server_run() -{ - return httpd_run(); -} - -int -soap_server_get_port(void) -{ - return httpd_get_port(); -} - -void -soap_server_destroy() -{ - SoapRouterNode *node = head; - SoapRouterNode *tmp; - - while (node != NULL) - { - tmp = node->next; - log_verbose2("soap_router_free(%p)", node->router); - soap_router_free(node->router); - free(node->context); - free(node); - node = tmp; - } - httpd_destroy(); -} - - -void +static void soap_server_entry(httpd_conn_t * conn, hrequest_t * req) { hpair_t *header = NULL; @@ -167,7 +224,7 @@ soap_server_entry(httpd_conn_t * conn, hrequest_t * req) httpd_send_header(conn, 200, "OK"); http_output_stream_write_string(conn->out, "<html><head></head><body>"); - http_output_stream_write_string(conn->out, "<h1>Sorry! </h1><hr>"); + http_output_stream_write_string(conn->out, "<h1>Sorry!</h1><hr />"); http_output_stream_write_string(conn->out, "I only speak with 'POST' method"); http_output_stream_write_string(conn->out, "</body></html>"); @@ -196,6 +253,8 @@ soap_server_entry(httpd_conn_t * conn, hrequest_t * req) { ctx = soap_ctx_new(env); + ctx->action = hpairnode_get_ignore_case(req->header, "SoapAction"); + ctx->http = req; soap_ctx_add_files(ctx, req->attachments); if (ctx->env == NULL) @@ -285,8 +344,8 @@ soap_server_entry(httpd_conn_t * conn, hrequest_t * req) else { -/* httpd_send_header(conn, 200, "OK"); - _soap_server_send_env(conn->out, ctxres->env); +/* httpd_send_header(conn, 200, "OK"); + _soap_server_send_env(conn->out, ctxres->env); */ _soap_server_send_ctx(conn, ctxres); /* free envctx */ @@ -301,131 +360,63 @@ soap_server_entry(httpd_conn_t * conn, hrequest_t * req) } } - -static void -_soap_server_send_ctx(httpd_conn_t * conn, SoapCtx * ctx) +herror_t +soap_server_init_args(int argc, char *argv[]) { - xmlBufferPtr buffer; - static int counter = 1; - char strbuffer[150]; - part_t *part; + return httpd_init(argc, argv); +} - if (ctx->env == NULL || ctx->env->root == NULL) - return; +int +soap_server_register_router(SoapRouter * router, const char *context) +{ - buffer = xmlBufferCreate(); -/* xmlIndentTreeOutput = 1;*/ - xmlThrDefIndentTreeOutput(1); -/* xmlKeepBlanksDefault(0);*/ - xmlNodeDump(buffer, ctx->env->root->doc, ctx->env->root, 1, 1); + if (!httpd_register(context, soap_server_entry)) + { + return 0; + } - if (ctx->attachments) + if (tail == NULL) { - sprintf(strbuffer, "000128590350940924234%d", counter++); - httpd_mime_send_header(conn, strbuffer, "", "text/xml", 200, "OK"); - httpd_mime_next(conn, strbuffer, "text/xml", "binary"); - http_output_stream_write_string(conn->out, - (const char *) xmlBufferContent(buffer)); - part = ctx->attachments->parts; - while (part) - { - httpd_mime_send_file(conn, part->id, part->content_type, - part->transfer_encoding, part->filename); - part = part->next; - } - httpd_mime_end(conn); + head = tail = router_node_new(router, context, NULL); } else { - char buflen[100]; - xmlXPathContextPtr xpathCtx; - xmlXPathObjectPtr xpathObj; - xpathCtx = xmlXPathNewContext(ctx->env->root->doc); - xpathObj = xmlXPathEvalExpression("//Fault", xpathCtx); -#ifdef WIN32 -#define snprintf(buffer, num, s1, s2) sprintf(buffer, s1,s2) -#endif - snprintf(buflen, 100, "%d", - strlen((const char *) xmlBufferContent(buffer))); - httpd_set_header(conn, HEADER_CONTENT_LENGTH, buflen); - if ((xpathObj->nodesetval) ? xpathObj->nodesetval->nodeNr : 0) - { - httpd_send_header(conn, 500, "FAILED"); - } - else - { - httpd_send_header(conn, 200, "OK"); - } - - http_output_stream_write_string(conn->out, - (const char *) xmlBufferContent(buffer)); - xmlXPathFreeObject(xpathObj); - xmlXPathFreeContext(xpathCtx); - + tail->next = router_node_new(router, context, NULL); + tail = tail->next; } - xmlBufferFree(buffer); + return 1; } -static void -_soap_server_send_env(http_output_stream_t * out, SoapEnv * env) -{ - xmlBufferPtr buffer; - if (env == NULL || env->root == NULL) - return; - - buffer = xmlBufferCreate(); - xmlNodeDump(buffer, env->root->doc, env->root, 1, 1); - http_output_stream_write_string(out, - (const char *) xmlBufferContent(buffer)); - xmlBufferFree(buffer); +herror_t +soap_server_run() +{ + return httpd_run(); } -static void -_soap_server_send_fault(httpd_conn_t * conn, hpair_t * header, - const char *errmsg) +int +soap_server_get_port(void) { - SoapEnv *envres; - herror_t err; - char buffer[45]; - httpd_set_headers(conn, header); - err = httpd_send_header(conn, 500, "FAILED"); - if (err != H_OK) - { - /* WARNING: unhandled exception ! */ - log_error4("%s():%s [%d]", herror_func(err), herror_message(err), - herror_code(err)); - return; - } + return httpd_get_port(); +} - err = soap_env_new_with_fault(Fault_Server, - errmsg ? errmsg : "General error", - "cSOAP_Server", NULL, &envres); - if (err != H_OK) - { - log_error1(herror_message(err)); - http_output_stream_write_string(conn->out, "<html><head></head><body>"); - http_output_stream_write_string(conn->out, "<h1>Error</h1><hr>"); - http_output_stream_write_string(conn->out, - "Error while sending fault object:<br>Message: "); - http_output_stream_write_string(conn->out, herror_message(err)); - http_output_stream_write_string(conn->out, "<br>Function: "); - http_output_stream_write_string(conn->out, herror_func(err)); - http_output_stream_write_string(conn->out, "<br>Error code: "); - sprintf(buffer, "%d", herror_code(err)); - http_output_stream_write_string(conn->out, buffer); - http_output_stream_write_string(conn->out, "</body></html>"); - return; +void +soap_server_destroy() +{ + SoapRouterNode *node = head; + SoapRouterNode *tmp; - herror_release(err); - } - else + while (node != NULL) { - _soap_server_send_env(conn->out, envres); + tmp = node->next; + log_verbose2("soap_router_free(%p)", node->router); + soap_router_free(node->router); + free(node->context); + free(node); + node = tmp; } - + httpd_destroy(); } - diff --git a/nanohttp/Makefile.am b/nanohttp/Makefile.am index 6e6be3a..2ad1fb8 100644 --- a/nanohttp/Makefile.am +++ b/nanohttp/Makefile.am @@ -9,6 +9,7 @@ nanohttp-stream.h\ nanohttp-mime.h\ nanohttp-request.h\ nanohttp-response.h\ +nanohttp-base64.h\ nanohttp-ssl.h @@ -20,6 +21,7 @@ nanohttp-stream.c\ nanohttp-mime.c\ nanohttp-request.c\ nanohttp-response.c\ +nanohttp-base64.c\ nanohttp-ssl.c diff --git a/nanohttp/nanohttp-client.c b/nanohttp/nanohttp-client.c index 44ba815..802e021 100644 --- a/nanohttp/nanohttp-client.c +++ b/nanohttp/nanohttp-client.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-client.c,v 1.37 2006/02/08 11:13:14 snowdrop Exp $ +* $Id: nanohttp-client.c,v 1.38 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -21,30 +21,37 @@ * * Email: ferhatayaz@yahoo.com ******************************************************************/ -#include <nanohttp/nanohttp-client.h> -#include <nanohttp/nanohttp-ssl.h> - #ifdef HAVE_CONFIG_H #include <config.h> #endif +#ifdef HAVE_TIME_H #include <time.h> +#endif + +#ifdef HAVE_STDIO_H #include <stdio.h> +#endif + +#ifdef HAVE_STDLIB_H #include <stdlib.h> +#endif + +#ifdef HAVE_STDARG_H #include <stdarg.h> +#endif + +#ifdef HAVE_STRING_H #include <string.h> +#endif #ifdef MEM_DEBUG #include <utils/alloc.h> #endif -#if 0 -static int -httpc_send_data(httpc_conn_t * conn, const unsigned char *data, size_t size) -{ - return -1; -} -#endif +#include "nanohttp-client.h" +#include "nanohttp-socket.h" + /*-------------------------------------------------- FUNCTION: httpc_init DESC: Initialize http client connection @@ -54,24 +61,21 @@ herror_t httpc_init(int argc, char *argv[]) { hoption_init_args(argc, argv); - hsocket_module_init(); -#ifdef HAVE_SSL - start_ssl(); -#endif - return H_OK; -} + return hsocket_module_init(); +} /*-------------------------------------------------- FUNCTION: httpc_destroy DESC: Destroy the http client module ----------------------------------------------------*/ void -httpc_destroy() +httpc_destroy(void) { hsocket_module_destroy(); -} + return; +} /*-------------------------------------------------- FUNCTION: httpc_new @@ -80,26 +84,27 @@ You need to create at least 1 http client connection to communicate via http. ----------------------------------------------------*/ httpc_conn_t * -httpc_new() +httpc_new(void) { static int counter = 10000; - httpc_conn_t *res = (httpc_conn_t *) malloc(sizeof(httpc_conn_t)); + httpc_conn_t *res; + + if (!(res = (httpc_conn_t *) malloc(sizeof(httpc_conn_t)))) + return NULL; if (hsocket_init(&res->sock) != H_OK) - { return NULL; - } + res->header = NULL; res->version = HTTP_1_1; res->out = NULL; res->_dime_package_nr = 0; res->_dime_sent_bytes = 0; res->id = counter++; - res->block = 0; + return res; } - /*-------------------------------------------------- FUNCTION: httpc_free DESC: Free the given http client object. @@ -129,6 +134,7 @@ httpc_free(httpc_conn_t * conn) hsocket_free(conn->sock); free(conn); + return; } /*-------------------------------------------------- @@ -143,6 +149,8 @@ httpc_close_free(httpc_conn_t * conn) hsocket_close(conn->sock); httpc_free(conn); + + return; } int @@ -168,7 +176,7 @@ httpc_add_headers(httpc_conn_t *conn, const hpair_t *values) return; } - for(;values; values=values->next) + for ( ;values; values=values->next) httpc_add_header(conn, values->key, values->value); return; @@ -190,59 +198,40 @@ httpc_set_header(httpc_conn_t *conn, const char *key, const char *value) log_warn1("Connection object is NULL"); return 0; } - p = conn->header; - while (p != NULL) + + for (p = conn->header; p; p = p->next) { - if (p->key != NULL) + if (p->key && !strcmp(p->key, key)) { - if (!strcmp(p->key, key)) - { - free(p->value); - p->value = (char *) malloc(strlen(value) + 1); - strcpy(p->value, value); - return 1; - } + free(p->value); + p->value = strdup(value); + return 1; } - p = p->next; } conn->header = hpairnode_new(key, value, conn->header); + return 0; } /*-------------------------------------------------- -FUNCTION: httpc_header_add_date -DESC: Adds the current date to the header. -----------------------------------------------------*/ -/* static void -_httpc_set_error(httpc_conn_t * conn, int errcode, const char *format, ...) -{ - va_list ap; - - conn->errcode = errcode; - - va_start(ap, format); - vsprintf(conn->errmsg, format, ap); - va_end(ap); -} */ - -/*-------------------------------------------------- -FUNCTION: httpc_header_add_date +FUNCTION: httpc_header_set_date DESC: Adds the current date to the header. ----------------------------------------------------*/ static void -httpc_header_add_date(httpc_conn_t * conn) +httpc_header_set_date(httpc_conn_t * conn) { - char buffer[255]; - time_t nw; + char buffer[32]; + time_t ts; struct tm stm; - /* Set date */ - nw = time(NULL); - localtime_r(&nw, &stm); - strftime(buffer, 255, "%a, %d %b %Y %H:%M:%S GMT", &stm); + ts = time(NULL); + localtime_r(&ts, &stm); + strftime(buffer, 32, "%a, %d %b %Y %H:%M:%S GMT", &stm); + httpc_set_header(conn, HEADER_DATE, buffer); + return; } @@ -254,25 +243,21 @@ in conn through conn->sock. herror_t httpc_send_header(httpc_conn_t * conn) { - hpair_t *p; + hpair_t *walker; herror_t status; char buffer[1024]; - p = conn->header; - while (p != NULL) + for (walker = conn->header; walker; walker = walker->next) { - if (p->key && p->value) + if (walker->key && walker->value) { - sprintf(buffer, "%s: %s\r\n", p->key, p->value); - status = hsocket_send(conn->sock, buffer); - if (status != H_OK) + sprintf(buffer, "%s: %s\r\n", walker->key, walker->value); + if ((status = hsocket_send(conn->sock, buffer)) != H_OK) return status; } - p = p->next; } - status = hsocket_send(conn->sock, "\r\n"); - return status; + return hsocket_send(conn->sock, "\r\n"); } /*-------------------------------------------------- @@ -335,11 +320,9 @@ httpc_talk_to_server(hreq_method_t method, httpc_conn_t * conn, GENERAL_INVALID_PARAM, "httpc_conn_t param is NULL"); } /* Build request header */ - httpc_header_add_date(conn); + httpc_header_set_date(conn); - /* Create url */ - status = hurl_parse(&url, urlstr); - if (status != H_OK) + if ((status = hurl_parse(&url, urlstr)) != H_OK) { log_error2("Can not parse URL '%s'", SAVE_STR(urlstr)); return status; @@ -350,61 +333,42 @@ httpc_talk_to_server(hreq_method_t method, httpc_conn_t * conn, httpc_set_header(conn, HEADER_HOST, url.host); /* Open connection */ - status = hsocket_open(&conn->sock, url.host, url.port); - if (status != H_OK) - { + if ((status = hsocket_open(&conn->sock, url.host, url.port)) != H_OK) return status; - } -#ifdef HAVE_SSL - /* TODO XXX XXX this is probably not right -- matt */ - if (!&conn->sock.ssl) - { - status = hsocket_block(conn->sock, conn->block); - if (status != H_OK) - { - log_error1("Cannot make socket non-blocking"); - return status; - } - } -#endif - /* check method */ - if (method == HTTP_REQUEST_GET) + + switch(method) { + case HTTP_REQUEST_GET: - /* Set GET Header */ - sprintf(buffer, "GET %s HTTP/%s\r\n", - (url.context[0] != '\0') ? url.context : ("/"), - (conn->version == HTTP_1_0) ? "1.0" : "1.1"); + sprintf(buffer, "GET %s HTTP/%s\r\n", + (url.context[0] != '\0') ? url.context : ("/"), + (conn->version == HTTP_1_0) ? "1.0" : "1.1"); + break; - } - else if (method == HTTP_REQUEST_POST) - { + case HTTP_REQUEST_POST: - /* Set POST Header */ - sprintf(buffer, "POST %s HTTP/%s\r\n", - (url.context[0] != '\0') ? url.context : ("/"), - (conn->version == HTTP_1_0) ? "1.0" : "1.1"); - } - else - { + sprintf(buffer, "POST %s HTTP/%s\r\n", + (url.context[0] != '\0') ? url.context : ("/"), + (conn->version == HTTP_1_0) ? "1.0" : "1.1"); + break; - log_error1("Unknown method type!"); - return herror_new("httpc_talk_to_server", - GENERAL_INVALID_PARAM, - "hreq_method_t must be HTTP_REQUEST_GET or HTTP_REQUEST_POST"); + default: + log_error1("Unknown method type!"); + return herror_new("httpc_talk_to_server", + GENERAL_INVALID_PARAM, + "hreq_method_t must be HTTP_REQUEST_GET or HTTP_REQUEST_POST"); } - log_verbose1("Sending header..."); - status = hsocket_send(conn->sock, buffer); - if (status != H_OK) + log_verbose1("Sending request..."); + if ((status = hsocket_send(conn->sock, buffer)) != H_OK) { log_error2("Can not send request (status:%d)", status); hsocket_close(conn->sock); return status; } - /* Send Header */ - status = httpc_send_header(conn); - if (status != H_OK) + + log_verbose1("Sending header..."); + if ((status = httpc_send_header(conn)) != H_OK) { log_error2("Can not send header (status:%d)", status); hsocket_close(conn->sock); @@ -412,7 +376,6 @@ httpc_talk_to_server(hreq_method_t method, httpc_conn_t * conn, } return H_OK; - } /*-------------------------------------------------- @@ -424,19 +387,11 @@ httpc_get(httpc_conn_t * conn, hresponse_t ** out, const char *urlstr) { herror_t status; - status = httpc_talk_to_server(HTTP_REQUEST_GET, conn, urlstr); - - if (status != H_OK) - { + if ((status = httpc_talk_to_server(HTTP_REQUEST_GET, conn, urlstr)) != H_OK) return status; - } - status = hresponse_new_from_socket(conn->sock, out); - if (status != H_OK) - { + if ((status = hresponse_new_from_socket(conn->sock, out)) != H_OK) return status; - } - return H_OK; } @@ -449,11 +404,9 @@ DESC: Returns H_OK if success herror_t httpc_post_begin(httpc_conn_t * conn, const char *url) { - herror_t status; - status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, url); - if (status != H_OK) + if ((status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, url)) != H_OK) return status; conn->out = http_output_stream_new(conn->sock, conn->header); @@ -472,171 +425,15 @@ httpc_post_end(httpc_conn_t * conn, hresponse_t ** out) { herror_t status; - status = http_output_stream_flush(conn->out); - - if (status != H_OK) - { + if ((status = http_output_stream_flush(conn->out)) != H_OK) return status; - } - status = hresponse_new_from_socket(conn->sock, out); - if (status != H_OK) - { + if ((status = hresponse_new_from_socket(conn->sock, out)) != H_OK) return status; - } return H_OK; } - - -/* --------------------------------------------------- - DIME support functions httpc_dime_* function set ------------------------------------------------------*/ -/* -int httpc_dime_begin(httpc_conn_t *conn, const char *url) -{ - int status; - - httpc_set_header(conn, HEADER_CONTENT_TYPE, "application/dime"); - - status = httpc_talk_to_server(HTTP_REQUEST_POST, conn, url); - if (status != H_OK) - return status; - - conn->out = http_output_stream_new(conn->sock, conn->header); - - return H_OK; -} - -static _print_binary_ascii(int n) -{ - int i,c=0; - char ascii[36]; - - for (i=0;i<32;i++) { - ascii[34-i-c] = (n & (1<<i))?'1':'0'; - if ((i+1)%8 == 0) { - c++; - ascii[i+c] = ' '; - } - } - - ascii[35]='\0'; - - log_verbose2("%s", ascii); -} - -static -void _get_binary_ascii8(unsigned char n, char* ascii) -{ - int i; - for (i=0;i<8;i++) - ascii[7-i] = (n & (1<<i))?'1':'0'; - - ascii[8]='\0'; -} - -static -void _print_binary_ascii32(unsigned char b1, unsigned char b2, - unsigned char b3, unsigned char b4) -{ - char ascii[4][9]; - _get_binary_ascii8(b1, ascii[0]); - _get_binary_ascii8(b2, ascii[1]); - _get_binary_ascii8(b3, ascii[2]); - _get_binary_ascii8(b4, ascii[3]); - - log_verbose5("%s %s %s %s", ascii[0], ascii[1], ascii[2], ascii[3]); -} - -int httpc_dime_next(httpc_conn_t* conn, long content_length, - const char *content_type, const char *id, - const char *dime_options, int last) -{ - int status, tmp; - byte_t header[12]; - - for (tmp=0;tmp<12;tmp++) - header[tmp]=0; - - header[0] |= DIME_VERSION_1; - - if (conn->_dime_package_nr == 0) - header[0] |= DIME_FIRST_PACKAGE; - - if (last) - header[0] |= DIME_LAST_PACKAGE; - - header[1] = DIME_TYPE_URI; - - tmp = strlen(dime_options); - header[2] = tmp >> 8; - header[3] = tmp; - - tmp = strlen(id); - header[4] = tmp >> 8; - header[5] = tmp; - - tmp = strlen(content_type); - header[6] = tmp >> 8; - header[7] = tmp; - - header[8] = (byte_t)content_length >> 24; - header[9] = (byte_t)content_length >> 16; - header[10] = (byte_t)content_length >> 8; - header[11] = (byte_t)content_length; - - - _print_binary_ascii32(header[0], header[1], header[2], header[3]); - _print_binary_ascii32(header[4], header[5], header[6], header[7]); - _print_binary_ascii32(header[8], header[9], header[10], header[11]); - - status = http_output_stream_write(conn->out, header, 12); - if (status != H_OK) - return status; - - status = http_output_stream_write(conn->out, (const byte_t*)dime_options, strlen(dime_options)); - if (status != H_OK) - return status; - - status = http_output_stream_write(conn->out, (const byte_t*)id, strlen(id)); - if (status != H_OK) - return status; - - status = http_output_stream_write(conn->out, (const byte_t*)content_type, strlen(content_type)); - if (status != H_OK) - return status; - - return status; -} - - -hresponse_t* httpc_dime_end(httpc_conn_t *conn) -{ - int status; - hresponse_t *res; - - Flush put stream - status = http_output_stream_flush(conn->out); - - if (status != H_OK) - { - _httpc_set_error(conn, status, "Can not flush output stream"); - return NULL; - } - - res = hresponse_new_from_socket(conn->sock); - if (res == NULL) - { - _httpc_set_error(conn, -1, "Can not get response "); - return NULL; - } - - return res; -} - -*/ /* --------------------------------------------------- MIME support functions httpc_mime_* function set -----------------------------------------------------*/ @@ -699,7 +496,6 @@ httpc_mime_begin(httpc_conn_t * conn, const char *url, return status; } - herror_t httpc_mime_next(httpc_conn_t * conn, const char *content_id, @@ -726,10 +522,8 @@ httpc_mime_next(httpc_conn_t * conn, HEADER_CONTENT_TRANSFER_ENCODING, transfer_encoding, HEADER_CONTENT_ID, content_id); - status = http_output_stream_write(conn->out, + return http_output_stream_write(conn->out, (const byte_t *) buffer, strlen(buffer)); - - return status; } @@ -751,22 +545,13 @@ httpc_mime_end(httpc_conn_t * conn, hresponse_t ** out) if (status != H_OK) return status; - /* Flush put stream */ - status = http_output_stream_flush(conn->out); - - if (status != H_OK) - { + if ((status = http_output_stream_flush(conn->out)) != H_OK) return status; - } - status = hresponse_new_from_socket(conn->sock, out); - if (status != H_OK) - { + if ((status = hresponse_new_from_socket(conn->sock, out)) != H_OK) return status; - } return H_OK; - } diff --git a/nanohttp/nanohttp-client.h b/nanohttp/nanohttp-client.h index 03e1e16..221ae34 100644 --- a/nanohttp/nanohttp-client.h +++ b/nanohttp/nanohttp-client.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-client.h,v 1.19 2006/02/08 11:13:14 snowdrop Exp $ + * $Id: nanohttp-client.h,v 1.20 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -44,7 +44,6 @@ typedef struct httpc_conn char errmsg[150]; http_output_stream_t *out; int id; /* uniq id */ - int block; } httpc_conn_t; diff --git a/nanohttp/nanohttp-common.c b/nanohttp/nanohttp-common.c index d7b1f27..1f2040d 100644 --- a/nanohttp/nanohttp-common.c +++ b/nanohttp/nanohttp-common.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-common.c,v 1.26 2006/02/09 13:43:49 mrcsys Exp $ +* $Id: nanohttp-common.c,v 1.27 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -21,17 +21,31 @@ * * Email: ayaz@jprogrammer.net ******************************************************************/ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif -#include <nanohttp/nanohttp-common.h> - - +#ifdef HAVE_STDIO_H #include <stdio.h> +#endif + +#ifdef HAVE_STDLIB_H #include <stdlib.h> +#endif + +#ifdef HAVE_STDARG_H #include <stdarg.h> +#endif + +#ifdef HAVE_STRING_H #include <string.h> +#endif + +#ifdef HAVE_CTYPE_H #include <ctype.h> +#endif -#ifndef WIN32 +#ifdef HAVE_PTHREAD_H #include <pthread.h> #endif @@ -39,19 +53,35 @@ #include <utils/alloc.h> #endif +#include <nanohttp/nanohttp-common.h> #define MAX_OPTION_SIZE 50 #define MAX_OPTION_VALUE_SIZE 150 static char _hoption_table[MAX_OPTION_SIZE][MAX_OPTION_VALUE_SIZE]; -#ifdef HAVE_SSL -/*extern char *SSLCert; -extern char *SSLPass; -extern char *SSLCA; -extern int SSLCertLess; -*/ -#endif +static int +strcmpigcase(const char *s1, const char *s2) +{ + int l1, l2, i; + + if (s1 == NULL && s2 == NULL) + return 1; + if (s1 == NULL || s2 == NULL) + return 0; + + l1 = strlen(s1); + l2 = strlen(s2); + + if (l1 != l2) + return 0; + + for (i = 0; i < l1; i++) + if (toupper(s1[i]) != toupper(s2[i])) + return 0; + + return 1; +} /* option stuff */ void @@ -64,6 +94,8 @@ hoption_set(int opt, const char *value) } strncpy(_hoption_table[opt], value, MAX_OPTION_VALUE_SIZE); + + return; } @@ -173,7 +205,6 @@ typedef struct _herror_impl_t char func[100]; } herror_impl_t; - herror_t herror_new(const char *func, int errcode, const char *format, ...) { @@ -363,32 +394,6 @@ log_error(const char *FUNC, const char *format, ...) } -/* ----------------------------------------- - FUNCTION: strcmpigcase - ------------------------------------------*/ -int -strcmpigcase(const char *s1, const char *s2) -{ - int l1, l2, i; - - if (s1 == NULL && s2 == NULL) - return 1; - if (s1 == NULL || s2 == NULL) - return 0; - - l1 = strlen(s1); - l2 = strlen(s2); - - if (l1 != l2) - return 0; - - for (i = 0; i < l1; i++) - if (toupper(s1[i]) != toupper(s2[i])) - return 0; - - return 1; -} - hpair_t * hpairnode_new(const char *key, const char *value, hpair_t * next) @@ -607,7 +612,6 @@ hurl_dump(const hurl_t * url) log_verbose2(" CONTEXT : %s", url->context); } - herror_t hurl_parse(hurl_t * url, const char *urlstr) { diff --git a/nanohttp/nanohttp-common.h b/nanohttp/nanohttp-common.h index 607fc2b..d982d51 100644 --- a/nanohttp/nanohttp-common.h +++ b/nanohttp/nanohttp-common.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-common.h,v 1.24 2006/01/18 16:28:24 mrcsys Exp $ + * $Id: nanohttp-common.h,v 1.25 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003-2004 Ferhat Ayaz @@ -39,6 +39,8 @@ #define HEADER_DATE "Date" #define HEADER_ACCEPT "Accept" +#define HEADER_AUTHORIZATION "Authorization" +#define HEADER_WWW_AUTHENTICATE "WWW-Authenticate" #define NHTTPD_ARG_PORT "-NHTTPport" #define NHTTPD_ARG_TERMSIG "-NHTTPtsig" @@ -189,15 +191,6 @@ char *herror_func(herror_t err); char *herror_message(herror_t err); void herror_release(herror_t err); - -/* - string function to compare strings ignoring case - Returns 1 if s1 equals s2 and 0 otherwise. - */ -int strcmpigcase(const char *s1, const char *s2); - - - /* hpairnode_t represents a pair (key, value) pair. This is also a linked list. diff --git a/nanohttp/nanohttp-mime.c b/nanohttp/nanohttp-mime.c index 5ca7df9..10926fe 100755 --- a/nanohttp/nanohttp-mime.c +++ b/nanohttp/nanohttp-mime.c @@ -3,7 +3,7 @@ * | \/ | | | | \/ | | _/ * |_''_| |_| |_''_| |_'/ PARSER * -* $Id: nanohttp-mime.c,v 1.9 2006/01/10 11:29:05 snowdrop Exp $ +* $Id: nanohttp-mime.c,v 1.10 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003-2004 Ferhat Ayaz @@ -25,12 +25,17 @@ * * Email: ferhatayaz@yahoo.com ******************************************************************/ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif - - -#include <nanohttp/nanohttp-mime.h> +#ifdef HAVE_STDIO_H #include <stdio.h> +#endif + +#ifdef HAVE_STRING_H #include <string.h> +#endif /*---------------------------------------------------------------- Buffered Reader. A helper object to read bytes from a source @@ -40,6 +45,7 @@ Buffered Reader. A helper object to read bytes from a source #include <utils/alloc.h> #endif +#include <nanohttp/nanohttp-mime.h> /* ------------------------------------------------------------------ diff --git a/nanohttp/nanohttp-request.c b/nanohttp/nanohttp-request.c index 1bd8a1d..98880f2 100755 --- a/nanohttp/nanohttp-request.c +++ b/nanohttp/nanohttp-request.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-request.c,v 1.9 2006/01/11 10:54:43 snowdrop Exp $ +* $Id: nanohttp-request.c,v 1.10 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -21,16 +21,21 @@ * * Email: ayaz@jprogrammer.net ******************************************************************/ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif -#include <nanohttp/nanohttp-common.h> -#include <nanohttp/nanohttp-request.h> - +#ifdef HAVE_STRING_H #include <string.h> +#endif #ifdef MEM_DEBUG #include <utils/alloc.h> #endif +#include <nanohttp/nanohttp-common.h> +#include <nanohttp/nanohttp-request.h> + /* request stuff */ @@ -197,7 +202,7 @@ _hrequest_parse_header(char *data) } /* Check Content-type */ - tmp = hpairnode_get(req->header, HEADER_CONTENT_TYPE); + tmp = hpairnode_get_ignore_case(req->header, HEADER_CONTENT_TYPE); if (tmp != NULL) req->content_type = content_type_new(tmp); diff --git a/nanohttp/nanohttp-response.c b/nanohttp/nanohttp-response.c index 2253640..cf728e4 100755 --- a/nanohttp/nanohttp-response.c +++ b/nanohttp/nanohttp-response.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-response.c,v 1.7 2006/01/10 11:29:05 snowdrop Exp $ +* $Id: nanohttp-response.c,v 1.8 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003-2004 Ferhat Ayaz @@ -21,16 +21,21 @@ * * Email: ferhatayaz@yahoo.com ******************************************************************/ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif -#include <nanohttp/nanohttp-common.h> -#include <nanohttp/nanohttp-response.h> - +#ifdef HAVE_STRING_H #include <string.h> +#endif #ifdef MEM_DEBUG #include <utils/alloc.h> #endif +#include <nanohttp/nanohttp-common.h> +#include <nanohttp/nanohttp-response.h> + static hresponse_t * hresponse_new() { diff --git a/nanohttp/nanohttp-server.c b/nanohttp/nanohttp-server.c index e063045..19d741a 100644 --- a/nanohttp/nanohttp-server.c +++ b/nanohttp/nanohttp-server.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-server.c,v 1.48 2006/02/08 11:13:14 snowdrop Exp $ +* $Id: nanohttp-server.c,v 1.49 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -21,44 +21,62 @@ * * Email: ayaz@jprogrammer.net ******************************************************************/ -#include <nanohttp/nanohttp-server.h> -#include <nanohttp/nanohttp-ssl.h> - -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <string.h> - #ifdef HAVE_CONFIG_H #include <config.h> #endif -#ifndef WIN32 - -/* According to POSIX 1003.1-2001 */ +#ifdef HAVE_SYS_SELECT_H #include <sys/select.h> +#endif -/* According to earlier standards */ +#ifdef HAVE_SYS_TIME_H #include <sys/time.h> +#endif + +#ifdef HAVE_SYS_TYPES_H #include <sys/types.h> +#endif + +#ifdef HAVE_STDIO_H +#include <stdio.h> +#endif + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#ifdef HAVE_SIGNAL_H +#include <signal.h> +#endif + +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#ifdef HAVE_UNISTD_H #include <unistd.h> +#endif +#ifdef HAVE_PTHREAD_H #include <pthread.h> +#endif -#ifdef HAVE_SOCKET +#ifdef HAVE_SOCKET_H #include <sys/socket.h> #endif -#else - +#ifdef WIN32 #include <process.h> - +#define snprintf(buffer, num, s1, s2) sprintf(buffer, s1,s2) #endif #ifdef MEM_DEBUG #include <utils/alloc.h> #endif +#include "nanohttp-server.h" +#include "nanohttp-base64.h" +#include "nanohttp-ssl.h" typedef struct _conndata { @@ -81,26 +99,21 @@ conndata_t; */ static int _httpd_port = 10000; static int _httpd_max_connections = 20; -#ifdef WIN32 -static int _httpd_max_idle = 120; -#endif static hsocket_t _httpd_socket; static hservice_t *_httpd_services_default = NULL; static hservice_t *_httpd_services_head = NULL; static hservice_t *_httpd_services_tail = NULL; static int _httpd_run = 1; -#ifdef WIN32 -static DWORD _httpd_terminate_signal = CTRL_C_EVENT; -#else -static int _httpd_terminate_signal = SIGINT; -#endif static conndata_t *_httpd_connection; - #ifdef WIN32 +static DWORD _httpd_terminate_signal = CTRL_C_EVENT; +static int _httpd_max_idle = 120; static void WSAReaper (void *x); +#define strncasecmp(s1, s2, num) strncmp(s1, s2, num) #else -sigset_t thrsigset; +static int _httpd_terminate_signal = SIGINT; +static sigset_t thrsigset; #endif #ifdef HAVE_SSL @@ -125,8 +138,7 @@ httpd_init (int argc, char *argv[]) hoption_init_args (argc, argv); - status = hsocket_module_init (); - if (status != H_OK) + if ((status = hsocket_module_init()) != H_OK) return status; /* write argument information */ @@ -171,19 +183,18 @@ httpd_init (int argc, char *argv[]) */ #endif -#ifdef HAVE_SSL - start_ssl(); -#endif - /* create socket */ #ifdef HAVE_SSL SSLCert = hoption_get(HOPTION_SSL_CERT); SSLPass = hoption_get(HOPTION_SSL_PASS); SSLCA = hoption_get(HOPTION_SSL_CA); log_verbose3("SSL: %s %s", SSLCert, SSLCA); - if(SSLCert[0] != '\0'){ - status = hsocket_init_ssl(&_httpd_socket, SSLCert, SSLPass, SSLCA); - } else + if (SSLCert[0] != '\0'){ + + start_ssl(); + status = hsocket_init_ssl(&_httpd_socket, SSLCert, SSLPass, SSLCA); + } + else #endif { status = hsocket_init (&_httpd_socket); @@ -193,9 +204,8 @@ httpd_init (int argc, char *argv[]) { return status; } - status = hsocket_bind (&_httpd_socket, _httpd_port); - return status; + return hsocket_bind (&_httpd_socket, _httpd_port); } /* @@ -205,12 +215,18 @@ httpd_init (int argc, char *argv[]) */ int -httpd_register (const char *ctx, httpd_service func) +httpd_register_secure(const char *ctx, httpd_service func, httpd_auth auth) { hservice_t *service; - service = (hservice_t *) malloc (sizeof (hservice_t)); + if (!(service = (hservice_t *) malloc (sizeof (hservice_t)))) + { + log_error1("malloc failed"); + return -1; + } + service->next = NULL; + service->auth = auth; service->func = func; strcpy (service->ctx, ctx); @@ -229,11 +245,17 @@ httpd_register (const char *ctx, httpd_service func) } int -httpd_register_default (const char *ctx, httpd_service func) +httpd_register(const char *ctx, httpd_service service) +{ + return httpd_register_secure(ctx, service, NULL); +} + +int +httpd_register_default_secure(const char *ctx, httpd_service service, httpd_auth auth) { int ret; - ret = httpd_register(ctx, func); + ret = httpd_register_secure(ctx, service, auth); /* this is broken, but working */ _httpd_services_default = _httpd_services_tail; @@ -242,6 +264,12 @@ httpd_register_default (const char *ctx, httpd_service func) } int +httpd_register_default(const char *ctx, httpd_service service) +{ + return httpd_register_default_secure(ctx, service, NULL); +} + +int httpd_get_port(void) { return _httpd_port; @@ -325,9 +353,8 @@ httpd_send_header (httpd_conn_t * res, int code, const char *text) /* set date */ nw = time (NULL); localtime_r (&nw, &stm); - strftime (buffer, 255, "Date: %a, %d %b %Y %H:%M:%S GMT", &stm); + strftime (buffer, 255, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", &stm); strcat (header, buffer); - strcat (header, "\r\n"); /* set content-type */ /* @@ -343,20 +370,17 @@ httpd_send_header (httpd_conn_t * res, int code, const char *text) // strcat (header, "Connection: close\r\n"); /* add pairs */ - cur = res->header; - while (cur != NULL) + for(cur = res->header; cur; cur = cur->next) { sprintf (buffer, "%s: %s\r\n", cur->key, cur->value); strcat (header, buffer); - cur = cur->next; } /* set end of header */ strcat (header, "\r\n"); /* send header */ - status = hsocket_nsend (res->sock, header, strlen (header)); - if (status != H_OK) + if ((status = hsocket_nsend (res->sock, header, strlen (header))) != H_OK) return status; res->out = http_output_stream_new (res->sock, res->header); @@ -373,9 +397,6 @@ httpd_send_internal_error (httpd_conn_t * conn, const char *errmsg) char buffer[4064]; char buflen[5]; sprintf (buffer, template1, errmsg); -#ifdef WIN32 -#define snprintf(buffer, num, s1, s2) sprintf(buffer, s1,s2) -#endif snprintf (buflen, 5, "%d", strlen (buffer)); httpd_set_header (conn, HEADER_CONTENT_LENGTH, buflen); httpd_send_header (conn, 500, "INTERNAL"); @@ -435,7 +456,7 @@ void httpd_free (httpd_conn_t * conn) { if(!conn) - return; + return; if (conn->out != NULL) http_output_stream_free (conn->out); @@ -464,6 +485,61 @@ do_req_timeout (int signum) #endif } +static int httpd_decode_authorization(const char *value, char **user, char **pass) +{ + + unsigned char *tmp, *tmp2; + + tmp = malloc(strlen(value) * 2); + bzero(tmp, strlen(value) * 2); + + value = index(value, ' '); + value++; + log_debug2("Authorization (base64) = \"%s\"", value); + + base64_decode(value, tmp); + + log_debug2("Authorization (ascii) = \"%s\"", tmp); + + tmp2 = index(tmp, ':'); + *tmp2++ = '\0'; + + *pass = strdup(tmp2); + *user = strdup(tmp); + + free(tmp); + + return 1; +} + +static int httpd_authenticate_request(hrequest_t *req, httpd_auth auth) +{ + char *user, *pass; + char *authorization; + int ret; + + if (!auth) + return 1; + + if (!(authorization = hpairnode_get_ignore_case(req->header, HEADER_AUTHORIZATION))) { + return 0; + } + + if (!httpd_decode_authorization(authorization, &user, &pass)) + { + log_error1("httpd_base64_decode_failed"); + return 0; + } + + if (!(ret = auth(user, pass))) + log_info1("Authentication failed"); + + free(user); + free(pass); + + return ret; +} + /* * ----------------------------------------------------- * FUNCTION: httpd_session_main @@ -515,28 +591,22 @@ httpd_session_main (void *data) while (!done) { log_verbose1 ("starting HTTP request"); - rconn = httpd_new (conn->sock); - status = hrequest_new_from_socket (conn->sock, &req); + rconn = httpd_new (conn->sock); - if (status != H_OK) + if ((status = hrequest_new_from_socket (conn->sock, &req)) != H_OK) { + /* "Request parse error!" */ if (herror_code (status) != HSOCKET_ERROR_SSLCLOSE) { - httpd_send_internal_error (rconn, herror_message (status) /* "Request - parse - error!" */ ); + httpd_send_internal_error (rconn, herror_message (status)); herror_release (status); } done = 1; } else { - char *conn_str = - hpairnode_get_ignore_case (req->header, HEADER_CONNECTION); -#ifdef WIN32 -#define strncasecmp(s1, s2, num) strncmp(s1, s2, num) -#endif + char *conn_str = hpairnode_get_ignore_case (req->header, HEADER_CONNECTION); if (conn_str && strncasecmp (conn_str, "close", 5) == 0) { done = 1; @@ -547,29 +617,34 @@ httpd_session_main (void *data) } httpd_request_print (req); - service = httpd_find_service (req->path); if (service != NULL) { - log_verbose2 ("service '%s' found", req->path); - if (service->func != NULL) - { - service->func (rconn, req); - if (rconn->out - && rconn->out->type == HTTP_TRANSFER_CONNECTION_CLOSE) + log_verbose3 ("service '%s' for '%s' found", service->ctx, req->path); + + if (httpd_authenticate_request(req, service->auth)) { + + if (service->func != NULL) { - log_verbose1 ("Connection close requested"); - done = 1; + service->func (rconn, req); + if (rconn->out && rconn->out->type == HTTP_TRANSFER_CONNECTION_CLOSE) { + log_verbose1 ("Connection close requested"); + done = 1; + } + } + else + { + sprintf (buffer, "service '%s' not registered properly (func == NULL)", req->path); + log_verbose1 (buffer); + httpd_send_internal_error (rconn, buffer); } } - else - { - sprintf (buffer, - "service '%s' not registered properly (func == NULL)", - req->path); - log_verbose1 (buffer); - httpd_send_internal_error (rconn, buffer); - } + else { + + httpd_set_header(rconn, HEADER_WWW_AUTHENTICATE, "Basic realm=\"nanoHTTP\""); + httpd_send_header(rconn, 401, "Unauthorized"); + hsocket_send(conn->sock, "<html><head><title>Unauthorized</title></header><body><h1>Unauthorized</h1></body></html>"); + } } else { @@ -577,9 +652,6 @@ httpd_session_main (void *data) log_verbose1 (buffer); httpd_send_internal_error (rconn, buffer); } - - /* httpd_response_free(res); */ - /* hrequest_free (req); */ } } @@ -588,13 +660,14 @@ httpd_session_main (void *data) conn->sock.sock = 0; hrequest_free (req); httpd_free (rconn); + #ifdef WIN32 CloseHandle ((HANDLE) conn->tid); _endthread (); return 0; #else - pthread_exit (NULL); - return service; + /* pthread_exits automagically */ + return NULL; #endif } @@ -696,14 +769,13 @@ httpd_term (int sig) #endif - /* * ----------------------------------------------------- * FUNCTION: _httpd_register_signal_handler * ----------------------------------------------------- */ static void -_httpd_register_signal_handler () +_httpd_register_signal_handler (void) { log_verbose2 ("registering termination signal handler (SIGNAL:%d)", _httpd_terminate_signal); @@ -716,16 +788,15 @@ _httpd_register_signal_handler () #else signal (_httpd_terminate_signal, httpd_term); #endif -} - - + return; +} /*-------------------------------------------------- FUNCTION: _httpd_wait_for_empty_conn ----------------------------------------------------*/ static conndata_t * -_httpd_wait_for_empty_conn () +_httpd_wait_for_empty_conn (void) { int i; for (i = 0;; i++) @@ -758,25 +829,22 @@ _httpd_start_thread (conndata_t * conn) int err; #ifdef WIN32 - conn->tid = - (HANDLE) _beginthreadex (NULL, 65535, httpd_session_main, conn, 0, &err); + conn->tid = (HANDLE) _beginthreadex (NULL, 65535, httpd_session_main, conn, 0, &err); #else pthread_attr_init (&(conn->attr)); + #ifdef PTHREAD_CREATE_DETACHED pthread_attr_setdetachstate (&(conn->attr), PTHREAD_CREATE_DETACHED); #endif + pthread_sigmask (SIG_BLOCK, &thrsigset, NULL); - err = - pthread_create (&(conn->tid), &(conn->attr), httpd_session_main, conn); + err = pthread_create (&(conn->tid), &(conn->attr), httpd_session_main, conn); if (err) - { log_error2 ("Error creating thread: ('%d')", err); - } #endif } - /* * ----------------------------------------------------- * FUNCTION: httpd_run @@ -784,28 +852,25 @@ _httpd_start_thread (conndata_t * conn) */ herror_t -httpd_run () +httpd_run (void) { herror_t err; conndata_t *conn; fd_set fds; struct timeval timeout; - log_verbose1 ("starting run routine"); timeout.tv_sec = 1; timeout.tv_usec = 0; -#ifdef WIN32 -#else + +#ifndef WIN32 sigemptyset (&thrsigset); sigaddset (&thrsigset, SIGALRM); #endif - /* listen to port */ - err = hsocket_listen (_httpd_socket); - if (err != H_OK) + if ((err = hsocket_listen (_httpd_socket)) != H_OK) { log_error2 ("httpd_run(): '%d'", herror_message (err)); return err; @@ -816,14 +881,12 @@ httpd_run () _httpd_register_signal_handler (); /* make the socket non blocking */ - err = hsocket_block (_httpd_socket, 0); - if (err != H_OK) + if ((err = hsocket_block (_httpd_socket, 0)) != H_OK) { log_error2 ("httpd_run(): '%s'", herror_message (err)); return err; } - while (_httpd_run) { /* Get an empty connection struct */ @@ -870,15 +933,14 @@ httpd_run () /* Accept a socket */ err = hsocket_accept (_httpd_socket, &(conn->sock)); if (err != H_OK - /* TODO (#1#) is this check neccessary? - && herror_code (err) == SSL_ERROR_INIT*/ - ) + /* TODO (#1#) is this check neccessary? + && herror_code (err) == SSL_ERROR_INIT*/ + ) { hsocket_close (conn->sock); - conn->sock.sock = -1; -#ifdef HAVE_SSL - conn->sock.ssl = NULL; -#endif + + hsocket_init(&(conn->sock)); + log_error1 (herror_message (err)); continue; } @@ -896,7 +958,7 @@ httpd_run () } void -httpd_destroy () +httpd_destroy (void) { hservice_t *tmp, *cur = _httpd_services_head; @@ -908,6 +970,8 @@ httpd_destroy () } hsocket_module_destroy (); + + return; } #ifdef WIN32 @@ -969,8 +1033,7 @@ httpd_get_postdata (httpd_conn_t * conn, hrequest_t * req, long *received, if (req->method == HTTP_REQUEST_POST) { - content_length_str = - hpairnode_get_ignore_case (req->header, HEADER_CONTENT_LENGTH); + content_length_str = hpairnode_get_ignore_case (req->header, HEADER_CONTENT_LENGTH); if (content_length_str != NULL) content_length = atol (content_length_str); @@ -1020,6 +1083,8 @@ _httpd_mime_get_boundary (httpd_conn_t * conn, char *dest) { sprintf (dest, "---=.Part_NH_%p", conn); log_verbose2 ("boundary= \"%s\"", dest); + + return; } @@ -1028,23 +1093,14 @@ _httpd_mime_get_boundary (httpd_conn_t * conn, char *dest) Returns: H_OK or error flag */ herror_t -httpd_mime_send_header (httpd_conn_t * conn, - const char *related_start, - const char *related_start_info, - const char *related_type, int code, const char *text) +httpd_mime_send_header (httpd_conn_t * conn, const char *related_start, const char *related_start_info, const char *related_type, int code, const char *text) { char buffer[300]; char temp[250]; char boundary[250]; - /* - Set Content-type Set multipart/related parameter type=..; start=.. ; - start-info= ..; boundary=... - - */ - /* - using sprintf instead of snprintf because visual c does not support - snprintf */ + /* Set Content-type Set multipart/related parameter type=..; start=.. ; start-info= ..; boundary=... + using sprintf instead of snprintf because visual c does not support snprintf */ sprintf (buffer, "multipart/related;"); @@ -1081,9 +1137,7 @@ httpd_mime_send_header (httpd_conn_t * conn, with next part */ herror_t -httpd_mime_next (httpd_conn_t * conn, - const char *content_id, - const char *content_type, const char *transfer_encoding) +httpd_mime_next (httpd_conn_t * conn, const char *content_id, const char *content_type, const char *transfer_encoding) { herror_t status; char buffer[512]; @@ -1094,9 +1148,7 @@ httpd_mime_next (httpd_conn_t * conn, sprintf (buffer, "\r\n--%s\r\n", boundary); /* Send boundary */ - status = http_output_stream_write (conn->out, - (const byte_t *) buffer, - strlen (buffer)); + status = http_output_stream_write (conn->out, (const byte_t *) buffer, strlen (buffer)); if (status != H_OK) return status; @@ -1109,9 +1161,7 @@ httpd_mime_next (httpd_conn_t * conn, HEADER_CONTENT_ID, content_id ? content_id : "<content-id-not-set>"); - status = http_output_stream_write (conn->out, - (const byte_t *) buffer, - strlen (buffer)); + status = http_output_stream_write (conn->out, (const byte_t *) buffer, strlen (buffer)); return status; } @@ -1121,22 +1171,17 @@ httpd_mime_next (httpd_conn_t * conn, with next part */ herror_t -httpd_mime_send_file (httpd_conn_t * conn, - const char *content_id, - const char *content_type, - const char *transfer_encoding, const char *filename) +httpd_mime_send_file (httpd_conn_t * conn, const char *content_id, const char *content_type, const char *transfer_encoding, const char *filename) { - herror_t status; - FILE *fd = fopen (filename, "rb"); byte_t buffer[MAX_FILE_BUFFER_SIZE]; + herror_t status; + FILE *fd; size_t size; - if (fd == NULL) - return herror_new ("httpd_mime_send_file", FILE_ERROR_OPEN, - "Can not open file '%d'", filename); + if ((fd = fopen (filename, "rb")) == NULL) + return herror_new ("httpd_mime_send_file", FILE_ERROR_OPEN, "Can not open file '%d'", filename); - status = - httpd_mime_next (conn, content_id, content_type, transfer_encoding); + status = httpd_mime_next (conn, content_id, content_type, transfer_encoding); if (status != H_OK) { fclose (fd); @@ -1149,8 +1194,7 @@ httpd_mime_send_file (httpd_conn_t * conn, if (size == -1) { fclose (fd); - return herror_new ("httpd_mime_send_file", FILE_ERROR_READ, - "Can not read from file '%d'", filename); + return herror_new ("httpd_mime_send_file", FILE_ERROR_READ, "Can not read from file '%d'", filename); } status = http_output_stream_write (conn->out, buffer, size); @@ -1181,9 +1225,7 @@ httpd_mime_end (httpd_conn_t * conn) sprintf (buffer, "\r\n--%s--\r\n\r\n", boundary); /* Send boundary */ - status = http_output_stream_write (conn->out, - (const byte_t *) buffer, - strlen (buffer)); + status = http_output_stream_write (conn->out, (const byte_t *) buffer, strlen (buffer)); if (status != H_OK) return status; diff --git a/nanohttp/nanohttp-server.h b/nanohttp/nanohttp-server.h index ccafe8f..4c50d23 100644 --- a/nanohttp/nanohttp-server.h +++ b/nanohttp/nanohttp-server.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-server.h,v 1.12 2006/02/08 11:13:14 snowdrop Exp $ + * $Id: nanohttp-server.h,v 1.13 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -45,7 +45,7 @@ typedef struct httpd_conn Service callback */ typedef void (*httpd_service) (httpd_conn_t *, hrequest_t *); - +typedef int (*httpd_auth) (const char *user, const char *password); /* * Service representation object @@ -54,6 +54,7 @@ typedef struct tag_hservice { char ctx[255]; httpd_service func; + httpd_auth auth; struct tag_hservice *next; } hservice_t; @@ -63,7 +64,13 @@ typedef struct tag_hservice Begin httpd_* function set */ herror_t httpd_init(int argc, char *argv[]); + int httpd_register(const char *ctx, httpd_service service); +int httpd_register_secure(const char *ctx, httpd_service service, httpd_auth auth); + +int httpd_register_default(const char *ctx, httpd_service service); +int httpd_register_secure_default(const char *ctx, httpd_service service, httpd_auth auth); + herror_t httpd_run(); void httpd_destroy(); diff --git a/nanohttp/nanohttp-socket.c b/nanohttp/nanohttp-socket.c index e2c9312..cdcfea0 100644 --- a/nanohttp/nanohttp-socket.c +++ b/nanohttp/nanohttp-socket.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-socket.c,v 1.48 2006/02/09 13:47:21 mrcsys Exp $ +* $Id: nanohttp-socket.c,v 1.49 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -21,25 +21,8 @@ * * Email: ferhatayaz@yahoo.com ******************************************************************/ -#include <nanohttp/nanohttp-socket.h> -#include <nanohttp/nanohttp-common.h> -#include <nanohttp/nanohttp-ssl.h> - -#ifdef WIN32 -#include "wsockcompat.h" -#include <winsock2.h> -#include <process.h> - -#ifndef __MINGW32__ -typedef int ssize_t; -#endif - -#else -#include <fcntl.h> -#endif - #ifdef HAVE_CONFIG_H -#include "config.h" +#include <config.h> #endif #ifdef HAVE_SYS_TYPES_H @@ -50,7 +33,7 @@ typedef int ssize_t; #include <sys/socket.h> #endif -#ifndef WIN32 +#ifdef HAVE_NETINET_IN_H #include <netinet/in.h> #endif @@ -58,6 +41,10 @@ typedef int ssize_t; #include <arpa/inet.h> #endif +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + #ifdef HAVE_NETDB_H #include <netdb.h> #endif @@ -66,20 +53,39 @@ typedef int ssize_t; #include <unistd.h> #endif +#ifdef HAVE_STDIO_H #include <stdio.h> -#include <errno.h> -#include <string.h> +#endif -#ifdef MEM_DEBUG -#include <utils/alloc.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> #endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif #ifdef WIN32 +#include "wsockcompat.h" +#include <winsock2.h> +#include <process.h> + +#ifndef __MINGW32__ +typedef int ssize_t; +#endif + #undef errno #define errno WSAGetLastError() + #endif +#ifdef MEM_DEBUG +#include <utils/alloc.h> +#endif + +#include "nanohttp-socket.h" +#include "nanohttp-common.h" +#include "nanohttp-ssl.h" #ifdef HAVE_SSL /*SSL_CTX *SSLctx = NULL; @@ -100,10 +106,12 @@ hsocket_module_init() #ifdef WIN32 struct WSAData info; WSAStartup(MAKEWORD(2, 2), &info); +#endif + +#ifdef HAVE_SSL + start_ssl(); +#endif -#else /* */ - /* nothing to init for unix sockets */ -#endif /* */ return H_OK; } @@ -115,10 +123,9 @@ hsocket_module_destroy() { #ifdef WIN32 WSACleanup(); +#endif -#else /* */ - /* nothing to destroy for unix sockets */ -#endif /* */ + return; } /*-------------------------------------------------- @@ -128,13 +135,9 @@ herror_t hsocket_init(hsocket_t * sock) { log_verbose1("Starting hsocket init"); - /* just set the descriptor to -1 */ - sock->sock = -1; -#ifdef HAVE_SSL - sock->ssl = NULL; - sock->sslCtx = NULL; -#endif + bzero(sock, sizeof(hsocket_t)); + sock->sock = -1; return H_OK; } @@ -172,6 +175,7 @@ void hsocket_free(hsocket_t sock) { /* nothing to free for unix sockets */ + return; } /*-------------------------------------------------- @@ -185,14 +189,12 @@ hsocket_open(hsocket_t * dsock, const char *hostname, int port) struct sockaddr_in address; struct hostent *host; - sock.sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock.sock <= 0) + if ((sock.sock = socket(AF_INET, SOCK_STREAM, 0)) <= 0) return herror_new("hsocket_open", HSOCKET_ERROR_CREATE, "Socket error: %d", errno); /* Get host data */ - host = gethostbyname(hostname); - if (host == NULL) + if (!(host = gethostbyname(hostname))) return herror_new("hsocket_open", HSOCKET_ERROR_GET_HOSTNAME, "Socket error: %d", errno); @@ -218,10 +220,17 @@ hsocket_open(hsocket_t * dsock, const char *hostname, int port) } else { + herror_t status; log_verbose1("Using HTTPS"); dsock->ssl = init_ssl(dsock->sslCtx, sock.sock, SSL_CLIENT); + if ((status = hsocket_block(*dsock, dsock->block)) != H_OK) + { + log_error1("Cannot make socket non-blocking"); + return status; + } } #endif + return H_OK; } @@ -236,8 +245,7 @@ hsocket_bind(hsocket_t * dsock, int port) int opt = 1; /* create socket */ - sock.sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock.sock == -1) + if ((sock.sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { log_error3("Can not create socket: '%s'", "Socket error: %d", errno); return herror_new("hsocket_bind", HSOCKET_ERROR_CREATE, @@ -330,45 +338,6 @@ hsocket_listen(hsocket_t sock) return H_OK; } -#if 0 -static void -_hsocket_wait_until_receive(hsocket_t sock) -{ - fd_set fds; - struct timeval timeout; - - - timeout.tv_sec = 1; - timeout.tv_usec = 0; - - while (1) - { - log_verbose1("waiting until receive mode"); - /* zero and set file descriptior */ - FD_ZERO(&fds); - FD_SET(sock, &fds); - - /* select socket descriptor */ - switch (select(sock + 1, &fds, NULL, NULL, &timeout)) - { - case 0: - /* descriptor is not ready */ - continue; - case -1: - /* got a signal? */ - continue; - default: - /* no nothing */ - break; - } - if (FD_ISSET(sock, &fds)) - { - break; - } - } -} -#endif - /*-------------------------------------------------- FUNCTION: hsocket_close ----------------------------------------------------*/ @@ -390,11 +359,9 @@ hsocket_close(hsocket_t sock) #ifdef WIN32 /* shutdown(sock,SD_RECEIVE); */ - shutdown(sock.sock, SD_SEND); - while (recv(sock.sock, junk, sizeof(junk), 0) > 0) - { - }; + while (recv(sock.sock, junk, sizeof(junk), 0) > 0) ; + /* nothing */ closesocket(sock.sock); #else @@ -405,40 +372,21 @@ hsocket_close(hsocket_t sock) { log_verbose1("Closing SSL"); ssl_cleanup(sock.ssl); - shutdown(sock.sock, SHUT_RDWR); - while (recv(sock.sock, junk, sizeof(junk), 0) > 0) - { - }; - close(sock.sock); - } - else - { -#endif - shutdown(sock.sock, SHUT_RDWR); - while (recv(sock.sock, junk, sizeof(junk), 0) > 0) - { - }; - close(sock.sock); -#ifdef HAVE_SSL + sock.ssl = NULL; } #endif + + shutdown(sock.sock, SHUT_RDWR); + while (recv(sock.sock, junk, sizeof(junk), 0) > 0) ; + /* nothing */ + close(sock.sock); #endif + log_verbose1("socket closed"); -} -#if 0 -static int -_test_send_to_file(const char *filename, const byte_t * bytes, int n) -{ - int size; - FILE *f = fopen(filename, "ab"); - if (!f) - f = fopen(filename, "wb"); - size = fwrite(bytes, 1, n, f); - fclose(f); - return size; + return; } -#endif + /*-------------------------------------------------- FUNCTION: hsocket_send ----------------------------------------------------*/ @@ -448,12 +396,8 @@ hsocket_nsend(hsocket_t sock, const byte_t * bytes, int n) int size; int total = 0; - log_verbose1("Starting to send"); -#ifdef HAVE_SSL - if (sock.sock <= 0 && !sock.ssl) -#else + log_verbose2("Starting to send on sock=%p", &sock); if (sock.sock <= 0) -#endif return herror_new("hsocket_nsend", HSOCKET_ERROR_NOT_INITIALIZED, "Called hsocket_listen() before initializing!"); @@ -463,6 +407,7 @@ hsocket_nsend(hsocket_t sock, const byte_t * bytes, int n) while (1) { #ifdef HAVE_SSL + log_verbose2("ssl = %p", sock.ssl); if (sock.ssl) { size = SSL_write(sock.ssl, bytes + total, n); @@ -542,24 +487,27 @@ hsocket_read(hsocket_t sock, byte_t * buffer, int total, int force, FD_SET(sock.sock, &fds); timeout.tv_sec = 10; timeout.tv_usec = 0; -#ifdef WIN32 -#else +#ifndef WIN32 fcntl(sock.sock, F_SETFL, O_NONBLOCK); #endif /* log_verbose1("START READ LOOP"); do{ log_verbose2("DEBUG A %d",i); */ status = SSL_read(sock.ssl, &buffer[totalRead], total - totalRead); - log_verbose2("DEBUG SSL_read %d",status); - if (SSL_get_error(sock.ssl, status) == SSL_ERROR_ZERO_RETURN || - SSL_get_error(sock.ssl, status) == SSL_ERROR_SSL || - SSL_get_error(sock.ssl, status) == SSL_ERROR_SYSCALL || - SSL_get_error(sock.ssl, status) == SSL_ERROR_SSL || - SSL_get_shutdown(sock.ssl) == SSL_RECEIVED_SHUTDOWN ) - { - log_verbose1("SSL Error"); - return herror_new("hsocket_read", HSOCKET_ERROR_SSLCLOSE, "SSL Error"); + log_verbose2("DEBUG SSL_read %d",status); + + switch (SSL_get_error(sock.ssl, status)) { + case SSL_ERROR_ZERO_RETURN: + case SSL_ERROR_SSL: + case SSL_ERROR_SYSCALL: + log_verbose1("SSL Error"); + return herror_new("hsocket_read", HSOCKET_ERROR_SSLCLOSE, "SSL Error"); + } + if (SSL_get_shutdown(sock.ssl) == SSL_RECEIVED_SHUTDOWN) { + log_verbose1("SSL shutdown error"); + return herror_new("hsocket_read", HSOCKET_ERROR_SSLCLOSE, "SSL shutdown error"); } + if (status < 1) { int ret = select(sock.sock + 1, &fds, NULL, NULL, &timeout); @@ -588,8 +536,7 @@ hsocket_read(hsocket_t sock, byte_t * buffer, int total, int force, buffer[totalRead], SSL_get_error(sock.ssl, status));*/ } /* } while( SSL_get_error(sock.ssl, status) == SSL_ERROR_WANT_READ); */ -#ifdef WIN32 -#else +#ifndef WIN32 fcntl(sock.sock, F_SETFL, 0); #endif } @@ -618,14 +565,6 @@ hsocket_read(hsocket_t sock, byte_t * buffer, int total, int force, } #else } -/* - switch (errno) { - case EWOULDBLOCK: - case EALREADY: - case EINPROGRESS: - return true; - } -*/ #ifdef HAVE_SSL if (sock.ssl && status < 1) diff --git a/nanohttp/nanohttp-socket.h b/nanohttp/nanohttp-socket.h index e0228e9..3c4529d 100644 --- a/nanohttp/nanohttp-socket.h +++ b/nanohttp/nanohttp-socket.h @@ -1,5 +1,5 @@ /****************************************************************** - * $Id: nanohttp-socket.h,v 1.21 2006/01/11 10:54:43 snowdrop Exp $ + * $Id: nanohttp-socket.h,v 1.22 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003 Ferhat Ayaz @@ -53,6 +53,7 @@ typedef struct hsocket_t #else int sock; #endif + int block; } hsocket_t; /* end of socket definition */ diff --git a/nanohttp/nanohttp-ssl.c b/nanohttp/nanohttp-ssl.c index b0f3aa2..85c8ca2 100644 --- a/nanohttp/nanohttp-ssl.c +++ b/nanohttp/nanohttp-ssl.c @@ -24,12 +24,18 @@ /* Enter only if --with-ssl was specified to the configure script */ #ifdef HAVE_SSL +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_SYS_TYPES_H #include <sys/types.h> -#include <openssl/rand.h> -#include <openssl/err.h> -#ifndef WIN32 +#endif + +#ifdef HAVE_NETINET_IN_H #include <netinet/in.h> #endif + #if HAVE_INTTYPES_H #include <inttypes.h> #else @@ -40,24 +46,44 @@ typedef unsigned int uint32_t; # endif #endif +#ifdef HAVE_STRING_H #include <string.h> +#endif + +#ifdef HAVE_STDLIB_H #include <stdlib.h> +#endif + +#ifdef HAVE_TIME_H #include <time.h> +#endif +#ifdef HAVE_FCNTL_H #include <fcntl.h> +#endif -#include "nanohttp-ssl.h" -#include "nanohttp-common.h" -#include "nanohttp-socket.h" - +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif #ifdef WIN32 #include <io.h> typedef unsigned int uint32_t; #else -#include <unistd.h> #endif +#ifdef HAVE_OPENSSL_RAND_H +#include <openssl/rand.h> +#endif + +#ifdef HAVE_OPENSSL_ERR_H +#include <openssl/err.h> +#endif + +#include "nanohttp-common.h" +#include "nanohttp-socket.h" +#include "nanohttp-ssl.h" + #define MAXCHUNK 1024 #define HEADER_LEN 5 char HEADER[HEADER_LEN] = { 186, 84, 202, 86, 224 }; @@ -126,6 +152,18 @@ verify_sn (X509 * cert, int who, int nid, char *str) } } +#ifdef NOUSER_VERIFY +static int +user_verify (X509 * cert) +{ + // TODO: Make sure that the client is providing a client cert, + // or that the Module is providing the Module cert + /* connect to anyone */ + log_verbose1 ("Validating certificate."); + return 1; +} +#endif + static int verify_cb (int prev_ok, X509_STORE_CTX * ctx) { @@ -152,26 +190,17 @@ verify_cb (int prev_ok, X509_STORE_CTX * ctx) #endif } -#ifdef NOUSER_VERIFY -int -user_verify (X509 * cert) -{ - // TODO: Make sure that the client is providing a client cert, - // or that the Module is providing the Module cert - /* connect to anyone */ - log_verbose1 ("Validating certificate."); - return 1; -} -#endif - void -start_ssl( void ){ +start_ssl( void ) +{ /* Global system initialization */ log_verbose1 ("Initializing library"); SSL_library_init (); SSL_load_error_strings (); ERR_load_crypto_strings (); OpenSSL_add_ssl_algorithms (); + + return; } SSL_CTX * diff --git a/nanohttp/nanohttp-stream.c b/nanohttp/nanohttp-stream.c index c8ba216..8908e54 100755 --- a/nanohttp/nanohttp-stream.c +++ b/nanohttp/nanohttp-stream.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-stream.c,v 1.9 2006/01/10 11:29:05 snowdrop Exp $ +* $Id: nanohttp-stream.c,v 1.10 2006/02/18 20:14:36 snowdrop Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2003-2004 Ferhat Ayaz @@ -21,14 +21,20 @@ * * Email: ferhatayaz@yahoo.com ******************************************************************/ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif -#include <nanohttp/nanohttp-stream.h> - +#ifdef HAVE_STRING_H #include <string.h> +#endif #ifdef MEM_DEBUG #include <utils/alloc.h> #endif + +#include "nanohttp-stream.h" + void _log_str(char *fn, char *str, int size) { @@ -416,7 +422,7 @@ _http_input_stream_file_read(http_input_stream_t * stream, byte_t * dest, int http_input_stream_is_ready(http_input_stream_t * stream) { - /* paranoya check */ + /* paranoia check */ if (stream == NULL) return 0; |