Merged httpd from TI Luminary: added basic SSI and CGI support, added support for dynamic HTTP header generation
This commit is contained in:
parent
3e130e4f7f
commit
4ec673b17d
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue