1*5d5fbe79SDavid van Moolenbroek /**
2*5d5fbe79SDavid van Moolenbroek * makefsdata: Converts a directory structure for use with the lwIP httpd.
3*5d5fbe79SDavid van Moolenbroek *
4*5d5fbe79SDavid van Moolenbroek * This file is part of the lwIP TCP/IP stack.
5*5d5fbe79SDavid van Moolenbroek *
6*5d5fbe79SDavid van Moolenbroek * Author: Jim Pettinato
7*5d5fbe79SDavid van Moolenbroek * Simon Goldschmidt
8*5d5fbe79SDavid van Moolenbroek *
9*5d5fbe79SDavid van Moolenbroek * @todo:
10*5d5fbe79SDavid van Moolenbroek * - take TCP_MSS, LWIP_TCP_TIMESTAMPS and
11*5d5fbe79SDavid van Moolenbroek * PAYLOAD_ALIGN_TYPE/PAYLOAD_ALIGNMENT as arguments
12*5d5fbe79SDavid van Moolenbroek */
13*5d5fbe79SDavid van Moolenbroek
14*5d5fbe79SDavid van Moolenbroek #include <stdio.h>
15*5d5fbe79SDavid van Moolenbroek #include <stdlib.h>
16*5d5fbe79SDavid van Moolenbroek #ifdef WIN32
17*5d5fbe79SDavid van Moolenbroek #define WIN32_LEAN_AND_MEAN
18*5d5fbe79SDavid van Moolenbroek #include "windows.h"
19*5d5fbe79SDavid van Moolenbroek #else
20*5d5fbe79SDavid van Moolenbroek #include <dir.h>
21*5d5fbe79SDavid van Moolenbroek #endif
22*5d5fbe79SDavid van Moolenbroek #include <dos.h>
23*5d5fbe79SDavid van Moolenbroek #include <string.h>
24*5d5fbe79SDavid van Moolenbroek #include <time.h>
25*5d5fbe79SDavid van Moolenbroek #include <sys/stat.h>
26*5d5fbe79SDavid van Moolenbroek
27*5d5fbe79SDavid van Moolenbroek /** Makefsdata can generate *all* files deflate-compressed (where file size shrinks).
28*5d5fbe79SDavid van Moolenbroek * Since nearly all browsers support this, this is a good way to reduce ROM size.
29*5d5fbe79SDavid van Moolenbroek * To compress the files, "miniz.c" must be downloaded seperately.
30*5d5fbe79SDavid van Moolenbroek */
31*5d5fbe79SDavid van Moolenbroek #ifndef MAKEFS_SUPPORT_DEFLATE
32*5d5fbe79SDavid van Moolenbroek #define MAKEFS_SUPPORT_DEFLATE 0
33*5d5fbe79SDavid van Moolenbroek #endif
34*5d5fbe79SDavid van Moolenbroek
35*5d5fbe79SDavid van Moolenbroek #define COPY_BUFSIZE (1024*1024) /* 1 MByte */
36*5d5fbe79SDavid van Moolenbroek
37*5d5fbe79SDavid van Moolenbroek #if MAKEFS_SUPPORT_DEFLATE
38*5d5fbe79SDavid van Moolenbroek #include "../miniz.c"
39*5d5fbe79SDavid van Moolenbroek
40*5d5fbe79SDavid van Moolenbroek typedef unsigned char uint8;
41*5d5fbe79SDavid van Moolenbroek typedef unsigned short uint16;
42*5d5fbe79SDavid van Moolenbroek typedef unsigned int uint;
43*5d5fbe79SDavid van Moolenbroek
44*5d5fbe79SDavid van Moolenbroek #define my_max(a,b) (((a) > (b)) ? (a) : (b))
45*5d5fbe79SDavid van Moolenbroek #define my_min(a,b) (((a) < (b)) ? (a) : (b))
46*5d5fbe79SDavid van Moolenbroek
47*5d5fbe79SDavid van Moolenbroek /* COMP_OUT_BUF_SIZE is the size of the output buffer used during compression.
48*5d5fbe79SDavid van Moolenbroek COMP_OUT_BUF_SIZE must be >= 1 and <= OUT_BUF_SIZE */
49*5d5fbe79SDavid van Moolenbroek #define COMP_OUT_BUF_SIZE COPY_BUFSIZE
50*5d5fbe79SDavid van Moolenbroek
51*5d5fbe79SDavid van Moolenbroek /* OUT_BUF_SIZE is the size of the output buffer used during decompression.
52*5d5fbe79SDavid van Moolenbroek OUT_BUF_SIZE must be a power of 2 >= TINFL_LZ_DICT_SIZE (because the low-level decompressor not only writes, but reads from the output buffer as it decompresses) */
53*5d5fbe79SDavid van Moolenbroek #define OUT_BUF_SIZE COPY_BUFSIZE
54*5d5fbe79SDavid van Moolenbroek static uint8 s_outbuf[OUT_BUF_SIZE];
55*5d5fbe79SDavid van Moolenbroek static uint8 s_checkbuf[OUT_BUF_SIZE];
56*5d5fbe79SDavid van Moolenbroek
57*5d5fbe79SDavid van Moolenbroek /* tdefl_compressor contains all the state needed by the low-level compressor so it's a pretty big struct (~300k).
58*5d5fbe79SDavid van Moolenbroek This example makes it a global vs. putting it on the stack, of course in real-world usage you'll probably malloc() or new it. */
59*5d5fbe79SDavid van Moolenbroek tdefl_compressor g_deflator;
60*5d5fbe79SDavid van Moolenbroek tinfl_decompressor g_inflator;
61*5d5fbe79SDavid van Moolenbroek
62*5d5fbe79SDavid van Moolenbroek int deflate_level = 10; /* default compression level, can be changed via command line */
63*5d5fbe79SDavid van Moolenbroek #define USAGE_ARG_DEFLATE " [-defl<:compr_level>]"
64*5d5fbe79SDavid van Moolenbroek #else /* MAKEFS_SUPPORT_DEFLATE */
65*5d5fbe79SDavid van Moolenbroek #define USAGE_ARG_DEFLATE ""
66*5d5fbe79SDavid van Moolenbroek #endif /* MAKEFS_SUPPORT_DEFLATE */
67*5d5fbe79SDavid van Moolenbroek
68*5d5fbe79SDavid van Moolenbroek /* Compatibility defines Win32 vs. DOS */
69*5d5fbe79SDavid van Moolenbroek #ifdef WIN32
70*5d5fbe79SDavid van Moolenbroek
71*5d5fbe79SDavid van Moolenbroek #define FIND_T WIN32_FIND_DATAA
72*5d5fbe79SDavid van Moolenbroek #define FIND_T_FILENAME(fInfo) (fInfo.cFileName)
73*5d5fbe79SDavid van Moolenbroek #define FIND_T_IS_DIR(fInfo) ((fInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
74*5d5fbe79SDavid van Moolenbroek #define FIND_T_IS_FILE(fInfo) ((fInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
75*5d5fbe79SDavid van Moolenbroek #define FIND_RET_T HANDLE
76*5d5fbe79SDavid van Moolenbroek #define FINDFIRST_FILE(path, result) FindFirstFileA(path, result)
77*5d5fbe79SDavid van Moolenbroek #define FINDFIRST_DIR(path, result) FindFirstFileA(path, result)
78*5d5fbe79SDavid van Moolenbroek #define FINDNEXT(ff_res, result) FindNextFileA(ff_res, result)
79*5d5fbe79SDavid van Moolenbroek #define FINDFIRST_SUCCEEDED(ret) (ret != INVALID_HANDLE_VALUE)
80*5d5fbe79SDavid van Moolenbroek #define FINDNEXT_SUCCEEDED(ret) (ret == TRUE)
81*5d5fbe79SDavid van Moolenbroek
82*5d5fbe79SDavid van Moolenbroek #define GETCWD(path, len) GetCurrentDirectoryA(len, path)
83*5d5fbe79SDavid van Moolenbroek #define CHDIR(path) SetCurrentDirectoryA(path)
84*5d5fbe79SDavid van Moolenbroek #define CHDIR_SUCCEEDED(ret) (ret == TRUE)
85*5d5fbe79SDavid van Moolenbroek
86*5d5fbe79SDavid van Moolenbroek #else
87*5d5fbe79SDavid van Moolenbroek
88*5d5fbe79SDavid van Moolenbroek #define FIND_T struct ffblk
89*5d5fbe79SDavid van Moolenbroek #define FIND_T_FILENAME(fInfo) (fInfo.ff_name)
90*5d5fbe79SDavid van Moolenbroek #define FIND_T_IS_DIR(fInfo) ((fInfo.ff_attrib & FA_DIREC) == FA_DIREC)
91*5d5fbe79SDavid van Moolenbroek #define FIND_T_IS_FILE(fInfo) (1)
92*5d5fbe79SDavid van Moolenbroek #define FIND_RET_T int
93*5d5fbe79SDavid van Moolenbroek #define FINDFIRST_FILE(path, result) findfirst(path, result, FA_ARCH)
94*5d5fbe79SDavid van Moolenbroek #define FINDFIRST_DIR(path, result) findfirst(path, result, FA_DIREC)
95*5d5fbe79SDavid van Moolenbroek #define FINDNEXT(ff_res, result) FindNextFileA(ff_res, result)
96*5d5fbe79SDavid van Moolenbroek #define FINDFIRST_SUCCEEDED(ret) (ret == 0)
97*5d5fbe79SDavid van Moolenbroek #define FINDNEXT_SUCCEEDED(ret) (ret == 0)
98*5d5fbe79SDavid van Moolenbroek
99*5d5fbe79SDavid van Moolenbroek #define GETCWD(path, len) getcwd(path, len)
100*5d5fbe79SDavid van Moolenbroek #define CHDIR(path) chdir(path)
101*5d5fbe79SDavid van Moolenbroek #define CHDIR_SUCCEEDED(ret) (ret == 0)
102*5d5fbe79SDavid van Moolenbroek
103*5d5fbe79SDavid van Moolenbroek #endif
104*5d5fbe79SDavid van Moolenbroek
105*5d5fbe79SDavid van Moolenbroek #define NEWLINE "\r\n"
106*5d5fbe79SDavid van Moolenbroek #define NEWLINE_LEN 2
107*5d5fbe79SDavid van Moolenbroek
108*5d5fbe79SDavid van Moolenbroek /* define this to get the header variables we use to build HTTP headers */
109*5d5fbe79SDavid van Moolenbroek #define LWIP_HTTPD_DYNAMIC_HEADERS 1
110*5d5fbe79SDavid van Moolenbroek #define LWIP_HTTPD_SSI 1
111*5d5fbe79SDavid van Moolenbroek #include "lwip/init.h"
112*5d5fbe79SDavid van Moolenbroek #include "../httpd_structs.h"
113*5d5fbe79SDavid van Moolenbroek #include "lwip/apps/fs.h"
114*5d5fbe79SDavid van Moolenbroek
115*5d5fbe79SDavid van Moolenbroek #include "../core/inet_chksum.c"
116*5d5fbe79SDavid van Moolenbroek #include "../core/def.c"
117*5d5fbe79SDavid van Moolenbroek
118*5d5fbe79SDavid van Moolenbroek /** (Your server name here) */
119*5d5fbe79SDavid van Moolenbroek const char *serverID = "Server: "HTTPD_SERVER_AGENT"\r\n";
120*5d5fbe79SDavid van Moolenbroek char serverIDBuffer[1024];
121*5d5fbe79SDavid van Moolenbroek
122*5d5fbe79SDavid van Moolenbroek /* change this to suit your MEM_ALIGNMENT */
123*5d5fbe79SDavid van Moolenbroek #define PAYLOAD_ALIGNMENT 4
124*5d5fbe79SDavid van Moolenbroek /* set this to 0 to prevent aligning payload */
125*5d5fbe79SDavid van Moolenbroek #define ALIGN_PAYLOAD 1
126*5d5fbe79SDavid van Moolenbroek /* define this to a type that has the required alignment */
127*5d5fbe79SDavid van Moolenbroek #define PAYLOAD_ALIGN_TYPE "unsigned int"
128*5d5fbe79SDavid van Moolenbroek static int payload_alingment_dummy_counter = 0;
129*5d5fbe79SDavid van Moolenbroek
130*5d5fbe79SDavid van Moolenbroek #define HEX_BYTES_PER_LINE 16
131*5d5fbe79SDavid van Moolenbroek
132*5d5fbe79SDavid van Moolenbroek #define MAX_PATH_LEN 256
133*5d5fbe79SDavid van Moolenbroek
134*5d5fbe79SDavid van Moolenbroek struct file_entry
135*5d5fbe79SDavid van Moolenbroek {
136*5d5fbe79SDavid van Moolenbroek struct file_entry* next;
137*5d5fbe79SDavid van Moolenbroek const char* filename_c;
138*5d5fbe79SDavid van Moolenbroek };
139*5d5fbe79SDavid van Moolenbroek
140*5d5fbe79SDavid van Moolenbroek int process_sub(FILE *data_file, FILE *struct_file);
141*5d5fbe79SDavid van Moolenbroek int process_file(FILE *data_file, FILE *struct_file, const char *filename);
142*5d5fbe79SDavid van Moolenbroek int file_write_http_header(FILE *data_file, const char *filename, int file_size, u16_t *http_hdr_len,
143*5d5fbe79SDavid van Moolenbroek u16_t *http_hdr_chksum, u8_t provide_content_len, int is_compressed);
144*5d5fbe79SDavid van Moolenbroek int file_put_ascii(FILE *file, const char *ascii_string, int len, int *i);
145*5d5fbe79SDavid van Moolenbroek int s_put_ascii(char *buf, const char *ascii_string, int len, int *i);
146*5d5fbe79SDavid van Moolenbroek void concat_files(const char *file1, const char *file2, const char *targetfile);
147*5d5fbe79SDavid van Moolenbroek int check_path(char* path, size_t size);
148*5d5fbe79SDavid van Moolenbroek
149*5d5fbe79SDavid van Moolenbroek /* 5 bytes per char + 3 bytes per line */
150*5d5fbe79SDavid van Moolenbroek static char file_buffer_c[COPY_BUFSIZE * 5 + ((COPY_BUFSIZE / HEX_BYTES_PER_LINE) * 3)];
151*5d5fbe79SDavid van Moolenbroek
152*5d5fbe79SDavid van Moolenbroek char curSubdir[MAX_PATH_LEN];
153*5d5fbe79SDavid van Moolenbroek char lastFileVar[MAX_PATH_LEN];
154*5d5fbe79SDavid van Moolenbroek char hdr_buf[4096];
155*5d5fbe79SDavid van Moolenbroek
156*5d5fbe79SDavid van Moolenbroek unsigned char processSubs = 1;
157*5d5fbe79SDavid van Moolenbroek unsigned char includeHttpHeader = 1;
158*5d5fbe79SDavid van Moolenbroek unsigned char useHttp11 = 0;
159*5d5fbe79SDavid van Moolenbroek unsigned char supportSsi = 1;
160*5d5fbe79SDavid van Moolenbroek unsigned char precalcChksum = 0;
161*5d5fbe79SDavid van Moolenbroek unsigned char includeLastModified = 0;
162*5d5fbe79SDavid van Moolenbroek #if MAKEFS_SUPPORT_DEFLATE
163*5d5fbe79SDavid van Moolenbroek unsigned char deflateNonSsiFiles = 0;
164*5d5fbe79SDavid van Moolenbroek size_t deflatedBytesReduced = 0;
165*5d5fbe79SDavid van Moolenbroek size_t overallDataBytes = 0;
166*5d5fbe79SDavid van Moolenbroek #endif
167*5d5fbe79SDavid van Moolenbroek
168*5d5fbe79SDavid van Moolenbroek struct file_entry* first_file = NULL;
169*5d5fbe79SDavid van Moolenbroek struct file_entry* last_file = NULL;
170*5d5fbe79SDavid van Moolenbroek
print_usage(void)171*5d5fbe79SDavid van Moolenbroek static void print_usage(void)
172*5d5fbe79SDavid van Moolenbroek {
173*5d5fbe79SDavid van Moolenbroek printf(" Usage: htmlgen [targetdir] [-s] [-e] [-i] [-11] [-nossi] [-c] [-f:<filename>] [-m] [-svr:<name>]" USAGE_ARG_DEFLATE NEWLINE NEWLINE);
174*5d5fbe79SDavid van Moolenbroek printf(" targetdir: relative or absolute path to files to convert" NEWLINE);
175*5d5fbe79SDavid van Moolenbroek printf(" switch -s: toggle processing of subdirectories (default is on)" NEWLINE);
176*5d5fbe79SDavid van Moolenbroek printf(" switch -e: exclude HTTP header from file (header is created at runtime, default is off)" NEWLINE);
177*5d5fbe79SDavid van Moolenbroek printf(" switch -11: include HTTP 1.1 header (1.0 is default)" NEWLINE);
178*5d5fbe79SDavid van Moolenbroek printf(" switch -nossi: no support for SSI (cannot calculate Content-Length for SSI)" NEWLINE);
179*5d5fbe79SDavid van Moolenbroek printf(" switch -c: precalculate checksums for all pages (default is off)" NEWLINE);
180*5d5fbe79SDavid van Moolenbroek printf(" switch -f: target filename (default is \"fsdata.c\")" NEWLINE);
181*5d5fbe79SDavid van Moolenbroek printf(" switch -m: include \"Last-Modified\" header based on file time" NEWLINE);
182*5d5fbe79SDavid van Moolenbroek printf(" switch -svr: server identifier sent in HTTP response header ('Server' field)" NEWLINE);
183*5d5fbe79SDavid van Moolenbroek #if MAKEFS_SUPPORT_DEFLATE
184*5d5fbe79SDavid van Moolenbroek printf(" switch -defl: deflate-compress all non-SSI files (with opt. compr.-level, default=10)" NEWLINE);
185*5d5fbe79SDavid van Moolenbroek printf(" ATTENTION: browser has to support \"Content-Encoding: deflate\"!" NEWLINE);
186*5d5fbe79SDavid van Moolenbroek #endif
187*5d5fbe79SDavid van Moolenbroek printf(" if targetdir not specified, htmlgen will attempt to" NEWLINE);
188*5d5fbe79SDavid van Moolenbroek printf(" process files in subdirectory 'fs'" NEWLINE);
189*5d5fbe79SDavid van Moolenbroek }
190*5d5fbe79SDavid van Moolenbroek
main(int argc,char * argv[])191*5d5fbe79SDavid van Moolenbroek int main(int argc, char *argv[])
192*5d5fbe79SDavid van Moolenbroek {
193*5d5fbe79SDavid van Moolenbroek char path[MAX_PATH_LEN];
194*5d5fbe79SDavid van Moolenbroek char appPath[MAX_PATH_LEN];
195*5d5fbe79SDavid van Moolenbroek FILE *data_file;
196*5d5fbe79SDavid van Moolenbroek FILE *struct_file;
197*5d5fbe79SDavid van Moolenbroek int filesProcessed;
198*5d5fbe79SDavid van Moolenbroek int i;
199*5d5fbe79SDavid van Moolenbroek char targetfile[MAX_PATH_LEN];
200*5d5fbe79SDavid van Moolenbroek strcpy(targetfile, "fsdata.c");
201*5d5fbe79SDavid van Moolenbroek
202*5d5fbe79SDavid van Moolenbroek memset(path, 0, sizeof(path));
203*5d5fbe79SDavid van Moolenbroek memset(appPath, 0, sizeof(appPath));
204*5d5fbe79SDavid van Moolenbroek
205*5d5fbe79SDavid van Moolenbroek printf(NEWLINE " makefsdata - HTML to C source converter" NEWLINE);
206*5d5fbe79SDavid van Moolenbroek printf(" by Jim Pettinato - circa 2003 " NEWLINE);
207*5d5fbe79SDavid van Moolenbroek printf(" extended by Simon Goldschmidt - 2009 " NEWLINE NEWLINE);
208*5d5fbe79SDavid van Moolenbroek
209*5d5fbe79SDavid van Moolenbroek strcpy(path, "fs");
210*5d5fbe79SDavid van Moolenbroek for (i = 1; i < argc; i++) {
211*5d5fbe79SDavid van Moolenbroek if (argv[i] == NULL) {
212*5d5fbe79SDavid van Moolenbroek continue;
213*5d5fbe79SDavid van Moolenbroek }
214*5d5fbe79SDavid van Moolenbroek if (argv[i][0] == '-') {
215*5d5fbe79SDavid van Moolenbroek if (strstr(argv[i], "-svr:") == argv[i]) {
216*5d5fbe79SDavid van Moolenbroek snprintf(serverIDBuffer, sizeof(serverIDBuffer), "Server: %s\r\n", &argv[i][5]);
217*5d5fbe79SDavid van Moolenbroek serverID = serverIDBuffer;
218*5d5fbe79SDavid van Moolenbroek printf("Using Server-ID: \"%s\"\n", serverID);
219*5d5fbe79SDavid van Moolenbroek } else if (strstr(argv[i], "-s") == argv[i]) {
220*5d5fbe79SDavid van Moolenbroek processSubs = 0;
221*5d5fbe79SDavid van Moolenbroek } else if (strstr(argv[i], "-e") == argv[i]) {
222*5d5fbe79SDavid van Moolenbroek includeHttpHeader = 0;
223*5d5fbe79SDavid van Moolenbroek } else if (strstr(argv[i], "-11") == argv[i]) {
224*5d5fbe79SDavid van Moolenbroek useHttp11 = 1;
225*5d5fbe79SDavid van Moolenbroek } else if (strstr(argv[i], "-nossi") == argv[i]) {
226*5d5fbe79SDavid van Moolenbroek supportSsi = 0;
227*5d5fbe79SDavid van Moolenbroek } else if (strstr(argv[i], "-c") == argv[i]) {
228*5d5fbe79SDavid van Moolenbroek precalcChksum = 1;
229*5d5fbe79SDavid van Moolenbroek } else if (strstr(argv[i], "-f:") == argv[i]) {
230*5d5fbe79SDavid van Moolenbroek strncpy(targetfile, &argv[i][3], sizeof(targetfile) - 1);
231*5d5fbe79SDavid van Moolenbroek targetfile[sizeof(targetfile) - 1] = 0;
232*5d5fbe79SDavid van Moolenbroek printf("Writing to file \"%s\"\n", targetfile);
233*5d5fbe79SDavid van Moolenbroek } else if (strstr(argv[i], "-m") == argv[i]) {
234*5d5fbe79SDavid van Moolenbroek includeLastModified = 1;
235*5d5fbe79SDavid van Moolenbroek } else if (strstr(argv[i], "-defl") == argv[i]) {
236*5d5fbe79SDavid van Moolenbroek #if MAKEFS_SUPPORT_DEFLATE
237*5d5fbe79SDavid van Moolenbroek char* colon = strstr(argv[i], ":");
238*5d5fbe79SDavid van Moolenbroek if (colon) {
239*5d5fbe79SDavid van Moolenbroek if (colon[1] != 0) {
240*5d5fbe79SDavid van Moolenbroek int defl_level = atoi(&colon[1]);
241*5d5fbe79SDavid van Moolenbroek if ((defl_level >= 0) && (defl_level <= 10)) {
242*5d5fbe79SDavid van Moolenbroek deflate_level = defl_level;
243*5d5fbe79SDavid van Moolenbroek } else {
244*5d5fbe79SDavid van Moolenbroek printf("ERROR: deflate level must be [0..10]" NEWLINE);
245*5d5fbe79SDavid van Moolenbroek exit(0);
246*5d5fbe79SDavid van Moolenbroek }
247*5d5fbe79SDavid van Moolenbroek }
248*5d5fbe79SDavid van Moolenbroek }
249*5d5fbe79SDavid van Moolenbroek deflateNonSsiFiles = 1;
250*5d5fbe79SDavid van Moolenbroek printf("Deflating all non-SSI files with level %d (but only if size is reduced)" NEWLINE, deflate_level);
251*5d5fbe79SDavid van Moolenbroek #else
252*5d5fbe79SDavid van Moolenbroek printf("WARNING: Deflate support is disabled\n");
253*5d5fbe79SDavid van Moolenbroek #endif
254*5d5fbe79SDavid van Moolenbroek } else if ((strstr(argv[i], "-?")) || (strstr(argv[i], "-h"))) {
255*5d5fbe79SDavid van Moolenbroek print_usage();
256*5d5fbe79SDavid van Moolenbroek exit(0);
257*5d5fbe79SDavid van Moolenbroek }
258*5d5fbe79SDavid van Moolenbroek } else if ((argv[i][0] == '/') && (argv[i][1] == '?') && (argv[i][2] == 0)) {
259*5d5fbe79SDavid van Moolenbroek print_usage();
260*5d5fbe79SDavid van Moolenbroek exit(0);
261*5d5fbe79SDavid van Moolenbroek } else {
262*5d5fbe79SDavid van Moolenbroek strncpy(path, argv[i], sizeof(path)-1);
263*5d5fbe79SDavid van Moolenbroek path[sizeof(path)-1] = 0;
264*5d5fbe79SDavid van Moolenbroek }
265*5d5fbe79SDavid van Moolenbroek }
266*5d5fbe79SDavid van Moolenbroek
267*5d5fbe79SDavid van Moolenbroek if (!check_path(path, sizeof(path))) {
268*5d5fbe79SDavid van Moolenbroek printf("Invalid path: \"%s\"." NEWLINE, path);
269*5d5fbe79SDavid van Moolenbroek exit(-1);
270*5d5fbe79SDavid van Moolenbroek }
271*5d5fbe79SDavid van Moolenbroek
272*5d5fbe79SDavid van Moolenbroek GETCWD(appPath, MAX_PATH_LEN);
273*5d5fbe79SDavid van Moolenbroek /* if command line param or subdir named 'fs' not found spout usage verbiage */
274*5d5fbe79SDavid van Moolenbroek if (!CHDIR_SUCCEEDED(CHDIR(path))) {
275*5d5fbe79SDavid van Moolenbroek /* if no subdir named 'fs' (or the one which was given) exists, spout usage verbiage */
276*5d5fbe79SDavid van Moolenbroek printf(" Failed to open directory \"%s\"." NEWLINE NEWLINE, path);
277*5d5fbe79SDavid van Moolenbroek print_usage();
278*5d5fbe79SDavid van Moolenbroek exit(-1);
279*5d5fbe79SDavid van Moolenbroek }
280*5d5fbe79SDavid van Moolenbroek CHDIR(appPath);
281*5d5fbe79SDavid van Moolenbroek
282*5d5fbe79SDavid van Moolenbroek printf("HTTP %sheader will %s statically included." NEWLINE,
283*5d5fbe79SDavid van Moolenbroek (includeHttpHeader ? (useHttp11 ? "1.1 " : "1.0 ") : ""),
284*5d5fbe79SDavid van Moolenbroek (includeHttpHeader ? "be" : "not be"));
285*5d5fbe79SDavid van Moolenbroek
286*5d5fbe79SDavid van Moolenbroek sprintf(curSubdir, ""); /* start off in web page's root directory - relative paths */
287*5d5fbe79SDavid van Moolenbroek printf(" Processing all files in directory %s", path);
288*5d5fbe79SDavid van Moolenbroek if (processSubs) {
289*5d5fbe79SDavid van Moolenbroek printf(" and subdirectories..." NEWLINE NEWLINE);
290*5d5fbe79SDavid van Moolenbroek } else {
291*5d5fbe79SDavid van Moolenbroek printf("..." NEWLINE NEWLINE);
292*5d5fbe79SDavid van Moolenbroek }
293*5d5fbe79SDavid van Moolenbroek
294*5d5fbe79SDavid van Moolenbroek data_file = fopen("fsdata.tmp", "wb");
295*5d5fbe79SDavid van Moolenbroek if (data_file == NULL) {
296*5d5fbe79SDavid van Moolenbroek printf("Failed to create file \"fsdata.tmp\"\n");
297*5d5fbe79SDavid van Moolenbroek exit(-1);
298*5d5fbe79SDavid van Moolenbroek }
299*5d5fbe79SDavid van Moolenbroek struct_file = fopen("fshdr.tmp", "wb");
300*5d5fbe79SDavid van Moolenbroek if (struct_file == NULL) {
301*5d5fbe79SDavid van Moolenbroek printf("Failed to create file \"fshdr.tmp\"\n");
302*5d5fbe79SDavid van Moolenbroek fclose(data_file);
303*5d5fbe79SDavid van Moolenbroek exit(-1);
304*5d5fbe79SDavid van Moolenbroek }
305*5d5fbe79SDavid van Moolenbroek
306*5d5fbe79SDavid van Moolenbroek CHDIR(path);
307*5d5fbe79SDavid van Moolenbroek
308*5d5fbe79SDavid van Moolenbroek fprintf(data_file, "#include \"lwip/apps/fs.h\"" NEWLINE);
309*5d5fbe79SDavid van Moolenbroek fprintf(data_file, "#include \"lwip/def.h\"" NEWLINE NEWLINE NEWLINE);
310*5d5fbe79SDavid van Moolenbroek
311*5d5fbe79SDavid van Moolenbroek fprintf(data_file, "#define file_NULL (struct fsdata_file *) NULL" NEWLINE NEWLINE NEWLINE);
312*5d5fbe79SDavid van Moolenbroek /* define FS_FILE_FLAGS_HEADER_INCLUDED to 1 if not defined (compatibility with older httpd/fs) */
313*5d5fbe79SDavid van Moolenbroek fprintf(data_file, "#ifndef FS_FILE_FLAGS_HEADER_INCLUDED" NEWLINE "#define FS_FILE_FLAGS_HEADER_INCLUDED 1" NEWLINE "#endif" NEWLINE);
314*5d5fbe79SDavid van Moolenbroek /* define FS_FILE_FLAGS_HEADER_PERSISTENT to 0 if not defined (compatibility with older httpd/fs: wasn't supported back then) */
315*5d5fbe79SDavid van Moolenbroek fprintf(data_file, "#ifndef FS_FILE_FLAGS_HEADER_PERSISTENT" NEWLINE "#define FS_FILE_FLAGS_HEADER_PERSISTENT 0" NEWLINE "#endif" NEWLINE);
316*5d5fbe79SDavid van Moolenbroek
317*5d5fbe79SDavid van Moolenbroek /* define alignment defines */
318*5d5fbe79SDavid van Moolenbroek #if ALIGN_PAYLOAD
319*5d5fbe79SDavid van Moolenbroek fprintf(data_file, "/* FSDATA_FILE_ALIGNMENT: 0=off, 1=by variable, 2=by include */" NEWLINE "#ifndef FSDATA_FILE_ALIGNMENT" NEWLINE "#define FSDATA_FILE_ALIGNMENT 0" NEWLINE "#endif" NEWLINE);
320*5d5fbe79SDavid van Moolenbroek #endif
321*5d5fbe79SDavid van Moolenbroek fprintf(data_file, "#ifndef FSDATA_ALIGN_PRE" NEWLINE "#define FSDATA_ALIGN_PRE" NEWLINE "#endif" NEWLINE);
322*5d5fbe79SDavid van Moolenbroek fprintf(data_file, "#ifndef FSDATA_ALIGN_POST" NEWLINE "#define FSDATA_ALIGN_POST" NEWLINE "#endif" NEWLINE);
323*5d5fbe79SDavid van Moolenbroek #if ALIGN_PAYLOAD
324*5d5fbe79SDavid van Moolenbroek fprintf(data_file, "#if FSDATA_FILE_ALIGNMENT==2" NEWLINE "#include \"fsdata_alignment.h\"" NEWLINE "#endif" NEWLINE);
325*5d5fbe79SDavid van Moolenbroek #endif
326*5d5fbe79SDavid van Moolenbroek
327*5d5fbe79SDavid van Moolenbroek sprintf(lastFileVar, "NULL");
328*5d5fbe79SDavid van Moolenbroek
329*5d5fbe79SDavid van Moolenbroek filesProcessed = process_sub(data_file, struct_file);
330*5d5fbe79SDavid van Moolenbroek
331*5d5fbe79SDavid van Moolenbroek /* data_file now contains all of the raw data.. now append linked list of
332*5d5fbe79SDavid van Moolenbroek * file header structs to allow embedded app to search for a file name */
333*5d5fbe79SDavid van Moolenbroek fprintf(data_file, NEWLINE NEWLINE);
334*5d5fbe79SDavid van Moolenbroek fprintf(struct_file, "#define FS_ROOT file_%s" NEWLINE, lastFileVar);
335*5d5fbe79SDavid van Moolenbroek fprintf(struct_file, "#define FS_NUMFILES %d" NEWLINE NEWLINE, filesProcessed);
336*5d5fbe79SDavid van Moolenbroek
337*5d5fbe79SDavid van Moolenbroek fclose(data_file);
338*5d5fbe79SDavid van Moolenbroek fclose(struct_file);
339*5d5fbe79SDavid van Moolenbroek
340*5d5fbe79SDavid van Moolenbroek CHDIR(appPath);
341*5d5fbe79SDavid van Moolenbroek /* append struct_file to data_file */
342*5d5fbe79SDavid van Moolenbroek printf(NEWLINE "Creating target file..." NEWLINE NEWLINE);
343*5d5fbe79SDavid van Moolenbroek concat_files("fsdata.tmp", "fshdr.tmp", targetfile);
344*5d5fbe79SDavid van Moolenbroek
345*5d5fbe79SDavid van Moolenbroek /* if succeeded, delete the temporary files */
346*5d5fbe79SDavid van Moolenbroek if (remove("fsdata.tmp") != 0) {
347*5d5fbe79SDavid van Moolenbroek printf("Warning: failed to delete fsdata.tmp\n");
348*5d5fbe79SDavid van Moolenbroek }
349*5d5fbe79SDavid van Moolenbroek if (remove("fshdr.tmp") != 0) {
350*5d5fbe79SDavid van Moolenbroek printf("Warning: failed to delete fshdr.tmp\n");
351*5d5fbe79SDavid van Moolenbroek }
352*5d5fbe79SDavid van Moolenbroek
353*5d5fbe79SDavid van Moolenbroek printf(NEWLINE "Processed %d files - done." NEWLINE, filesProcessed);
354*5d5fbe79SDavid van Moolenbroek #if MAKEFS_SUPPORT_DEFLATE
355*5d5fbe79SDavid van Moolenbroek if (deflateNonSsiFiles) {
356*5d5fbe79SDavid van Moolenbroek printf("(Deflated total byte reduction: %d bytes -> %d bytes (%.02f%%)" NEWLINE,
357*5d5fbe79SDavid van Moolenbroek (int)overallDataBytes, (int)deflatedBytesReduced, (float)((deflatedBytesReduced*100.0)/overallDataBytes));
358*5d5fbe79SDavid van Moolenbroek }
359*5d5fbe79SDavid van Moolenbroek #endif
360*5d5fbe79SDavid van Moolenbroek printf(NEWLINE);
361*5d5fbe79SDavid van Moolenbroek
362*5d5fbe79SDavid van Moolenbroek while (first_file != NULL) {
363*5d5fbe79SDavid van Moolenbroek struct file_entry* fe = first_file;
364*5d5fbe79SDavid van Moolenbroek first_file = fe->next;
365*5d5fbe79SDavid van Moolenbroek free(fe);
366*5d5fbe79SDavid van Moolenbroek }
367*5d5fbe79SDavid van Moolenbroek
368*5d5fbe79SDavid van Moolenbroek return 0;
369*5d5fbe79SDavid van Moolenbroek }
370*5d5fbe79SDavid van Moolenbroek
check_path(char * path,size_t size)371*5d5fbe79SDavid van Moolenbroek int check_path(char* path, size_t size)
372*5d5fbe79SDavid van Moolenbroek {
373*5d5fbe79SDavid van Moolenbroek size_t slen;
374*5d5fbe79SDavid van Moolenbroek if (path[0] == 0) {
375*5d5fbe79SDavid van Moolenbroek /* empty */
376*5d5fbe79SDavid van Moolenbroek return 0;
377*5d5fbe79SDavid van Moolenbroek }
378*5d5fbe79SDavid van Moolenbroek slen = strlen(path);
379*5d5fbe79SDavid van Moolenbroek if (slen >= size) {
380*5d5fbe79SDavid van Moolenbroek /* not NULL-terminated */
381*5d5fbe79SDavid van Moolenbroek return 0;
382*5d5fbe79SDavid van Moolenbroek }
383*5d5fbe79SDavid van Moolenbroek while ((slen > 0) && ((path[slen] == '\\') || (path[slen] == '/'))) {
384*5d5fbe79SDavid van Moolenbroek /* path should not end with trailing backslash */
385*5d5fbe79SDavid van Moolenbroek path[slen] = 0;
386*5d5fbe79SDavid van Moolenbroek slen--;
387*5d5fbe79SDavid van Moolenbroek }
388*5d5fbe79SDavid van Moolenbroek if (slen == 0) {
389*5d5fbe79SDavid van Moolenbroek return 0;
390*5d5fbe79SDavid van Moolenbroek }
391*5d5fbe79SDavid van Moolenbroek return 1;
392*5d5fbe79SDavid van Moolenbroek }
393*5d5fbe79SDavid van Moolenbroek
copy_file(const char * filename_in,FILE * fout)394*5d5fbe79SDavid van Moolenbroek static void copy_file(const char *filename_in, FILE *fout)
395*5d5fbe79SDavid van Moolenbroek {
396*5d5fbe79SDavid van Moolenbroek FILE *fin;
397*5d5fbe79SDavid van Moolenbroek size_t len;
398*5d5fbe79SDavid van Moolenbroek void* buf;
399*5d5fbe79SDavid van Moolenbroek fin = fopen(filename_in, "rb");
400*5d5fbe79SDavid van Moolenbroek if (fin == NULL) {
401*5d5fbe79SDavid van Moolenbroek printf("Failed to open file \"%s\"\n", filename_in);
402*5d5fbe79SDavid van Moolenbroek exit(-1);
403*5d5fbe79SDavid van Moolenbroek }
404*5d5fbe79SDavid van Moolenbroek buf = malloc(COPY_BUFSIZE);
405*5d5fbe79SDavid van Moolenbroek while ((len = fread(buf, 1, COPY_BUFSIZE, fin)) > 0) {
406*5d5fbe79SDavid van Moolenbroek fwrite(buf, 1, len, fout);
407*5d5fbe79SDavid van Moolenbroek }
408*5d5fbe79SDavid van Moolenbroek free(buf);
409*5d5fbe79SDavid van Moolenbroek fclose(fin);
410*5d5fbe79SDavid van Moolenbroek }
411*5d5fbe79SDavid van Moolenbroek
concat_files(const char * file1,const char * file2,const char * targetfile)412*5d5fbe79SDavid van Moolenbroek void concat_files(const char *file1, const char *file2, const char *targetfile)
413*5d5fbe79SDavid van Moolenbroek {
414*5d5fbe79SDavid van Moolenbroek FILE *fout;
415*5d5fbe79SDavid van Moolenbroek fout = fopen(targetfile, "wb");
416*5d5fbe79SDavid van Moolenbroek if (fout == NULL) {
417*5d5fbe79SDavid van Moolenbroek printf("Failed to open file \"%s\"\n", targetfile);
418*5d5fbe79SDavid van Moolenbroek exit(-1);
419*5d5fbe79SDavid van Moolenbroek }
420*5d5fbe79SDavid van Moolenbroek copy_file(file1, fout);
421*5d5fbe79SDavid van Moolenbroek copy_file(file2, fout);
422*5d5fbe79SDavid van Moolenbroek fclose(fout);
423*5d5fbe79SDavid van Moolenbroek }
424*5d5fbe79SDavid van Moolenbroek
process_sub(FILE * data_file,FILE * struct_file)425*5d5fbe79SDavid van Moolenbroek int process_sub(FILE *data_file, FILE *struct_file)
426*5d5fbe79SDavid van Moolenbroek {
427*5d5fbe79SDavid van Moolenbroek FIND_T fInfo;
428*5d5fbe79SDavid van Moolenbroek FIND_RET_T fret;
429*5d5fbe79SDavid van Moolenbroek int filesProcessed = 0;
430*5d5fbe79SDavid van Moolenbroek
431*5d5fbe79SDavid van Moolenbroek if (processSubs) {
432*5d5fbe79SDavid van Moolenbroek /* process subs recursively */
433*5d5fbe79SDavid van Moolenbroek size_t sublen = strlen(curSubdir);
434*5d5fbe79SDavid van Moolenbroek size_t freelen = sizeof(curSubdir) - sublen - 1;
435*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("sublen < sizeof(curSubdir)", sublen < sizeof(curSubdir));
436*5d5fbe79SDavid van Moolenbroek fret = FINDFIRST_DIR("*", &fInfo);
437*5d5fbe79SDavid van Moolenbroek if (FINDFIRST_SUCCEEDED(fret)) {
438*5d5fbe79SDavid van Moolenbroek do {
439*5d5fbe79SDavid van Moolenbroek const char *curName = FIND_T_FILENAME(fInfo);
440*5d5fbe79SDavid van Moolenbroek if ((curName[0] == '.') || (strcmp(curName, "CVS") == 0)) {
441*5d5fbe79SDavid van Moolenbroek continue;
442*5d5fbe79SDavid van Moolenbroek }
443*5d5fbe79SDavid van Moolenbroek if (!FIND_T_IS_DIR(fInfo)) {
444*5d5fbe79SDavid van Moolenbroek continue;
445*5d5fbe79SDavid van Moolenbroek }
446*5d5fbe79SDavid van Moolenbroek if (freelen > 0) {
447*5d5fbe79SDavid van Moolenbroek CHDIR(curName);
448*5d5fbe79SDavid van Moolenbroek strncat(curSubdir, "/", freelen);
449*5d5fbe79SDavid van Moolenbroek strncat(curSubdir, curName, freelen - 1);
450*5d5fbe79SDavid van Moolenbroek curSubdir[sizeof(curSubdir) - 1] = 0;
451*5d5fbe79SDavid van Moolenbroek printf("processing subdirectory %s/..." NEWLINE, curSubdir);
452*5d5fbe79SDavid van Moolenbroek filesProcessed += process_sub(data_file, struct_file);
453*5d5fbe79SDavid van Moolenbroek CHDIR("..");
454*5d5fbe79SDavid van Moolenbroek curSubdir[sublen] = 0;
455*5d5fbe79SDavid van Moolenbroek } else {
456*5d5fbe79SDavid van Moolenbroek printf("WARNING: cannot process sub due to path length restrictions: \"%s/%s\"\n", curSubdir, curName);
457*5d5fbe79SDavid van Moolenbroek }
458*5d5fbe79SDavid van Moolenbroek } while (FINDNEXT_SUCCEEDED(FINDNEXT(fret, &fInfo)));
459*5d5fbe79SDavid van Moolenbroek }
460*5d5fbe79SDavid van Moolenbroek }
461*5d5fbe79SDavid van Moolenbroek
462*5d5fbe79SDavid van Moolenbroek fret = FINDFIRST_FILE("*.*", &fInfo);
463*5d5fbe79SDavid van Moolenbroek if (FINDFIRST_SUCCEEDED(fret)) {
464*5d5fbe79SDavid van Moolenbroek /* at least one file in directory */
465*5d5fbe79SDavid van Moolenbroek do {
466*5d5fbe79SDavid van Moolenbroek if (FIND_T_IS_FILE(fInfo)) {
467*5d5fbe79SDavid van Moolenbroek const char *curName = FIND_T_FILENAME(fInfo);
468*5d5fbe79SDavid van Moolenbroek printf("processing %s/%s..." NEWLINE, curSubdir, curName);
469*5d5fbe79SDavid van Moolenbroek if (process_file(data_file, struct_file, curName) < 0) {
470*5d5fbe79SDavid van Moolenbroek printf(NEWLINE "Error... aborting" NEWLINE);
471*5d5fbe79SDavid van Moolenbroek return -1;
472*5d5fbe79SDavid van Moolenbroek }
473*5d5fbe79SDavid van Moolenbroek filesProcessed++;
474*5d5fbe79SDavid van Moolenbroek }
475*5d5fbe79SDavid van Moolenbroek } while (FINDNEXT_SUCCEEDED(FINDNEXT(fret, &fInfo)));
476*5d5fbe79SDavid van Moolenbroek }
477*5d5fbe79SDavid van Moolenbroek return filesProcessed;
478*5d5fbe79SDavid van Moolenbroek }
479*5d5fbe79SDavid van Moolenbroek
get_file_data(const char * filename,int * file_size,int can_be_compressed,int * is_compressed)480*5d5fbe79SDavid van Moolenbroek u8_t* get_file_data(const char* filename, int* file_size, int can_be_compressed, int* is_compressed)
481*5d5fbe79SDavid van Moolenbroek {
482*5d5fbe79SDavid van Moolenbroek FILE *inFile;
483*5d5fbe79SDavid van Moolenbroek size_t fsize = 0;
484*5d5fbe79SDavid van Moolenbroek u8_t* buf;
485*5d5fbe79SDavid van Moolenbroek size_t r;
486*5d5fbe79SDavid van Moolenbroek int rs;
487*5d5fbe79SDavid van Moolenbroek inFile = fopen(filename, "rb");
488*5d5fbe79SDavid van Moolenbroek if (inFile == NULL) {
489*5d5fbe79SDavid van Moolenbroek printf("Failed to open file \"%s\"\n", filename);
490*5d5fbe79SDavid van Moolenbroek exit(-1);
491*5d5fbe79SDavid van Moolenbroek }
492*5d5fbe79SDavid van Moolenbroek fseek(inFile, 0, SEEK_END);
493*5d5fbe79SDavid van Moolenbroek rs = ftell(inFile);
494*5d5fbe79SDavid van Moolenbroek if (rs < 0) {
495*5d5fbe79SDavid van Moolenbroek printf("ftell failed with %d\n", errno);
496*5d5fbe79SDavid van Moolenbroek exit(-1);
497*5d5fbe79SDavid van Moolenbroek }
498*5d5fbe79SDavid van Moolenbroek fsize = (size_t)rs;
499*5d5fbe79SDavid van Moolenbroek fseek(inFile, 0, SEEK_SET);
500*5d5fbe79SDavid van Moolenbroek buf = (u8_t*)malloc(fsize);
501*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("buf != NULL", buf != NULL);
502*5d5fbe79SDavid van Moolenbroek r = fread(buf, 1, fsize, inFile);
503*5d5fbe79SDavid van Moolenbroek *file_size = fsize;
504*5d5fbe79SDavid van Moolenbroek *is_compressed = 0;
505*5d5fbe79SDavid van Moolenbroek #if MAKEFS_SUPPORT_DEFLATE
506*5d5fbe79SDavid van Moolenbroek overallDataBytes += fsize;
507*5d5fbe79SDavid van Moolenbroek if (deflateNonSsiFiles) {
508*5d5fbe79SDavid van Moolenbroek if (can_be_compressed) {
509*5d5fbe79SDavid van Moolenbroek if (fsize < OUT_BUF_SIZE) {
510*5d5fbe79SDavid van Moolenbroek u8_t* ret_buf;
511*5d5fbe79SDavid van Moolenbroek tdefl_status status;
512*5d5fbe79SDavid van Moolenbroek size_t in_bytes = fsize;
513*5d5fbe79SDavid van Moolenbroek size_t out_bytes = OUT_BUF_SIZE;
514*5d5fbe79SDavid van Moolenbroek const void *next_in = buf;
515*5d5fbe79SDavid van Moolenbroek void *next_out = s_outbuf;
516*5d5fbe79SDavid van Moolenbroek /* create tdefl() compatible flags (we have to compose the low-level flags ourselves, or use tdefl_create_comp_flags_from_zip_params() but that means MINIZ_NO_ZLIB_APIS can't be defined). */
517*5d5fbe79SDavid van Moolenbroek mz_uint comp_flags = s_tdefl_num_probes[MZ_MIN(10, deflate_level)] | ((deflate_level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
518*5d5fbe79SDavid van Moolenbroek if (!deflate_level) {
519*5d5fbe79SDavid van Moolenbroek comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
520*5d5fbe79SDavid van Moolenbroek }
521*5d5fbe79SDavid van Moolenbroek status = tdefl_init(&g_deflator, NULL, NULL, comp_flags);
522*5d5fbe79SDavid van Moolenbroek if (status != TDEFL_STATUS_OKAY) {
523*5d5fbe79SDavid van Moolenbroek printf("tdefl_init() failed!\n");
524*5d5fbe79SDavid van Moolenbroek exit(-1);
525*5d5fbe79SDavid van Moolenbroek }
526*5d5fbe79SDavid van Moolenbroek memset(s_outbuf, 0, sizeof(s_outbuf));
527*5d5fbe79SDavid van Moolenbroek status = tdefl_compress(&g_deflator, next_in, &in_bytes, next_out, &out_bytes, TDEFL_FINISH);
528*5d5fbe79SDavid van Moolenbroek if (status != TDEFL_STATUS_DONE) {
529*5d5fbe79SDavid van Moolenbroek printf("deflate failed: %d\n", status);
530*5d5fbe79SDavid van Moolenbroek exit(-1);
531*5d5fbe79SDavid van Moolenbroek }
532*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("out_bytes <= COPY_BUFSIZE", out_bytes <= OUT_BUF_SIZE);
533*5d5fbe79SDavid van Moolenbroek if (out_bytes < fsize) {
534*5d5fbe79SDavid van Moolenbroek ret_buf = (u8_t*)malloc(out_bytes);
535*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("ret_buf != NULL", ret_buf != NULL);
536*5d5fbe79SDavid van Moolenbroek memcpy(ret_buf, s_outbuf, out_bytes);
537*5d5fbe79SDavid van Moolenbroek {
538*5d5fbe79SDavid van Moolenbroek /* sanity-check compression be inflating and comparing to the original */
539*5d5fbe79SDavid van Moolenbroek tinfl_status dec_status;
540*5d5fbe79SDavid van Moolenbroek tinfl_decompressor inflator;
541*5d5fbe79SDavid van Moolenbroek size_t dec_in_bytes = out_bytes;
542*5d5fbe79SDavid van Moolenbroek size_t dec_out_bytes = OUT_BUF_SIZE;
543*5d5fbe79SDavid van Moolenbroek next_out = s_checkbuf;
544*5d5fbe79SDavid van Moolenbroek
545*5d5fbe79SDavid van Moolenbroek tinfl_init(&inflator);
546*5d5fbe79SDavid van Moolenbroek memset(s_checkbuf, 0, sizeof(s_checkbuf));
547*5d5fbe79SDavid van Moolenbroek dec_status = tinfl_decompress(&inflator, (const mz_uint8 *)ret_buf, &dec_in_bytes, s_checkbuf, (mz_uint8 *)next_out, &dec_out_bytes, 0);
548*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("tinfl_decompress failed", dec_status == TINFL_STATUS_DONE);
549*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("tinfl_decompress size mismatch", fsize == dec_out_bytes);
550*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("decompressed memcmp failed", !memcmp(s_checkbuf, buf, fsize));
551*5d5fbe79SDavid van Moolenbroek }
552*5d5fbe79SDavid van Moolenbroek /* free original buffer, use compressed data + size */
553*5d5fbe79SDavid van Moolenbroek free(buf);
554*5d5fbe79SDavid van Moolenbroek buf = ret_buf;
555*5d5fbe79SDavid van Moolenbroek *file_size = out_bytes;
556*5d5fbe79SDavid van Moolenbroek printf(" - deflate: %d bytes -> %d bytes (%.02f%%)" NEWLINE, (int)fsize, (int)out_bytes, (float)((out_bytes*100.0)/fsize));
557*5d5fbe79SDavid van Moolenbroek deflatedBytesReduced += (size_t)(fsize - out_bytes);
558*5d5fbe79SDavid van Moolenbroek *is_compressed = 1;
559*5d5fbe79SDavid van Moolenbroek } else {
560*5d5fbe79SDavid van Moolenbroek printf(" - uncompressed: (would be %d bytes larger using deflate)" NEWLINE, (int)(out_bytes - fsize));
561*5d5fbe79SDavid van Moolenbroek }
562*5d5fbe79SDavid van Moolenbroek } else {
563*5d5fbe79SDavid van Moolenbroek printf(" - uncompressed: (file is larger than deflate bufer)" NEWLINE);
564*5d5fbe79SDavid van Moolenbroek }
565*5d5fbe79SDavid van Moolenbroek } else {
566*5d5fbe79SDavid van Moolenbroek printf(" - SSI file, cannot be compressed" NEWLINE);
567*5d5fbe79SDavid van Moolenbroek }
568*5d5fbe79SDavid van Moolenbroek }
569*5d5fbe79SDavid van Moolenbroek #else
570*5d5fbe79SDavid van Moolenbroek LWIP_UNUSED_ARG(can_be_compressed);
571*5d5fbe79SDavid van Moolenbroek #endif
572*5d5fbe79SDavid van Moolenbroek fclose(inFile);
573*5d5fbe79SDavid van Moolenbroek return buf;
574*5d5fbe79SDavid van Moolenbroek }
575*5d5fbe79SDavid van Moolenbroek
process_file_data(FILE * data_file,u8_t * file_data,size_t file_size)576*5d5fbe79SDavid van Moolenbroek void process_file_data(FILE* data_file, u8_t* file_data, size_t file_size)
577*5d5fbe79SDavid van Moolenbroek {
578*5d5fbe79SDavid van Moolenbroek size_t written, i, src_off=0;
579*5d5fbe79SDavid van Moolenbroek
580*5d5fbe79SDavid van Moolenbroek size_t off = 0;
581*5d5fbe79SDavid van Moolenbroek for (i = 0; i < file_size; i++) {
582*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("file_buffer_c overflow", off < sizeof(file_buffer_c) - 5);
583*5d5fbe79SDavid van Moolenbroek sprintf(&file_buffer_c[off], "0x%02.2x,", file_data[i]);
584*5d5fbe79SDavid van Moolenbroek off += 5;
585*5d5fbe79SDavid van Moolenbroek if ((++src_off % HEX_BYTES_PER_LINE) == 0) {
586*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("file_buffer_c overflow", off < sizeof(file_buffer_c) - NEWLINE_LEN);
587*5d5fbe79SDavid van Moolenbroek memcpy(&file_buffer_c[off], NEWLINE, NEWLINE_LEN);
588*5d5fbe79SDavid van Moolenbroek off += NEWLINE_LEN;
589*5d5fbe79SDavid van Moolenbroek }
590*5d5fbe79SDavid van Moolenbroek if (off + 20 >= sizeof(file_buffer_c)) {
591*5d5fbe79SDavid van Moolenbroek written = fwrite(file_buffer_c, 1, off, data_file);
592*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("written == off", written == off);
593*5d5fbe79SDavid van Moolenbroek off = 0;
594*5d5fbe79SDavid van Moolenbroek }
595*5d5fbe79SDavid van Moolenbroek }
596*5d5fbe79SDavid van Moolenbroek written = fwrite(file_buffer_c, 1, off, data_file);
597*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("written == off", written == off);
598*5d5fbe79SDavid van Moolenbroek }
599*5d5fbe79SDavid van Moolenbroek
write_checksums(FILE * struct_file,const char * varname,u16_t hdr_len,u16_t hdr_chksum,const u8_t * file_data,size_t file_size)600*5d5fbe79SDavid van Moolenbroek int write_checksums(FILE *struct_file, const char *varname,
601*5d5fbe79SDavid van Moolenbroek u16_t hdr_len, u16_t hdr_chksum, const u8_t* file_data, size_t file_size)
602*5d5fbe79SDavid van Moolenbroek {
603*5d5fbe79SDavid van Moolenbroek int chunk_size = TCP_MSS;
604*5d5fbe79SDavid van Moolenbroek int offset, src_offset;
605*5d5fbe79SDavid van Moolenbroek size_t len;
606*5d5fbe79SDavid van Moolenbroek int i = 0;
607*5d5fbe79SDavid van Moolenbroek #if LWIP_TCP_TIMESTAMPS
608*5d5fbe79SDavid van Moolenbroek /* when timestamps are used, usable space is 12 bytes less per segment */
609*5d5fbe79SDavid van Moolenbroek chunk_size -= 12;
610*5d5fbe79SDavid van Moolenbroek #endif
611*5d5fbe79SDavid van Moolenbroek
612*5d5fbe79SDavid van Moolenbroek fprintf(struct_file, "#if HTTPD_PRECALCULATED_CHECKSUM" NEWLINE);
613*5d5fbe79SDavid van Moolenbroek fprintf(struct_file, "const struct fsdata_chksum chksums_%s[] = {" NEWLINE, varname);
614*5d5fbe79SDavid van Moolenbroek
615*5d5fbe79SDavid van Moolenbroek if (hdr_len > 0) {
616*5d5fbe79SDavid van Moolenbroek /* add checksum for HTTP header */
617*5d5fbe79SDavid van Moolenbroek fprintf(struct_file, "{%d, 0x%04x, %d}," NEWLINE, 0, hdr_chksum, hdr_len);
618*5d5fbe79SDavid van Moolenbroek i++;
619*5d5fbe79SDavid van Moolenbroek }
620*5d5fbe79SDavid van Moolenbroek src_offset = 0;
621*5d5fbe79SDavid van Moolenbroek for (offset = hdr_len; ; offset += len) {
622*5d5fbe79SDavid van Moolenbroek unsigned short chksum;
623*5d5fbe79SDavid van Moolenbroek void* data = (void*)&file_data[src_offset];
624*5d5fbe79SDavid van Moolenbroek len = LWIP_MIN(chunk_size, (int)file_size - src_offset);
625*5d5fbe79SDavid van Moolenbroek if (len == 0) {
626*5d5fbe79SDavid van Moolenbroek break;
627*5d5fbe79SDavid van Moolenbroek }
628*5d5fbe79SDavid van Moolenbroek chksum = ~inet_chksum(data, (u16_t)len);
629*5d5fbe79SDavid van Moolenbroek /* add checksum for data */
630*5d5fbe79SDavid van Moolenbroek fprintf(struct_file, "{%d, 0x%04x, %d}," NEWLINE, offset, chksum, len);
631*5d5fbe79SDavid van Moolenbroek i++;
632*5d5fbe79SDavid van Moolenbroek }
633*5d5fbe79SDavid van Moolenbroek fprintf(struct_file, "};" NEWLINE);
634*5d5fbe79SDavid van Moolenbroek fprintf(struct_file, "#endif /* HTTPD_PRECALCULATED_CHECKSUM */" NEWLINE);
635*5d5fbe79SDavid van Moolenbroek return i;
636*5d5fbe79SDavid van Moolenbroek }
637*5d5fbe79SDavid van Moolenbroek
is_valid_char_for_c_var(char x)638*5d5fbe79SDavid van Moolenbroek static int is_valid_char_for_c_var(char x)
639*5d5fbe79SDavid van Moolenbroek {
640*5d5fbe79SDavid van Moolenbroek if (((x >= 'A') && (x <= 'Z')) ||
641*5d5fbe79SDavid van Moolenbroek ((x >= 'a') && (x <= 'z')) ||
642*5d5fbe79SDavid van Moolenbroek ((x >= '0') && (x <= '9')) ||
643*5d5fbe79SDavid van Moolenbroek (x == '_')) {
644*5d5fbe79SDavid van Moolenbroek return 1;
645*5d5fbe79SDavid van Moolenbroek }
646*5d5fbe79SDavid van Moolenbroek return 0;
647*5d5fbe79SDavid van Moolenbroek }
648*5d5fbe79SDavid van Moolenbroek
fix_filename_for_c(char * qualifiedName,size_t max_len)649*5d5fbe79SDavid van Moolenbroek static void fix_filename_for_c(char* qualifiedName, size_t max_len)
650*5d5fbe79SDavid van Moolenbroek {
651*5d5fbe79SDavid van Moolenbroek struct file_entry* f;
652*5d5fbe79SDavid van Moolenbroek size_t len = strlen(qualifiedName);
653*5d5fbe79SDavid van Moolenbroek char *new_name = (char*)malloc(len + 2);
654*5d5fbe79SDavid van Moolenbroek int filename_ok;
655*5d5fbe79SDavid van Moolenbroek int cnt = 0;
656*5d5fbe79SDavid van Moolenbroek size_t i;
657*5d5fbe79SDavid van Moolenbroek if (len + 3 == max_len) {
658*5d5fbe79SDavid van Moolenbroek printf("File name too long: \"%s\"\n", qualifiedName);
659*5d5fbe79SDavid van Moolenbroek exit(-1);
660*5d5fbe79SDavid van Moolenbroek }
661*5d5fbe79SDavid van Moolenbroek strcpy(new_name, qualifiedName);
662*5d5fbe79SDavid van Moolenbroek for (i = 0; i < len; i++) {
663*5d5fbe79SDavid van Moolenbroek if (!is_valid_char_for_c_var(new_name[i])) {
664*5d5fbe79SDavid van Moolenbroek new_name[i] = '_';
665*5d5fbe79SDavid van Moolenbroek }
666*5d5fbe79SDavid van Moolenbroek }
667*5d5fbe79SDavid van Moolenbroek do {
668*5d5fbe79SDavid van Moolenbroek filename_ok = 1;
669*5d5fbe79SDavid van Moolenbroek for (f = first_file; f != NULL; f = f->next) {
670*5d5fbe79SDavid van Moolenbroek if (!strcmp(f->filename_c, new_name)) {
671*5d5fbe79SDavid van Moolenbroek filename_ok = 0;
672*5d5fbe79SDavid van Moolenbroek cnt++;
673*5d5fbe79SDavid van Moolenbroek /* try next unique file name */
674*5d5fbe79SDavid van Moolenbroek sprintf(&new_name[len], "%d", cnt);
675*5d5fbe79SDavid van Moolenbroek break;
676*5d5fbe79SDavid van Moolenbroek }
677*5d5fbe79SDavid van Moolenbroek }
678*5d5fbe79SDavid van Moolenbroek } while (!filename_ok && (cnt < 999));
679*5d5fbe79SDavid van Moolenbroek if (!filename_ok) {
680*5d5fbe79SDavid van Moolenbroek printf("Failed to get unique file name: \"%s\"\n", qualifiedName);
681*5d5fbe79SDavid van Moolenbroek exit(-1);
682*5d5fbe79SDavid van Moolenbroek }
683*5d5fbe79SDavid van Moolenbroek strcpy(qualifiedName, new_name);
684*5d5fbe79SDavid van Moolenbroek free(new_name);
685*5d5fbe79SDavid van Moolenbroek }
686*5d5fbe79SDavid van Moolenbroek
register_filename(const char * qualifiedName)687*5d5fbe79SDavid van Moolenbroek static void register_filename(const char* qualifiedName)
688*5d5fbe79SDavid van Moolenbroek {
689*5d5fbe79SDavid van Moolenbroek struct file_entry* fe = (struct file_entry*)malloc(sizeof(struct file_entry));
690*5d5fbe79SDavid van Moolenbroek fe->filename_c = strdup(qualifiedName);
691*5d5fbe79SDavid van Moolenbroek fe->next = NULL;
692*5d5fbe79SDavid van Moolenbroek if (first_file == NULL) {
693*5d5fbe79SDavid van Moolenbroek first_file = last_file = fe;
694*5d5fbe79SDavid van Moolenbroek } else {
695*5d5fbe79SDavid van Moolenbroek last_file->next = fe;
696*5d5fbe79SDavid van Moolenbroek last_file = fe;
697*5d5fbe79SDavid van Moolenbroek }
698*5d5fbe79SDavid van Moolenbroek }
699*5d5fbe79SDavid van Moolenbroek
is_ssi_file(const char * filename)700*5d5fbe79SDavid van Moolenbroek int is_ssi_file(const char* filename)
701*5d5fbe79SDavid van Moolenbroek {
702*5d5fbe79SDavid van Moolenbroek size_t loop;
703*5d5fbe79SDavid van Moolenbroek for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) {
704*5d5fbe79SDavid van Moolenbroek if (strstr(filename, g_pcSSIExtensions[loop])) {
705*5d5fbe79SDavid van Moolenbroek return 1;
706*5d5fbe79SDavid van Moolenbroek }
707*5d5fbe79SDavid van Moolenbroek }
708*5d5fbe79SDavid van Moolenbroek return 0;
709*5d5fbe79SDavid van Moolenbroek }
710*5d5fbe79SDavid van Moolenbroek
process_file(FILE * data_file,FILE * struct_file,const char * filename)711*5d5fbe79SDavid van Moolenbroek int process_file(FILE *data_file, FILE *struct_file, const char *filename)
712*5d5fbe79SDavid van Moolenbroek {
713*5d5fbe79SDavid van Moolenbroek char varname[MAX_PATH_LEN];
714*5d5fbe79SDavid van Moolenbroek int i = 0;
715*5d5fbe79SDavid van Moolenbroek char qualifiedName[MAX_PATH_LEN];
716*5d5fbe79SDavid van Moolenbroek int file_size;
717*5d5fbe79SDavid van Moolenbroek u16_t http_hdr_chksum = 0;
718*5d5fbe79SDavid van Moolenbroek u16_t http_hdr_len = 0;
719*5d5fbe79SDavid van Moolenbroek int chksum_count = 0;
720*5d5fbe79SDavid van Moolenbroek u8_t flags = 0;
721*5d5fbe79SDavid van Moolenbroek const char* flags_str;
722*5d5fbe79SDavid van Moolenbroek u8_t has_content_len;
723*5d5fbe79SDavid van Moolenbroek u8_t* file_data;
724*5d5fbe79SDavid van Moolenbroek int is_compressed = 0;
725*5d5fbe79SDavid van Moolenbroek
726*5d5fbe79SDavid van Moolenbroek /* create qualified name (@todo: prepend slash or not?) */
727*5d5fbe79SDavid van Moolenbroek sprintf(qualifiedName,"%s/%s", curSubdir, filename);
728*5d5fbe79SDavid van Moolenbroek /* create C variable name */
729*5d5fbe79SDavid van Moolenbroek strcpy(varname, qualifiedName);
730*5d5fbe79SDavid van Moolenbroek /* convert slashes & dots to underscores */
731*5d5fbe79SDavid van Moolenbroek fix_filename_for_c(varname, MAX_PATH_LEN);
732*5d5fbe79SDavid van Moolenbroek register_filename(varname);
733*5d5fbe79SDavid van Moolenbroek #if ALIGN_PAYLOAD
734*5d5fbe79SDavid van Moolenbroek /* to force even alignment of array, type 1 */
735*5d5fbe79SDavid van Moolenbroek fprintf(data_file, "#if FSDATA_FILE_ALIGNMENT==1" NEWLINE);
736*5d5fbe79SDavid van Moolenbroek fprintf(data_file, "static const " PAYLOAD_ALIGN_TYPE " dummy_align_%s = %d;" NEWLINE, varname, payload_alingment_dummy_counter++);
737*5d5fbe79SDavid van Moolenbroek fprintf(data_file, "#endif" NEWLINE);
738*5d5fbe79SDavid van Moolenbroek #endif /* ALIGN_PAYLOAD */
739*5d5fbe79SDavid van Moolenbroek fprintf(data_file, "static const unsigned char FSDATA_ALIGN_PRE data_%s[] FSDATA_ALIGN_POST = {" NEWLINE, varname);
740*5d5fbe79SDavid van Moolenbroek /* encode source file name (used by file system, not returned to browser) */
741*5d5fbe79SDavid van Moolenbroek fprintf(data_file, "/* %s (%d chars) */" NEWLINE, qualifiedName, strlen(qualifiedName)+1);
742*5d5fbe79SDavid van Moolenbroek file_put_ascii(data_file, qualifiedName, strlen(qualifiedName)+1, &i);
743*5d5fbe79SDavid van Moolenbroek #if ALIGN_PAYLOAD
744*5d5fbe79SDavid van Moolenbroek /* pad to even number of bytes to assure payload is on aligned boundary */
745*5d5fbe79SDavid van Moolenbroek while(i % PAYLOAD_ALIGNMENT != 0) {
746*5d5fbe79SDavid van Moolenbroek fprintf(data_file, "0x%02.2x,", 0);
747*5d5fbe79SDavid van Moolenbroek i++;
748*5d5fbe79SDavid van Moolenbroek }
749*5d5fbe79SDavid van Moolenbroek #endif /* ALIGN_PAYLOAD */
750*5d5fbe79SDavid van Moolenbroek fprintf(data_file, NEWLINE);
751*5d5fbe79SDavid van Moolenbroek
752*5d5fbe79SDavid van Moolenbroek has_content_len = !is_ssi_file(filename);
753*5d5fbe79SDavid van Moolenbroek file_data = get_file_data(filename, &file_size, includeHttpHeader && has_content_len, &is_compressed);
754*5d5fbe79SDavid van Moolenbroek if (includeHttpHeader) {
755*5d5fbe79SDavid van Moolenbroek file_write_http_header(data_file, filename, file_size, &http_hdr_len, &http_hdr_chksum, has_content_len, is_compressed);
756*5d5fbe79SDavid van Moolenbroek flags = FS_FILE_FLAGS_HEADER_INCLUDED;
757*5d5fbe79SDavid van Moolenbroek if (has_content_len) {
758*5d5fbe79SDavid van Moolenbroek flags |= FS_FILE_FLAGS_HEADER_PERSISTENT;
759*5d5fbe79SDavid van Moolenbroek }
760*5d5fbe79SDavid van Moolenbroek }
761*5d5fbe79SDavid van Moolenbroek if (precalcChksum) {
762*5d5fbe79SDavid van Moolenbroek chksum_count = write_checksums(struct_file, varname, http_hdr_len, http_hdr_chksum, file_data, file_size);
763*5d5fbe79SDavid van Moolenbroek }
764*5d5fbe79SDavid van Moolenbroek
765*5d5fbe79SDavid van Moolenbroek /* build declaration of struct fsdata_file in temp file */
766*5d5fbe79SDavid van Moolenbroek fprintf(struct_file, "const struct fsdata_file file_%s[] = { {" NEWLINE, varname);
767*5d5fbe79SDavid van Moolenbroek fprintf(struct_file, "file_%s," NEWLINE, lastFileVar);
768*5d5fbe79SDavid van Moolenbroek fprintf(struct_file, "data_%s," NEWLINE, varname);
769*5d5fbe79SDavid van Moolenbroek fprintf(struct_file, "data_%s + %d," NEWLINE, varname, i);
770*5d5fbe79SDavid van Moolenbroek fprintf(struct_file, "sizeof(data_%s) - %d," NEWLINE, varname, i);
771*5d5fbe79SDavid van Moolenbroek switch(flags)
772*5d5fbe79SDavid van Moolenbroek {
773*5d5fbe79SDavid van Moolenbroek case(FS_FILE_FLAGS_HEADER_INCLUDED):
774*5d5fbe79SDavid van Moolenbroek flags_str = "FS_FILE_FLAGS_HEADER_INCLUDED";
775*5d5fbe79SDavid van Moolenbroek break;
776*5d5fbe79SDavid van Moolenbroek case(FS_FILE_FLAGS_HEADER_PERSISTENT):
777*5d5fbe79SDavid van Moolenbroek flags_str = "FS_FILE_FLAGS_HEADER_PERSISTENT";
778*5d5fbe79SDavid van Moolenbroek break;
779*5d5fbe79SDavid van Moolenbroek case(FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT):
780*5d5fbe79SDavid van Moolenbroek flags_str = "FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT";
781*5d5fbe79SDavid van Moolenbroek break;
782*5d5fbe79SDavid van Moolenbroek default:
783*5d5fbe79SDavid van Moolenbroek flags_str = "0";
784*5d5fbe79SDavid van Moolenbroek break;
785*5d5fbe79SDavid van Moolenbroek }
786*5d5fbe79SDavid van Moolenbroek fprintf(struct_file, "%s," NEWLINE, flags_str);
787*5d5fbe79SDavid van Moolenbroek if (precalcChksum) {
788*5d5fbe79SDavid van Moolenbroek fprintf(struct_file, "#if HTTPD_PRECALCULATED_CHECKSUM" NEWLINE);
789*5d5fbe79SDavid van Moolenbroek fprintf(struct_file, "%d, chksums_%s," NEWLINE, chksum_count, varname);
790*5d5fbe79SDavid van Moolenbroek fprintf(struct_file, "#endif /* HTTPD_PRECALCULATED_CHECKSUM */" NEWLINE);
791*5d5fbe79SDavid van Moolenbroek }
792*5d5fbe79SDavid van Moolenbroek fprintf(struct_file, "}};" NEWLINE NEWLINE);
793*5d5fbe79SDavid van Moolenbroek strcpy(lastFileVar, varname);
794*5d5fbe79SDavid van Moolenbroek
795*5d5fbe79SDavid van Moolenbroek /* write actual file contents */
796*5d5fbe79SDavid van Moolenbroek i = 0;
797*5d5fbe79SDavid van Moolenbroek fprintf(data_file, NEWLINE "/* raw file data (%d bytes) */" NEWLINE, file_size);
798*5d5fbe79SDavid van Moolenbroek process_file_data(data_file, file_data, file_size);
799*5d5fbe79SDavid van Moolenbroek fprintf(data_file, "};" NEWLINE NEWLINE);
800*5d5fbe79SDavid van Moolenbroek free(file_data);
801*5d5fbe79SDavid van Moolenbroek return 0;
802*5d5fbe79SDavid van Moolenbroek }
803*5d5fbe79SDavid van Moolenbroek
file_write_http_header(FILE * data_file,const char * filename,int file_size,u16_t * http_hdr_len,u16_t * http_hdr_chksum,u8_t provide_content_len,int is_compressed)804*5d5fbe79SDavid van Moolenbroek int file_write_http_header(FILE *data_file, const char *filename, int file_size, u16_t *http_hdr_len,
805*5d5fbe79SDavid van Moolenbroek u16_t *http_hdr_chksum, u8_t provide_content_len, int is_compressed)
806*5d5fbe79SDavid van Moolenbroek {
807*5d5fbe79SDavid van Moolenbroek int i = 0;
808*5d5fbe79SDavid van Moolenbroek int response_type = HTTP_HDR_OK;
809*5d5fbe79SDavid van Moolenbroek const char* file_type;
810*5d5fbe79SDavid van Moolenbroek const char *cur_string;
811*5d5fbe79SDavid van Moolenbroek size_t cur_len;
812*5d5fbe79SDavid van Moolenbroek int written = 0;
813*5d5fbe79SDavid van Moolenbroek size_t hdr_len = 0;
814*5d5fbe79SDavid van Moolenbroek u16_t acc;
815*5d5fbe79SDavid van Moolenbroek const char *file_ext;
816*5d5fbe79SDavid van Moolenbroek int j;
817*5d5fbe79SDavid van Moolenbroek u8_t provide_last_modified = includeLastModified;
818*5d5fbe79SDavid van Moolenbroek
819*5d5fbe79SDavid van Moolenbroek memset(hdr_buf, 0, sizeof(hdr_buf));
820*5d5fbe79SDavid van Moolenbroek
821*5d5fbe79SDavid van Moolenbroek if (useHttp11) {
822*5d5fbe79SDavid van Moolenbroek response_type = HTTP_HDR_OK_11;
823*5d5fbe79SDavid van Moolenbroek }
824*5d5fbe79SDavid van Moolenbroek
825*5d5fbe79SDavid van Moolenbroek fprintf(data_file, NEWLINE "/* HTTP header */");
826*5d5fbe79SDavid van Moolenbroek if (strstr(filename, "404") == filename) {
827*5d5fbe79SDavid van Moolenbroek response_type = HTTP_HDR_NOT_FOUND;
828*5d5fbe79SDavid van Moolenbroek if (useHttp11) {
829*5d5fbe79SDavid van Moolenbroek response_type = HTTP_HDR_NOT_FOUND_11;
830*5d5fbe79SDavid van Moolenbroek }
831*5d5fbe79SDavid van Moolenbroek } else if (strstr(filename, "400") == filename) {
832*5d5fbe79SDavid van Moolenbroek response_type = HTTP_HDR_BAD_REQUEST;
833*5d5fbe79SDavid van Moolenbroek if (useHttp11) {
834*5d5fbe79SDavid van Moolenbroek response_type = HTTP_HDR_BAD_REQUEST_11;
835*5d5fbe79SDavid van Moolenbroek }
836*5d5fbe79SDavid van Moolenbroek } else if (strstr(filename, "501") == filename) {
837*5d5fbe79SDavid van Moolenbroek response_type = HTTP_HDR_NOT_IMPL;
838*5d5fbe79SDavid van Moolenbroek if (useHttp11) {
839*5d5fbe79SDavid van Moolenbroek response_type = HTTP_HDR_NOT_IMPL_11;
840*5d5fbe79SDavid van Moolenbroek }
841*5d5fbe79SDavid van Moolenbroek }
842*5d5fbe79SDavid van Moolenbroek cur_string = g_psHTTPHeaderStrings[response_type];
843*5d5fbe79SDavid van Moolenbroek cur_len = strlen(cur_string);
844*5d5fbe79SDavid van Moolenbroek fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len);
845*5d5fbe79SDavid van Moolenbroek written += file_put_ascii(data_file, cur_string, cur_len, &i);
846*5d5fbe79SDavid van Moolenbroek i = 0;
847*5d5fbe79SDavid van Moolenbroek if (precalcChksum) {
848*5d5fbe79SDavid van Moolenbroek memcpy(&hdr_buf[hdr_len], cur_string, cur_len);
849*5d5fbe79SDavid van Moolenbroek hdr_len += cur_len;
850*5d5fbe79SDavid van Moolenbroek }
851*5d5fbe79SDavid van Moolenbroek
852*5d5fbe79SDavid van Moolenbroek cur_string = serverID;
853*5d5fbe79SDavid van Moolenbroek cur_len = strlen(cur_string);
854*5d5fbe79SDavid van Moolenbroek fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len);
855*5d5fbe79SDavid van Moolenbroek written += file_put_ascii(data_file, cur_string, cur_len, &i);
856*5d5fbe79SDavid van Moolenbroek i = 0;
857*5d5fbe79SDavid van Moolenbroek if (precalcChksum) {
858*5d5fbe79SDavid van Moolenbroek memcpy(&hdr_buf[hdr_len], cur_string, cur_len);
859*5d5fbe79SDavid van Moolenbroek hdr_len += cur_len;
860*5d5fbe79SDavid van Moolenbroek }
861*5d5fbe79SDavid van Moolenbroek
862*5d5fbe79SDavid van Moolenbroek file_ext = filename;
863*5d5fbe79SDavid van Moolenbroek if (file_ext != NULL) {
864*5d5fbe79SDavid van Moolenbroek while(strstr(file_ext, ".") != NULL) {
865*5d5fbe79SDavid van Moolenbroek file_ext = strstr(file_ext, ".");
866*5d5fbe79SDavid van Moolenbroek file_ext++;
867*5d5fbe79SDavid van Moolenbroek }
868*5d5fbe79SDavid van Moolenbroek }
869*5d5fbe79SDavid van Moolenbroek if ((file_ext == NULL) || (*file_ext == 0)) {
870*5d5fbe79SDavid van Moolenbroek printf("failed to get extension for file \"%s\", using default.\n", filename);
871*5d5fbe79SDavid van Moolenbroek file_type = HTTP_HDR_DEFAULT_TYPE;
872*5d5fbe79SDavid van Moolenbroek } else {
873*5d5fbe79SDavid van Moolenbroek file_type = NULL;
874*5d5fbe79SDavid van Moolenbroek for (j = 0; j < NUM_HTTP_HEADERS; j++) {
875*5d5fbe79SDavid van Moolenbroek if (!strcmp(file_ext, g_psHTTPHeaders[j].extension)) {
876*5d5fbe79SDavid van Moolenbroek file_type = g_psHTTPHeaders[j].content_type;
877*5d5fbe79SDavid van Moolenbroek break;
878*5d5fbe79SDavid van Moolenbroek }
879*5d5fbe79SDavid van Moolenbroek }
880*5d5fbe79SDavid van Moolenbroek if (file_type == NULL) {
881*5d5fbe79SDavid van Moolenbroek printf("failed to get file type for extension \"%s\", using default.\n", file_ext);
882*5d5fbe79SDavid van Moolenbroek file_type = HTTP_HDR_DEFAULT_TYPE;
883*5d5fbe79SDavid van Moolenbroek }
884*5d5fbe79SDavid van Moolenbroek }
885*5d5fbe79SDavid van Moolenbroek
886*5d5fbe79SDavid van Moolenbroek /* Content-Length is used for persistent connections in HTTP/1.1 but also for
887*5d5fbe79SDavid van Moolenbroek download progress in older versions
888*5d5fbe79SDavid van Moolenbroek @todo: just use a big-enough buffer and let the HTTPD send spaces? */
889*5d5fbe79SDavid van Moolenbroek if (provide_content_len) {
890*5d5fbe79SDavid van Moolenbroek char intbuf[MAX_PATH_LEN];
891*5d5fbe79SDavid van Moolenbroek int content_len = file_size;
892*5d5fbe79SDavid van Moolenbroek memset(intbuf, 0, sizeof(intbuf));
893*5d5fbe79SDavid van Moolenbroek cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH];
894*5d5fbe79SDavid van Moolenbroek cur_len = strlen(cur_string);
895*5d5fbe79SDavid van Moolenbroek fprintf(data_file, NEWLINE "/* \"%s%d\r\n\" (%d+ bytes) */" NEWLINE, cur_string, content_len, cur_len+2);
896*5d5fbe79SDavid van Moolenbroek written += file_put_ascii(data_file, cur_string, cur_len, &i);
897*5d5fbe79SDavid van Moolenbroek if (precalcChksum) {
898*5d5fbe79SDavid van Moolenbroek memcpy(&hdr_buf[hdr_len], cur_string, cur_len);
899*5d5fbe79SDavid van Moolenbroek hdr_len += cur_len;
900*5d5fbe79SDavid van Moolenbroek }
901*5d5fbe79SDavid van Moolenbroek
902*5d5fbe79SDavid van Moolenbroek _itoa(content_len, intbuf, 10);
903*5d5fbe79SDavid van Moolenbroek strcat(intbuf, "\r\n");
904*5d5fbe79SDavid van Moolenbroek cur_len = strlen(intbuf);
905*5d5fbe79SDavid van Moolenbroek written += file_put_ascii(data_file, intbuf, cur_len, &i);
906*5d5fbe79SDavid van Moolenbroek i = 0;
907*5d5fbe79SDavid van Moolenbroek if (precalcChksum) {
908*5d5fbe79SDavid van Moolenbroek memcpy(&hdr_buf[hdr_len], intbuf, cur_len);
909*5d5fbe79SDavid van Moolenbroek hdr_len += cur_len;
910*5d5fbe79SDavid van Moolenbroek }
911*5d5fbe79SDavid van Moolenbroek }
912*5d5fbe79SDavid van Moolenbroek if (provide_last_modified) {
913*5d5fbe79SDavid van Moolenbroek char modbuf[256];
914*5d5fbe79SDavid van Moolenbroek struct stat stat_data;
915*5d5fbe79SDavid van Moolenbroek struct tm* t;
916*5d5fbe79SDavid van Moolenbroek memset(modbuf, 0, sizeof(modbuf));
917*5d5fbe79SDavid van Moolenbroek memset(&stat_data, 0, sizeof(stat_data));
918*5d5fbe79SDavid van Moolenbroek cur_string = modbuf;
919*5d5fbe79SDavid van Moolenbroek strcpy(modbuf, "Last-Modified: ");
920*5d5fbe79SDavid van Moolenbroek if (stat(filename, &stat_data) != 0) {
921*5d5fbe79SDavid van Moolenbroek printf("stat(%s) failed with error %d\n", filename, errno);
922*5d5fbe79SDavid van Moolenbroek exit(-1);
923*5d5fbe79SDavid van Moolenbroek }
924*5d5fbe79SDavid van Moolenbroek t = gmtime(&stat_data.st_mtime);
925*5d5fbe79SDavid van Moolenbroek if (t == NULL) {
926*5d5fbe79SDavid van Moolenbroek printf("gmtime() failed with error %d\n", errno);
927*5d5fbe79SDavid van Moolenbroek exit(-1);
928*5d5fbe79SDavid van Moolenbroek }
929*5d5fbe79SDavid van Moolenbroek strftime(&modbuf[15], sizeof(modbuf)-15, "%a, %d %b %Y %H:%M:%S GMT", t);
930*5d5fbe79SDavid van Moolenbroek cur_len = strlen(cur_string);
931*5d5fbe79SDavid van Moolenbroek fprintf(data_file, NEWLINE "/* \"%s\"\r\n\" (%d+ bytes) */" NEWLINE, cur_string, cur_len+2);
932*5d5fbe79SDavid van Moolenbroek written += file_put_ascii(data_file, cur_string, cur_len, &i);
933*5d5fbe79SDavid van Moolenbroek if (precalcChksum) {
934*5d5fbe79SDavid van Moolenbroek memcpy(&hdr_buf[hdr_len], cur_string, cur_len);
935*5d5fbe79SDavid van Moolenbroek hdr_len += cur_len;
936*5d5fbe79SDavid van Moolenbroek }
937*5d5fbe79SDavid van Moolenbroek
938*5d5fbe79SDavid van Moolenbroek modbuf[0] = 0;
939*5d5fbe79SDavid van Moolenbroek strcat(modbuf, "\r\n");
940*5d5fbe79SDavid van Moolenbroek cur_len = strlen(modbuf);
941*5d5fbe79SDavid van Moolenbroek written += file_put_ascii(data_file, modbuf, cur_len, &i);
942*5d5fbe79SDavid van Moolenbroek i = 0;
943*5d5fbe79SDavid van Moolenbroek if (precalcChksum) {
944*5d5fbe79SDavid van Moolenbroek memcpy(&hdr_buf[hdr_len], modbuf, cur_len);
945*5d5fbe79SDavid van Moolenbroek hdr_len += cur_len;
946*5d5fbe79SDavid van Moolenbroek }
947*5d5fbe79SDavid van Moolenbroek }
948*5d5fbe79SDavid van Moolenbroek
949*5d5fbe79SDavid van Moolenbroek /* HTTP/1.1 implements persistent connections */
950*5d5fbe79SDavid van Moolenbroek if (useHttp11) {
951*5d5fbe79SDavid van Moolenbroek if (provide_content_len) {
952*5d5fbe79SDavid van Moolenbroek cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_KEEPALIVE];
953*5d5fbe79SDavid van Moolenbroek } else {
954*5d5fbe79SDavid van Moolenbroek /* no Content-Length available, so a persistent connection is no possible
955*5d5fbe79SDavid van Moolenbroek because the client does not know the data length */
956*5d5fbe79SDavid van Moolenbroek cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE];
957*5d5fbe79SDavid van Moolenbroek }
958*5d5fbe79SDavid van Moolenbroek cur_len = strlen(cur_string);
959*5d5fbe79SDavid van Moolenbroek fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len);
960*5d5fbe79SDavid van Moolenbroek written += file_put_ascii(data_file, cur_string, cur_len, &i);
961*5d5fbe79SDavid van Moolenbroek i = 0;
962*5d5fbe79SDavid van Moolenbroek if (precalcChksum) {
963*5d5fbe79SDavid van Moolenbroek memcpy(&hdr_buf[hdr_len], cur_string, cur_len);
964*5d5fbe79SDavid van Moolenbroek hdr_len += cur_len;
965*5d5fbe79SDavid van Moolenbroek }
966*5d5fbe79SDavid van Moolenbroek }
967*5d5fbe79SDavid van Moolenbroek
968*5d5fbe79SDavid van Moolenbroek #if MAKEFS_SUPPORT_DEFLATE
969*5d5fbe79SDavid van Moolenbroek if (is_compressed) {
970*5d5fbe79SDavid van Moolenbroek /* tell the client about the deflate encoding */
971*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("error", deflateNonSsiFiles);
972*5d5fbe79SDavid van Moolenbroek cur_string = "Content-Encoding: deflate\r\n";
973*5d5fbe79SDavid van Moolenbroek cur_len = strlen(cur_string);
974*5d5fbe79SDavid van Moolenbroek fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len);
975*5d5fbe79SDavid van Moolenbroek written += file_put_ascii(data_file, cur_string, cur_len, &i);
976*5d5fbe79SDavid van Moolenbroek i = 0;
977*5d5fbe79SDavid van Moolenbroek }
978*5d5fbe79SDavid van Moolenbroek #else
979*5d5fbe79SDavid van Moolenbroek LWIP_UNUSED_ARG(is_compressed);
980*5d5fbe79SDavid van Moolenbroek #endif
981*5d5fbe79SDavid van Moolenbroek
982*5d5fbe79SDavid van Moolenbroek /* write content-type, ATTENTION: this includes the double-CRLF! */
983*5d5fbe79SDavid van Moolenbroek cur_string = file_type;
984*5d5fbe79SDavid van Moolenbroek cur_len = strlen(cur_string);
985*5d5fbe79SDavid van Moolenbroek fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len);
986*5d5fbe79SDavid van Moolenbroek written += file_put_ascii(data_file, cur_string, cur_len, &i);
987*5d5fbe79SDavid van Moolenbroek i = 0;
988*5d5fbe79SDavid van Moolenbroek
989*5d5fbe79SDavid van Moolenbroek /* ATTENTION: headers are done now (double-CRLF has been written!) */
990*5d5fbe79SDavid van Moolenbroek
991*5d5fbe79SDavid van Moolenbroek if (precalcChksum) {
992*5d5fbe79SDavid van Moolenbroek memcpy(&hdr_buf[hdr_len], cur_string, cur_len);
993*5d5fbe79SDavid van Moolenbroek hdr_len += cur_len;
994*5d5fbe79SDavid van Moolenbroek
995*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("hdr_len <= 0xffff", hdr_len <= 0xffff);
996*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("strlen(hdr_buf) == hdr_len", strlen(hdr_buf) == hdr_len);
997*5d5fbe79SDavid van Moolenbroek acc = ~inet_chksum(hdr_buf, (u16_t)hdr_len);
998*5d5fbe79SDavid van Moolenbroek *http_hdr_len = (u16_t)hdr_len;
999*5d5fbe79SDavid van Moolenbroek *http_hdr_chksum = acc;
1000*5d5fbe79SDavid van Moolenbroek }
1001*5d5fbe79SDavid van Moolenbroek
1002*5d5fbe79SDavid van Moolenbroek return written;
1003*5d5fbe79SDavid van Moolenbroek }
1004*5d5fbe79SDavid van Moolenbroek
file_put_ascii(FILE * file,const char * ascii_string,int len,int * i)1005*5d5fbe79SDavid van Moolenbroek int file_put_ascii(FILE *file, const char* ascii_string, int len, int *i)
1006*5d5fbe79SDavid van Moolenbroek {
1007*5d5fbe79SDavid van Moolenbroek int x;
1008*5d5fbe79SDavid van Moolenbroek for (x = 0; x < len; x++) {
1009*5d5fbe79SDavid van Moolenbroek unsigned char cur = ascii_string[x];
1010*5d5fbe79SDavid van Moolenbroek fprintf(file, "0x%02.2x,", cur);
1011*5d5fbe79SDavid van Moolenbroek if ((++(*i) % HEX_BYTES_PER_LINE) == 0) {
1012*5d5fbe79SDavid van Moolenbroek fprintf(file, NEWLINE);
1013*5d5fbe79SDavid van Moolenbroek }
1014*5d5fbe79SDavid van Moolenbroek }
1015*5d5fbe79SDavid van Moolenbroek return len;
1016*5d5fbe79SDavid van Moolenbroek }
1017*5d5fbe79SDavid van Moolenbroek
s_put_ascii(char * buf,const char * ascii_string,int len,int * i)1018*5d5fbe79SDavid van Moolenbroek int s_put_ascii(char *buf, const char *ascii_string, int len, int *i)
1019*5d5fbe79SDavid van Moolenbroek {
1020*5d5fbe79SDavid van Moolenbroek int x;
1021*5d5fbe79SDavid van Moolenbroek int idx = 0;
1022*5d5fbe79SDavid van Moolenbroek for (x = 0; x < len; x++) {
1023*5d5fbe79SDavid van Moolenbroek unsigned char cur = ascii_string[x];
1024*5d5fbe79SDavid van Moolenbroek sprintf(&buf[idx], "0x%02.2x,", cur);
1025*5d5fbe79SDavid van Moolenbroek idx += 5;
1026*5d5fbe79SDavid van Moolenbroek if ((++(*i) % HEX_BYTES_PER_LINE) == 0) {
1027*5d5fbe79SDavid van Moolenbroek sprintf(&buf[idx], NEWLINE);
1028*5d5fbe79SDavid van Moolenbroek idx += NEWLINE_LEN;
1029*5d5fbe79SDavid van Moolenbroek }
1030*5d5fbe79SDavid van Moolenbroek }
1031*5d5fbe79SDavid van Moolenbroek return len;
1032*5d5fbe79SDavid van Moolenbroek }
1033