source: azure_iot_hub_f767zi/trunk/asp_baseplatform/lwip/lwip-2.1.2/src/apps/http/makefsdata/makefsdata.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

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