Merged httpd from TI Luminary: added basic SSI and CGI support, added support for dynamic HTTP header generation

This commit is contained in:
goldsimon 2010-02-17 21:19:17 +00:00
parent 3e130e4f7f
commit 4ec673b17d
6 changed files with 1545 additions and 296 deletions

View File

@ -33,30 +33,100 @@
#include "fs.h"
#include "fsdata.h"
#include "fsdata.c"
#include <string.h>
/** Search for a file by its full name and return pointer and length if found.
*
* @param name full file name as passed in HTTP request
* @param file structure that must be allocated by caller and will be filled in
* by the function if the filename was found.
* @return 1 if the file was found, 0 if the file was not found
*/
int
fs_open(const char *name, struct fs_file *file)
{
const struct fsdata_file *f;
for (f = FS_ROOT; f != NULL; f = f->next) {
if (!strcmp(name, (const char*)f->name)) {
file->data = f->data;
file->len = f->len;
#if HTTPD_SUPPORT_DYNAMIC_PAGES
file->includes_http_header = f->includes_http_header;
/*-----------------------------------------------------------------------------------*/
/* Define the number of open files that we can support. */
#ifndef LWIP_MAX_OPEN_FILES
#define LWIP_MAX_OPEN_FILES 10
#endif
return 1;
/* Define the file system memory allocation structure. */
struct fs_table {
struct fs_file file;
int inuse;
};
/* Allocate file system memory */
struct fs_table fs_memory[LWIP_MAX_OPEN_FILES];
/*-----------------------------------------------------------------------------------*/
static struct fs_file *
fs_malloc(void)
{
int i;
for(i = 0; i < LWIP_MAX_OPEN_FILES; i++) {
if(fs_memory[i].inuse == 0) {
fs_memory[i].inuse = 1;
return(&fs_memory[i].file);
}
}
return 0;
return(NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
fs_free(struct fs_file *file)
{
int i;
for(i = 0; i < LWIP_MAX_OPEN_FILES; i++) {
if(&fs_memory[i].file == file) {
fs_memory[i].inuse = 0;
break;
}
}
return;
}
/*-----------------------------------------------------------------------------------*/
struct fs_file *
fs_open(const char *name)
{
struct fs_file *file;
const struct fsdata_file *f;
file = fs_malloc();
if(file == NULL) {
return NULL;
}
for(f = FS_ROOT; f != NULL; f = f->next) {
if (!strcmp(name, (char *)f->name)) {
file->data = (const char *)f->data;
file->len = f->len;
file->index = f->len;
file->pextension = NULL;
return file;
}
}
fs_free(file);
return NULL;
}
/*-----------------------------------------------------------------------------------*/
void
fs_close(struct fs_file *file)
{
fs_free(file);
}
/*-----------------------------------------------------------------------------------*/
int
fs_read(struct fs_file *file, char *buffer, int count)
{
int read;
if(file->index == file->len) {
return -1;
}
read = file->len - file->index;
if(read > count) {
read = count;
}
memcpy(buffer, (file->data + file->index), read);
file->index += read;
return(read);
}

View File

@ -32,21 +32,17 @@
#ifndef __FS_H__
#define __FS_H__
/** Support dynamically created pages (free contents after sending) */
#ifndef HTTPD_SUPPORT_DYNAMIC_PAGES
#define HTTPD_SUPPORT_DYNAMIC_PAGES 1
#endif
struct fs_file {
const unsigned char *data;
const char *data;
int len;
#if HTTPD_SUPPORT_DYNAMIC_PAGES
u8_t includes_http_header;
#endif /* HTTPD_SUPPORT_DYNAMIC_PAGES */
int index;
void *pextension;
};
/* file must be allocated by caller and will be filled in
by the function. */
int fs_open(const char *name, struct fs_file *file);
struct fs_file * fs_open(const char *name);
void fs_close(struct fs_file *file);
int fs_read(struct fs_file *file, char *buffer, int count);
#endif /* __FS_H__ */

View File

@ -37,9 +37,6 @@ struct fsdata_file {
const unsigned char *name;
const unsigned char *data;
int len;
u8_t includes_http_header;
u8_t content_type;
u8_t http_response;
};
#endif /* __FSDATA_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
@ -11,71 +11,143 @@
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
*
* Author: Adam Dunkels <adam@sics.se>
*
* This version of the file has been modified by Texas Instruments to offer
* simple server-side-include (SSI) and Common Gateway Interface (CGI)
* capability.
*/
#ifndef __HTTPD_H__
#define __HTTPD_H__
void httpd_init(void);
typedef enum file_type_enum
#ifndef LWIP_HTTPD_CGI
#define LWIP_HTTPD_CGI 0
#endif
#ifndef LWIP_HTTPD_SSI
#define LWIP_HTTPD_SSI 0
#endif
#if LWIP_HTTPD_CGI
/*
* Function pointer for a CGI script handler.
*
* This function is called each time the HTTPD server is asked for a file
* whose name was previously registered as a CGI function using a call to
* http_set_cgi_handler. The iIndex parameter provides the index of the
* CGI within the ppcURLs array passed to http_set_cgi_handler. Parameters
* pcParam and pcValue provide access to the parameters provided along with
* the URI. iNumParams provides a count of the entries in the pcParam and
* pcValue arrays. Each entry in the pcParam array contains the name of a
* parameter with the corresponding entry in the pcValue array containing the
* value for that parameter. Note that pcParam may contain multiple elements
* with the same name if, for example, a multi-selection list control is used
* in the form generating the data.
*
* The function should return a pointer to a character string which is the
* path and filename of the response that is to be sent to the connected
* browser, for example "/thanks.htm" or "/response/error.ssi".
*
* The maximum number of parameters that will be passed to this function via
* iNumParams is defined by LWIP_HTTPD_MAX_CGI_PARAMETERS. Any parameters in the incoming
* HTTP request above this number will be discarded.
*
* Requests intended for use by this CGI mechanism must be sent using the GET
* method (which encodes all parameters within the URI rather than in a block
* later in the request). Attempts to use the POST method will result in the
* request being ignored.
*
*/
typedef char *(*tCGIHandler)(int iIndex, int iNumParams, char *pcParam[],
char *pcValue[]);
/*
* Structure defining the base filename (URL) of a CGI and the associated
* function which is to be called when that URL is requested.
*/
typedef struct
{
HTML, /* .htm(l) */
GIF, /* .gif */
PNG, /* .png */
JPEG, /* .jp(e)g */
OCTET_STREAM, /* .bin, .class, ??? */
REALAUDIO, /* .ra(m) */
TEXT, /* .txt */
JAVASCRIPT, /* .js */
CSS /* .css */
}
CONTENT_TYPE;
const char *pcCGIName;
tCGIHandler pfnCGIHandler;
} tCGI;
static const char *httpContentType_header[] = {
"Content-Type: text/html\r\n",
"Content-Type: image/gif\r\n",
"Content-Type: image/png\r\n",
"Content-Type: image/jpeg\r\n",
"Content-Type: application/octet-stream\r\n",
"Content-Type: audio/x-pn-realaudio\r\n",
"Content-Type: text/plain\r\n",
"Content-Type: application/x-javascript\r\n",
"Content-Type: text/css\r\n",
NULL
};
void http_set_cgi_handlers(const tCGI *pCGIs, int iNumHandlers);
typedef enum getResponseEnum
{
HTTP_200_OK,
HTTP_404_NOT_FOUND
} HTTP_RESPONSE;
static const char *httpResponseText_1_0[] = {
"HTTP/1.0 200 OK\r\n",
"HTTP/1.0 404 File not found\r\n"
};
static const char *httpResponseText_1_1[] = {
"HTTP/1.1 200 OK\r\n",
"HTTP/1.1 404 File not found\r\n"
};
static const char *httpContentLength = "Content-Length: ";
static const char *httpConnectionClose = "Connection: close\r\n";
/* The maximum number of parameters that the CGI handler can be sent. */
#ifndef LWIP_HTTPD_MAX_CGI_PARAMETERS
#define LWIP_HTTPD_MAX_CGI_PARAMETERS 16
#endif
#endif /* LWIP_HTTPD_CGI */
#if LWIP_HTTPD_SSI
/*
* Function pointer for the SSI tag handler callback.
*
* This function will be called each time the HTTPD server detects a tag of the
* form <!--#name--> in a .shtml, .ssi or .shtm file where "name" appears as
* one of the tags supplied to http_set_ssi_handler in the ppcTags array. The
* returned insert string, which will be appended after the the string
* "<!--#name-->" in file sent back to the client,should be written to pointer
* pcInsert. iInsertLen contains the size of the buffer pointed to by
* pcInsert. The iIndex parameter provides the zero-based index of the tag as
* found in the ppcTags array and identifies the tag that is to be processed.
*
* The handler returns the number of characters written to pcInsert excluding
* any terminating NULL or a negative number to indicate a failure (tag not
* recognized, for example).
*
* Note that the behavior of this SSI mechanism is somewhat different from the
* "normal" SSI processing as found in, for example, the Apache web server. In
* this case, the inserted text is appended following the SSI tag rather than
* replacing the tag entirely. This allows for an implementation that does not
* require significant additional buffering of output data yet which will still
* offer usable SSI functionality. One downside to this approach is when
* attempting to use SSI within JavaScript. The SSI tag is structured to
* resemble an HTML comment but this syntax does not constitute a comment
* within JavaScript and, hence, leaving the tag in place will result in
* problems in these cases. To work around this, any SSI tag which needs to
* output JavaScript code must do so in an encapsulated way, sending the whole
* HTML <script>...</script> section as a single include.
*/
typedef u16_t (*tSSIHandler)(int iIndex, char *pcInsert, int iInsertLen);
void http_set_ssi_handler(tSSIHandler pfnSSIHandler,
const char **ppcTags, int iNumTags);
/* The maximum length of the string comprising the tag name */
#ifndef LWIP_HTTPD_MAX_TAG_NAME_LEN
#define LWIP_HTTPD_MAX_TAG_NAME_LEN 8
#endif
/* The maximum length of string that can be returned to replace any given tag */
#ifndef LWIP_HTTPD_MAX_TAG_INSERT_LEN
#define LWIP_HTTPD_MAX_TAG_INSERT_LEN 192
#endif
#endif /* LWIP_HTTPD_SSI */
void httpd_init(void);

View File

@ -55,8 +55,9 @@
#endif
typedef unsigned char u8_t;
#include "../httpd.h"
/* define this to get the header variables we use to build HTTP headers */
#define LWIP_HTTPD_DYNAMIC_HEADERS 1
#include "../httpd.c"
/** (Your server name here) */
const char *serverID =
@ -303,20 +304,22 @@ int process_file(FILE *data_file, FILE *struct_file, const char *filename)
int file_write_http_header(FILE *data_file, const char *filename, int file_size)
{
int i = 0;
enum getResponseEnum response_type = HTTP_200_OK;
enum file_type_enum file_type;
const char **httpResponseText = httpResponseText_1_0;
int response_type = HTTP_HDR_OK;
int file_type;
const char **httpResponseText = g_psHTTPHeaderStrings /*httpResponseText_1_0*/;
const char *cur_string;
size_t cur_len;
int written = 0;
#ifdef HTTP_11
if (useHttp11) {
httpResponseText = httpResponseText_1_1;
}
#endif
fprintf(data_file, NEWLINE "/* HTTP header */");
if (strstr(filename, "404")) {
response_type = HTTP_404_NOT_FOUND;
response_type = HTTP_HDR_NOT_FOUND;
}
cur_string = httpResponseText[response_type];
cur_len = strlen(cur_string);
@ -331,30 +334,31 @@ int file_write_http_header(FILE *data_file, const char *filename, int file_size)
i = 0;
if (strstr(filename, ".html") || strstr(filename, ".htm")) {
file_type = HTML;
file_type = HTTP_HDR_HTML;
} else if (strstr(filename, ".gif")) {
file_type = GIF;
file_type = HTTP_HDR_GIF;
} else if (strstr(filename, ".png")) {
file_type = PNG;
file_type = HTTP_HDR_PNG;
} else if (strstr(filename, ".jpeg") || strstr(filename, ".jpg")) {
file_type = JPEG;
file_type = HTTP_HDR_JPG;
} else if (strstr(filename, ".bin") || strstr(filename, ".class")) {
file_type = OCTET_STREAM;
file_type = HTTP_HDR_APP;
} else if (strstr(filename, ".ra") || strstr(filename, ".ram")) {
file_type = REALAUDIO;
file_type = HTTP_HDR_RA;
} else if (strstr(filename, ".js")) {
file_type = JAVASCRIPT;
file_type = HTTP_HDR_JS;
} else if (strstr(filename, ".css")) {
file_type = CSS;
file_type = HTTP_HDR_CSS;
} else {
file_type = TEXT;
file_type = HTTP_HDR_DEFAULT_TYPE;
}
cur_string = httpContentType_header[file_type];
cur_string = /*httpContentType_header*/ g_psHTTPHeaderStrings[file_type];
cur_len = strlen(cur_string);
fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len);
written += file_put_ascii(data_file, cur_string, cur_len, &i);
i = 0;
#ifdef HTTP_11
if (useHttp11) {
char intbuf[MAX_PATH_LEN];
memset(intbuf, 0, sizeof(intbuf));
@ -373,8 +377,11 @@ int file_write_http_header(FILE *data_file, const char *filename, int file_size)
fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len);
written += file_put_ascii(data_file, cur_string, cur_len, &i);
}
#else
LWIP_UNUSED_ARG(file_size);
#endif
fprintf(data_file, NEWLINE "/* Empty line (end of header - 2 bytes) */" NEWLINE, cur_string);
fprintf(data_file, NEWLINE "/* Empty line (end of header - 2 bytes) */" NEWLINE, cur_string);
written += file_put_ascii(data_file, "\r\n", 2, &i);
return written;