summaryrefslogtreecommitdiffstats
path: root/nanohttp
diff options
context:
space:
mode:
authorGravatar snowdrop2006-02-18 20:14:35 +0000
committerGravatar snowdrop2006-02-18 20:14:35 +0000
commitd45b4bc26f330d2ce29e4a06ffdae74d82e8b43b (patch)
treed4b985c32b1246f5cde7c294b6654b27f71cc81b /nanohttp
parent29b034ec9c827c7311e69fcb5765ef4e43478c29 (diff)
downloadcsoap-d45b4bc26f330d2ce29e4a06ffdae74d82e8b43b.tar.gz
csoap-d45b4bc26f330d2ce29e4a06ffdae74d82e8b43b.tar.bz2
added basic authentication and SOAP-Header capabilities for request objects
Thanks to Heiko Ronsdorf
Diffstat (limited to 'nanohttp')
-rw-r--r--nanohttp/Makefile.am2
-rw-r--r--nanohttp/nanohttp-client.c393
-rw-r--r--nanohttp/nanohttp-client.h3
-rw-r--r--nanohttp/nanohttp-common.c84
-rw-r--r--nanohttp/nanohttp-common.h13
-rwxr-xr-xnanohttp/nanohttp-mime.c14
-rwxr-xr-xnanohttp/nanohttp-request.c15
-rwxr-xr-xnanohttp/nanohttp-response.c13
-rw-r--r--nanohttp/nanohttp-server.c354
-rw-r--r--nanohttp/nanohttp-server.h11
-rw-r--r--nanohttp/nanohttp-socket.c217
-rw-r--r--nanohttp/nanohttp-socket.h3
-rw-r--r--nanohttp/nanohttp-ssl.c71
-rwxr-xr-xnanohttp/nanohttp-stream.c14
14 files changed, 515 insertions, 692 deletions
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;