You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
762 lines
23 KiB
762 lines
23 KiB
/** |
|
* makefsdata: Converts a directory structure for use with the lwIP httpd. |
|
* |
|
* This file is part of the lwIP TCP/IP stack. |
|
* |
|
* Author: Jim Pettinato |
|
* Simon Goldschmidt |
|
* |
|
* @todo: |
|
* - take TCP_MSS, LWIP_TCP_TIMESTAMPS and |
|
* PAYLOAD_ALIGN_TYPE/PAYLOAD_ALIGNMENT as arguments |
|
*/ |
|
|
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#ifdef WIN32 |
|
#define WIN32_LEAN_AND_MEAN |
|
#include "windows.h" |
|
#else |
|
#include <dir.h> |
|
#endif |
|
#include <dos.h> |
|
#include <string.h> |
|
|
|
/* Compatibility defines Win32 vs. DOS */ |
|
#ifdef WIN32 |
|
|
|
#define FIND_T WIN32_FIND_DATAA |
|
#define FIND_T_FILENAME(fInfo) (fInfo.cFileName) |
|
#define FIND_T_IS_DIR(fInfo) ((fInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) |
|
#define FIND_T_IS_FILE(fInfo) ((fInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) |
|
#define FIND_RET_T HANDLE |
|
#define FINDFIRST_FILE(path, result) FindFirstFileA(path, result) |
|
#define FINDFIRST_DIR(path, result) FindFirstFileA(path, result) |
|
#define FINDNEXT(ff_res, result) FindNextFileA(ff_res, result) |
|
#define FINDFIRST_SUCCEEDED(ret) (ret != INVALID_HANDLE_VALUE) |
|
#define FINDNEXT_SUCCEEDED(ret) (ret == TRUE) |
|
|
|
#define GETCWD(path, len) GetCurrentDirectoryA(len, path) |
|
#define CHDIR(path) SetCurrentDirectoryA(path) |
|
#define CHDIR_SUCCEEDED(ret) (ret == TRUE) |
|
|
|
#else |
|
|
|
#define FIND_T struct ffblk |
|
#define FIND_T_FILENAME(fInfo) (fInfo.ff_name) |
|
#define FIND_T_IS_DIR(fInfo) ((fInfo.ff_attrib & FA_DIREC) == FA_DIREC) |
|
#define FIND_T_IS_FILE(fInfo) (1) |
|
#define FIND_RET_T int |
|
#define FINDFIRST_FILE(path, result) findfirst(path, result, FA_ARCH) |
|
#define FINDFIRST_DIR(path, result) findfirst(path, result, FA_DIREC) |
|
#define FINDNEXT(ff_res, result) FindNextFileA(ff_res, result) |
|
#define FINDFIRST_SUCCEEDED(ret) (ret == 0) |
|
#define FINDNEXT_SUCCEEDED(ret) (ret == 0) |
|
|
|
#define GETCWD(path, len) getcwd(path, len) |
|
#define CHDIR(path) chdir(path) |
|
#define CHDIR_SUCCEEDED(ret) (ret == 0) |
|
|
|
#endif |
|
|
|
#define NEWLINE "\r\n" |
|
#define NEWLINE_LEN 2 |
|
|
|
/* define this to get the header variables we use to build HTTP headers */ |
|
#define LWIP_HTTPD_DYNAMIC_HEADERS 1 |
|
#define LWIP_HTTPD_SSI 1 |
|
#include "../httpd_structs.h" |
|
|
|
#include "../core/inet_chksum.c" |
|
#include "../core/def.c" |
|
|
|
/** (Your server name here) */ |
|
const char *serverID = "Server: "HTTPD_SERVER_AGENT"\r\n"; |
|
|
|
/* change this to suit your MEM_ALIGNMENT */ |
|
#define PAYLOAD_ALIGNMENT 4 |
|
/* set this to 0 to prevent aligning payload */ |
|
#define ALIGN_PAYLOAD 1 |
|
/* define this to a type that has the required alignment */ |
|
#define PAYLOAD_ALIGN_TYPE "unsigned int" |
|
static int payload_alingment_dummy_counter = 0; |
|
|
|
#define HEX_BYTES_PER_LINE 16 |
|
|
|
#define MAX_PATH_LEN 256 |
|
|
|
#define COPY_BUFSIZE 10240 |
|
|
|
struct file_entry |
|
{ |
|
struct file_entry* next; |
|
const char* filename_c; |
|
}; |
|
|
|
int process_sub(FILE *data_file, FILE *struct_file); |
|
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, |
|
u16_t *http_hdr_len, u16_t *http_hdr_chksum); |
|
int file_put_ascii(FILE *file, const char *ascii_string, int len, int *i); |
|
int s_put_ascii(char *buf, const char *ascii_string, int len, int *i); |
|
void concat_files(const char *file1, const char *file2, const char *targetfile); |
|
int check_path(char* path, size_t size); |
|
|
|
static unsigned char file_buffer_raw[COPY_BUFSIZE]; |
|
/* 5 bytes per char + 3 bytes per line */ |
|
static char file_buffer_c[COPY_BUFSIZE * 5 + ((COPY_BUFSIZE / HEX_BYTES_PER_LINE) * 3)]; |
|
|
|
char curSubdir[MAX_PATH_LEN]; |
|
char lastFileVar[MAX_PATH_LEN]; |
|
char hdr_buf[4096]; |
|
|
|
unsigned char processSubs = 1; |
|
unsigned char includeHttpHeader = 1; |
|
unsigned char useHttp11 = 0; |
|
unsigned char supportSsi = 1; |
|
unsigned char precalcChksum = 0; |
|
|
|
struct file_entry* first_file = NULL; |
|
struct file_entry* last_file = NULL; |
|
|
|
int main(int argc, char *argv[]) |
|
{ |
|
char path[MAX_PATH_LEN]; |
|
char appPath[MAX_PATH_LEN]; |
|
FILE *data_file; |
|
FILE *struct_file; |
|
int filesProcessed; |
|
int i; |
|
char targetfile[MAX_PATH_LEN]; |
|
strcpy(targetfile, "fsdata.c"); |
|
|
|
memset(path, 0, sizeof(path)); |
|
memset(appPath, 0, sizeof(appPath)); |
|
|
|
printf(NEWLINE " makefsdata - HTML to C source converter" NEWLINE); |
|
printf(" by Jim Pettinato - circa 2003 " NEWLINE); |
|
printf(" extended by Simon Goldschmidt - 2009 " NEWLINE NEWLINE); |
|
|
|
strcpy(path, "fs"); |
|
for(i = 1; i < argc; i++) { |
|
if (argv[i][0] == '-') { |
|
if (strstr(argv[i], "-s")) { |
|
processSubs = 0; |
|
} else if (strstr(argv[i], "-e")) { |
|
includeHttpHeader = 0; |
|
} else if (strstr(argv[i], "-11")) { |
|
useHttp11 = 1; |
|
} else if (strstr(argv[i], "-nossi")) { |
|
supportSsi = 0; |
|
} else if (strstr(argv[i], "-c")) { |
|
precalcChksum = 1; |
|
} else if((argv[i][1] == 'f') && (argv[i][2] == ':')) { |
|
strncpy(targetfile, &argv[i][3], sizeof(targetfile) - 1); |
|
targetfile[sizeof(targetfile) - 1] = 0; |
|
printf("Writing to file \"%s\"\n", targetfile); |
|
} |
|
} else { |
|
strncpy(path, argv[i], sizeof(path)-1); |
|
path[sizeof(path)-1] = 0; |
|
} |
|
} |
|
|
|
if(!check_path(path, sizeof(path))) { |
|
printf("Invalid path: \"%s\"." NEWLINE, path); |
|
exit(-1); |
|
} |
|
|
|
GETCWD(appPath, MAX_PATH_LEN); |
|
/* if command line param or subdir named 'fs' not found spout usage verbiage */ |
|
if (!CHDIR_SUCCEEDED(CHDIR(path))) { |
|
/* if no subdir named 'fs' (or the one which was given) exists, spout usage verbiage */ |
|
printf(" Failed to open directory \"%s\"." NEWLINE NEWLINE, path); |
|
printf(" Usage: htmlgen [targetdir] [-s] [-i] [-f:<filename>]" NEWLINE NEWLINE); |
|
printf(" targetdir: relative or absolute path to files to convert" NEWLINE); |
|
printf(" switch -s: toggle processing of subdirectories (default is on)" NEWLINE); |
|
printf(" switch -e: exclude HTTP header from file (header is created at runtime, default is off)" NEWLINE); |
|
printf(" switch -11: include HTTP 1.1 header (1.0 is default)" NEWLINE); |
|
printf(" switch -nossi: no support for SSI (cannot calculate Content-Length for SSI)" NEWLINE); |
|
printf(" switch -c: precalculate checksums for all pages (default is off)" NEWLINE); |
|
printf(" switch -f: target filename (default is \"fsdata.c\")" NEWLINE); |
|
printf(" if targetdir not specified, htmlgen will attempt to" NEWLINE); |
|
printf(" process files in subdirectory 'fs'" NEWLINE); |
|
exit(-1); |
|
} |
|
CHDIR(appPath); |
|
|
|
printf("HTTP %sheader will %s statically included." NEWLINE, |
|
(includeHttpHeader ? (useHttp11 ? "1.1 " : "1.0 ") : ""), |
|
(includeHttpHeader ? "be" : "not be")); |
|
|
|
sprintf(curSubdir, ""); /* start off in web page's root directory - relative paths */ |
|
printf(" Processing all files in directory %s", path); |
|
if (processSubs) { |
|
printf(" and subdirectories..." NEWLINE NEWLINE); |
|
} else { |
|
printf("..." NEWLINE NEWLINE); |
|
} |
|
|
|
data_file = fopen("fsdata.tmp", "wb"); |
|
if (data_file == NULL) { |
|
printf("Failed to create file \"fsdata.tmp\"\n"); |
|
exit(-1); |
|
} |
|
struct_file = fopen("fshdr.tmp", "wb"); |
|
if (struct_file == NULL) { |
|
printf("Failed to create file \"fshdr.tmp\"\n"); |
|
fclose(data_file); |
|
exit(-1); |
|
} |
|
|
|
CHDIR(path); |
|
|
|
fprintf(data_file, "#include \"fs.h\"" NEWLINE); |
|
fprintf(data_file, "#include \"lwip/def.h\"" NEWLINE); |
|
fprintf(data_file, "#include \"fsdata.h\"" NEWLINE NEWLINE NEWLINE); |
|
|
|
fprintf(data_file, "#define file_NULL (struct fsdata_file *) NULL" NEWLINE NEWLINE NEWLINE); |
|
|
|
sprintf(lastFileVar, "NULL"); |
|
|
|
filesProcessed = process_sub(data_file, struct_file); |
|
|
|
/* data_file now contains all of the raw data.. now append linked list of |
|
* file header structs to allow embedded app to search for a file name */ |
|
fprintf(data_file, NEWLINE NEWLINE); |
|
fprintf(struct_file, "#define FS_ROOT file_%s" NEWLINE, lastFileVar); |
|
fprintf(struct_file, "#define FS_NUMFILES %d" NEWLINE NEWLINE, filesProcessed); |
|
|
|
fclose(data_file); |
|
fclose(struct_file); |
|
|
|
CHDIR(appPath); |
|
/* append struct_file to data_file */ |
|
printf(NEWLINE "Creating target file..." NEWLINE NEWLINE); |
|
concat_files("fsdata.tmp", "fshdr.tmp", targetfile); |
|
|
|
/* if succeeded, delete the temporary files */ |
|
if (remove("fsdata.tmp") != 0) { |
|
printf("Warning: failed to delete fsdata.tmp\n"); |
|
} |
|
if (remove("fshdr.tmp") != 0) { |
|
printf("Warning: failed to delete fshdr.tmp\n"); |
|
} |
|
|
|
printf(NEWLINE "Processed %d files - done." NEWLINE NEWLINE, filesProcessed); |
|
|
|
while (first_file != NULL) { |
|
struct file_entry* fe = first_file; |
|
first_file = fe->next; |
|
free(fe); |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
int check_path(char* path, size_t size) |
|
{ |
|
size_t slen; |
|
if (path[0] == 0) { |
|
/* empty */ |
|
return 0; |
|
} |
|
slen = strlen(path); |
|
if (slen >= size) { |
|
/* not NULL-terminated */ |
|
return 0; |
|
} |
|
while ((slen > 0) && ((path[slen] == '\\') || (path[slen] == '/'))) { |
|
/* path should not end with trailing backslash */ |
|
path[slen] = 0; |
|
slen--; |
|
} |
|
if (slen == 0) { |
|
return 0; |
|
} |
|
return 1; |
|
} |
|
|
|
static void copy_file(const char *filename_in, FILE *fout) |
|
{ |
|
FILE *fin; |
|
size_t len; |
|
fin = fopen(filename_in, "rb"); |
|
if (fin == NULL) { |
|
printf("Failed to open file \"%s\"\n", filename_in); |
|
exit(-1); |
|
} |
|
|
|
while((len = fread(file_buffer_raw, 1, COPY_BUFSIZE, fin)) > 0) |
|
{ |
|
fwrite(file_buffer_raw, 1, len, fout); |
|
} |
|
fclose(fin); |
|
} |
|
|
|
void concat_files(const char *file1, const char *file2, const char *targetfile) |
|
{ |
|
FILE *fout; |
|
fout = fopen(targetfile, "wb"); |
|
if (fout == NULL) { |
|
printf("Failed to open file \"%s\"\n", targetfile); |
|
exit(-1); |
|
} |
|
copy_file(file1, fout); |
|
copy_file(file2, fout); |
|
fclose(fout); |
|
} |
|
|
|
int process_sub(FILE *data_file, FILE *struct_file) |
|
{ |
|
FIND_T fInfo; |
|
FIND_RET_T fret; |
|
int filesProcessed = 0; |
|
|
|
if (processSubs) { |
|
/* process subs recursively */ |
|
size_t sublen = strlen(curSubdir); |
|
size_t freelen = sizeof(curSubdir) - sublen - 1; |
|
LWIP_ASSERT("sublen < sizeof(curSubdir)", sublen < sizeof(curSubdir)); |
|
fret = FINDFIRST_DIR("*", &fInfo); |
|
if (FINDFIRST_SUCCEEDED(fret)) { |
|
do { |
|
const char *curName = FIND_T_FILENAME(fInfo); |
|
if ((curName[0] == '.') || (strcmp(curName, "CVS") == 0)) { |
|
continue; |
|
} |
|
if (!FIND_T_IS_DIR(fInfo)) { |
|
continue; |
|
} |
|
if (freelen > 0) { |
|
CHDIR(curName); |
|
strncat(curSubdir, "/", freelen); |
|
strncat(curSubdir, curName, freelen - 1); |
|
curSubdir[sizeof(curSubdir) - 1] = 0; |
|
printf(NEWLINE "processing subdirectory %s/..." NEWLINE, curSubdir); |
|
filesProcessed += process_sub(data_file, struct_file); |
|
CHDIR(".."); |
|
curSubdir[sublen] = 0; |
|
} else { |
|
printf("WARNING: cannot process sub due to path length restrictions: \"%s/%s\"\n", curSubdir, curName); |
|
} |
|
} while (FINDNEXT_SUCCEEDED(FINDNEXT(fret, &fInfo))); |
|
} |
|
} |
|
|
|
fret = FINDFIRST_FILE("*.*", &fInfo); |
|
if (FINDFIRST_SUCCEEDED(fret)) { |
|
/* at least one file in directory */ |
|
do { |
|
if (FIND_T_IS_FILE(fInfo)) { |
|
const char *curName = FIND_T_FILENAME(fInfo); |
|
printf("processing %s/%s..." NEWLINE, curSubdir, curName); |
|
if (process_file(data_file, struct_file, curName) < 0) { |
|
printf(NEWLINE "Error... aborting" NEWLINE); |
|
return -1; |
|
} |
|
filesProcessed++; |
|
} |
|
} while (FINDNEXT_SUCCEEDED(FINDNEXT(fret, &fInfo))); |
|
} |
|
return filesProcessed; |
|
} |
|
|
|
int get_file_size(const char* filename) |
|
{ |
|
FILE *inFile; |
|
int file_size = -1; |
|
inFile = fopen(filename, "rb"); |
|
if (inFile == NULL) { |
|
printf("Failed to open file \"%s\"\n", filename); |
|
exit(-1); |
|
} |
|
fseek(inFile, 0, SEEK_END); |
|
file_size = ftell(inFile); |
|
fclose(inFile); |
|
return file_size; |
|
} |
|
|
|
void process_file_data(const char *filename, FILE *data_file) |
|
{ |
|
FILE *source_file; |
|
size_t len, written, i, src_off=0; |
|
|
|
source_file = fopen(filename, "rb"); |
|
if (source_file == NULL) { |
|
printf("Failed to open file \"%s\"\n", filename); |
|
exit(-1); |
|
} |
|
|
|
do { |
|
size_t off = 0; |
|
len = fread(file_buffer_raw, 1, COPY_BUFSIZE, source_file); |
|
if (len > 0) { |
|
for (i = 0; i < len; i++) { |
|
sprintf(&file_buffer_c[off], "0x%02.2x,", file_buffer_raw[i]); |
|
off += 5; |
|
if ((++src_off % HEX_BYTES_PER_LINE) == 0) { |
|
memcpy(&file_buffer_c[off], NEWLINE, NEWLINE_LEN); |
|
off += NEWLINE_LEN; |
|
} |
|
} |
|
written = fwrite(file_buffer_c, 1, off, data_file); |
|
} |
|
} while(len > 0); |
|
fclose(source_file); |
|
} |
|
|
|
int write_checksums(FILE *struct_file, const char *filename, const char *varname, |
|
u16_t hdr_len, u16_t hdr_chksum) |
|
{ |
|
int chunk_size = TCP_MSS; |
|
int offset; |
|
size_t len; |
|
int i = 0; |
|
FILE *f; |
|
#if LWIP_TCP_TIMESTAMPS |
|
/* when timestamps are used, usable space is 12 bytes less per segment */ |
|
chunk_size -= 12; |
|
#endif |
|
|
|
fprintf(struct_file, "#if HTTPD_PRECALCULATED_CHECKSUM" NEWLINE); |
|
fprintf(struct_file, "const struct fsdata_chksum chksums_%s[] = {" NEWLINE, varname); |
|
|
|
memset(file_buffer_raw, 0xab, sizeof(file_buffer_raw)); |
|
f = fopen(filename, "rb"); |
|
if (f == NULL) { |
|
printf("Failed to open file \"%s\"\n", filename); |
|
exit(-1); |
|
} |
|
if (hdr_len > 0) { |
|
/* add checksum for HTTP header */ |
|
fprintf(struct_file, "{%d, 0x%04x, %d}," NEWLINE, 0, hdr_chksum, hdr_len); |
|
i++; |
|
} |
|
for (offset = hdr_len; ; offset += len) { |
|
unsigned short chksum; |
|
len = fread(file_buffer_raw, 1, chunk_size, f); |
|
if (len == 0) { |
|
break; |
|
} |
|
chksum = ~inet_chksum(file_buffer_raw, (u16_t)len); |
|
/* add checksum for data */ |
|
fprintf(struct_file, "{%d, 0x%04x, %d}," NEWLINE, offset, chksum, len); |
|
i++; |
|
} |
|
fclose(f); |
|
fprintf(struct_file, "};" NEWLINE); |
|
fprintf(struct_file, "#endif /* HTTPD_PRECALCULATED_CHECKSUM */" NEWLINE); |
|
return i; |
|
} |
|
|
|
static int is_valid_char_for_c_var(char x) |
|
{ |
|
if (((x >= 'A') && (x <= 'Z')) || |
|
((x >= 'a') && (x <= 'z')) || |
|
((x >= '0') && (x <= '9')) || |
|
(x == '_')) |
|
{ |
|
return 1; |
|
} |
|
return 0; |
|
} |
|
|
|
static void fix_filename_for_c(char* qualifiedName, size_t max_len) |
|
{ |
|
struct file_entry* f; |
|
size_t len = strlen(qualifiedName); |
|
char *new_name = malloc(len + 2); |
|
int filename_ok; |
|
int cnt = 0; |
|
size_t i; |
|
if (len + 3 == max_len) { |
|
printf("File name too long: \"%s\"\n", qualifiedName); |
|
exit(-1); |
|
} |
|
strcpy(new_name, qualifiedName); |
|
for (i = 0; i < len; i++) { |
|
if (!is_valid_char_for_c_var(new_name[i])) { |
|
new_name[i] = '_'; |
|
} |
|
} |
|
do { |
|
filename_ok = 1; |
|
for (f = first_file; f != NULL; f = f->next) { |
|
if (!strcmp(f->filename_c, new_name)) { |
|
filename_ok = 0; |
|
cnt++; |
|
// try next unique file name |
|
sprintf(&new_name[len], "%d", cnt); |
|
break; |
|
} |
|
} |
|
} while (!filename_ok && (cnt < 999)); |
|
if (!filename_ok) { |
|
printf("Failed to get unique file name: \"%s\"\n", qualifiedName); |
|
exit(-1); |
|
} |
|
strcpy(qualifiedName, new_name); |
|
free(new_name); |
|
} |
|
|
|
static void register_filename(const char* qualifiedName) |
|
{ |
|
struct file_entry* fe = malloc(sizeof(struct file_entry)); |
|
fe->filename_c = strdup(qualifiedName); |
|
fe->next = NULL; |
|
if (first_file == NULL) { |
|
first_file = last_file = fe; |
|
} else { |
|
last_file->next = fe; |
|
last_file = fe; |
|
} |
|
} |
|
|
|
int process_file(FILE *data_file, FILE *struct_file, const char *filename) |
|
{ |
|
char varname[MAX_PATH_LEN]; |
|
int i = 0; |
|
char qualifiedName[MAX_PATH_LEN]; |
|
int file_size; |
|
u16_t http_hdr_chksum = 0; |
|
u16_t http_hdr_len = 0; |
|
int chksum_count = 0; |
|
|
|
/* create qualified name (TODO: prepend slash or not?) */ |
|
sprintf(qualifiedName,"%s/%s", curSubdir, filename); |
|
/* create C variable name */ |
|
strcpy(varname, qualifiedName); |
|
/* convert slashes & dots to underscores */ |
|
fix_filename_for_c(varname, MAX_PATH_LEN); |
|
register_filename(varname); |
|
#if ALIGN_PAYLOAD |
|
/* to force even alignment of array */ |
|
fprintf(data_file, "static const " PAYLOAD_ALIGN_TYPE " dummy_align_%s = %d;" NEWLINE, varname, payload_alingment_dummy_counter++); |
|
#endif /* ALIGN_PAYLOAD */ |
|
fprintf(data_file, "static const unsigned char data_%s[] = {" NEWLINE, varname); |
|
/* encode source file name (used by file system, not returned to browser) */ |
|
fprintf(data_file, "/* %s (%d chars) */" NEWLINE, qualifiedName, strlen(qualifiedName)+1); |
|
file_put_ascii(data_file, qualifiedName, strlen(qualifiedName)+1, &i); |
|
#if ALIGN_PAYLOAD |
|
/* pad to even number of bytes to assure payload is on aligned boundary */ |
|
while(i % PAYLOAD_ALIGNMENT != 0) { |
|
fprintf(data_file, "0x%02.2x,", 0); |
|
i++; |
|
} |
|
#endif /* ALIGN_PAYLOAD */ |
|
fprintf(data_file, NEWLINE); |
|
|
|
file_size = get_file_size(filename); |
|
if (includeHttpHeader) { |
|
file_write_http_header(data_file, filename, file_size, &http_hdr_len, &http_hdr_chksum); |
|
} |
|
if (precalcChksum) { |
|
chksum_count = write_checksums(struct_file, filename, varname, http_hdr_len, http_hdr_chksum); |
|
} |
|
|
|
/* build declaration of struct fsdata_file in temp file */ |
|
fprintf(struct_file, "const struct fsdata_file file_%s[] = { {" NEWLINE, varname); |
|
fprintf(struct_file, "file_%s," NEWLINE, lastFileVar); |
|
fprintf(struct_file, "data_%s," NEWLINE, varname); |
|
fprintf(struct_file, "data_%s + %d," NEWLINE, varname, i); |
|
fprintf(struct_file, "sizeof(data_%s) - %d," NEWLINE, varname, i); |
|
fprintf(struct_file, "%d," NEWLINE, includeHttpHeader); |
|
if (precalcChksum) { |
|
fprintf(struct_file, "#if HTTPD_PRECALCULATED_CHECKSUM" NEWLINE); |
|
fprintf(struct_file, "%d, chksums_%s," NEWLINE, chksum_count, varname); |
|
fprintf(struct_file, "#endif /* HTTPD_PRECALCULATED_CHECKSUM */" NEWLINE); |
|
} |
|
fprintf(struct_file, "}};" NEWLINE NEWLINE); |
|
strcpy(lastFileVar, varname); |
|
|
|
/* write actual file contents */ |
|
i = 0; |
|
fprintf(data_file, NEWLINE "/* raw file data (%d bytes) */" NEWLINE, file_size); |
|
process_file_data(filename, data_file); |
|
fprintf(data_file, "};" NEWLINE NEWLINE); |
|
|
|
return 0; |
|
} |
|
|
|
int file_write_http_header(FILE *data_file, const char *filename, int file_size, |
|
u16_t *http_hdr_len, u16_t *http_hdr_chksum) |
|
{ |
|
int i = 0; |
|
int response_type = HTTP_HDR_OK; |
|
int file_type = HTTP_HDR_DEFAULT_TYPE; |
|
const char *cur_string; |
|
size_t cur_len; |
|
int written = 0; |
|
size_t hdr_len = 0; |
|
u16_t acc; |
|
const char *file_ext; |
|
int j; |
|
u8_t keepalive = useHttp11; |
|
|
|
if (keepalive) { |
|
size_t loop; |
|
for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) { |
|
if (strstr(filename, g_pcSSIExtensions[loop])) { |
|
/* no keepalive connection for SSI files */ |
|
keepalive = 0; |
|
} |
|
} |
|
} |
|
|
|
memset(hdr_buf, 0, sizeof(hdr_buf)); |
|
|
|
if (useHttp11) { |
|
response_type = HTTP_HDR_OK_11; |
|
} |
|
|
|
fprintf(data_file, NEWLINE "/* HTTP header */"); |
|
if (strstr(filename, "404") == filename) { |
|
response_type = HTTP_HDR_NOT_FOUND; |
|
if (useHttp11) { |
|
response_type = HTTP_HDR_NOT_FOUND_11; |
|
} |
|
} else if (strstr(filename, "400") == filename) { |
|
response_type = HTTP_HDR_BAD_REQUEST; |
|
if (useHttp11) { |
|
response_type = HTTP_HDR_BAD_REQUEST_11; |
|
} |
|
} else if (strstr(filename, "501") == filename) { |
|
response_type = HTTP_HDR_NOT_IMPL; |
|
if (useHttp11) { |
|
response_type = HTTP_HDR_NOT_IMPL_11; |
|
} |
|
} |
|
cur_string = g_psHTTPHeaderStrings[response_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; |
|
if (precalcChksum) { |
|
memcpy(&hdr_buf[hdr_len], cur_string, cur_len); |
|
hdr_len += cur_len; |
|
} |
|
|
|
cur_string = serverID; |
|
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; |
|
if (precalcChksum) { |
|
memcpy(&hdr_buf[hdr_len], cur_string, cur_len); |
|
hdr_len += cur_len; |
|
} |
|
|
|
file_ext = filename; |
|
if (file_ext != NULL) { |
|
while(strstr(file_ext, ".") != NULL) { |
|
file_ext = strstr(file_ext, "."); |
|
file_ext++; |
|
} |
|
} |
|
if((file_ext == NULL) || (*file_ext == 0)) { |
|
printf("failed to get extension for file \"%s\", using default.\n", filename); |
|
} else { |
|
for(j = 0; j < NUM_HTTP_HEADERS; j++) { |
|
if(!strcmp(file_ext, g_psHTTPHeaders[j].extension)) { |
|
file_type = g_psHTTPHeaders[j].headerIndex; |
|
break; |
|
} |
|
} |
|
if (j >= NUM_HTTP_HEADERS) { |
|
printf("failed to get file type for extension \"%s\", using default.\n", file_ext); |
|
file_type = HTTP_HDR_DEFAULT_TYPE; |
|
} |
|
} |
|
|
|
if (useHttp11) { |
|
char intbuf[MAX_PATH_LEN]; |
|
int content_len = file_size; |
|
memset(intbuf, 0, sizeof(intbuf)); |
|
|
|
if (!keepalive) { |
|
content_len *= 2; |
|
} |
|
{ |
|
cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH]; |
|
cur_len = strlen(cur_string); |
|
fprintf(data_file, NEWLINE "/* \"%s%d\r\n\" (%d+ bytes) */" NEWLINE, cur_string, content_len, cur_len+2); |
|
written += file_put_ascii(data_file, cur_string, cur_len, &i); |
|
if (precalcChksum) { |
|
memcpy(&hdr_buf[hdr_len], cur_string, cur_len); |
|
hdr_len += cur_len; |
|
} |
|
|
|
_itoa(content_len, intbuf, 10); |
|
strcat(intbuf, "\r\n"); |
|
cur_len = strlen(intbuf); |
|
written += file_put_ascii(data_file, intbuf, cur_len, &i); |
|
i = 0; |
|
if (precalcChksum) { |
|
memcpy(&hdr_buf[hdr_len], intbuf, cur_len); |
|
hdr_len += cur_len; |
|
} |
|
} |
|
|
|
if (keepalive) { |
|
cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_KEEPALIVE]; |
|
} else { |
|
cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE]; |
|
} |
|
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; |
|
if (precalcChksum) { |
|
memcpy(&hdr_buf[hdr_len], cur_string, cur_len); |
|
hdr_len += cur_len; |
|
} |
|
} |
|
|
|
cur_string = 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; |
|
if (precalcChksum) { |
|
memcpy(&hdr_buf[hdr_len], cur_string, cur_len); |
|
hdr_len += cur_len; |
|
|
|
LWIP_ASSERT("hdr_len <= 0xffff", hdr_len <= 0xffff); |
|
LWIP_ASSERT("strlen(hdr_buf) == hdr_len", strlen(hdr_buf) == hdr_len); |
|
acc = ~inet_chksum(hdr_buf, (u16_t)hdr_len); |
|
*http_hdr_len = (u16_t)hdr_len; |
|
*http_hdr_chksum = acc; |
|
} |
|
|
|
return written; |
|
} |
|
|
|
int file_put_ascii(FILE *file, const char* ascii_string, int len, int *i) |
|
{ |
|
int x; |
|
for(x = 0; x < len; x++) { |
|
unsigned char cur = ascii_string[x]; |
|
fprintf(file, "0x%02.2x,", cur); |
|
if ((++(*i) % HEX_BYTES_PER_LINE) == 0) { |
|
fprintf(file, NEWLINE); |
|
} |
|
} |
|
return len; |
|
} |
|
|
|
int s_put_ascii(char *buf, const char *ascii_string, int len, int *i) |
|
{ |
|
int x; |
|
int idx = 0; |
|
for(x = 0; x < len; x++) { |
|
unsigned char cur = ascii_string[x]; |
|
sprintf(&buf[idx], "0x%02.2x,", cur); |
|
idx += 5; |
|
if ((++(*i) % HEX_BYTES_PER_LINE) == 0) { |
|
sprintf(&buf[idx], NEWLINE); |
|
idx += NEWLINE_LEN; |
|
} |
|
} |
|
return len; |
|
}
|
|
|