int 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) { int i = 0; int response_type = HTTP_HDR_OK; const char* file_type; const char *cur_string; size_t cur_len; int written = 0; size_t hdr_len = 0; u16_t acc; const char *file_ext; int j; u8_t provide_last_modified = includeLastModified; memset(hdr_buf, 0, sizeof(hdr_buf)); if (useHttp11) { response_type = HTTP_HDR_OK_11; } fprintf(data_file, NEWLINE "/* HTTP header */"); if (strstr(filename, "404") == filename) { response_type = HTTP_HDR_NOT_FOUND; if (useHttp11) { response_type = HTTP_HDR_NOT_FOUND_11; } } else if (strstr(filename, "400") == filename) { response_type = HTTP_HDR_BAD_REQUEST; if (useHttp11) { response_type = HTTP_HDR_BAD_REQUEST_11; } } else if (strstr(filename, "501") == filename) { response_type = HTTP_HDR_NOT_IMPL; if (useHttp11) { response_type = HTTP_HDR_NOT_IMPL_11; } } cur_string = g_psHTTPHeaderStrings[response_type]; cur_len = strlen(cur_string); fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); written += file_put_ascii(data_file, cur_string, cur_len, &i); i = 0; if (precalcChksum) { memcpy(&hdr_buf[hdr_len], cur_string, cur_len); hdr_len += cur_len; } cur_string = serverID; cur_len = strlen(cur_string); fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); written += file_put_ascii(data_file, cur_string, cur_len, &i); i = 0; if (precalcChksum) { memcpy(&hdr_buf[hdr_len], cur_string, cur_len); hdr_len += cur_len; } file_ext = filename; if (file_ext != NULL) { while(strstr(file_ext, ".") != NULL) { file_ext = strstr(file_ext, "."); file_ext++; } } if ((file_ext == NULL) || (*file_ext == 0)) { printf("failed to get extension for file \"%s\", using default.\n", filename); file_type = HTTP_HDR_DEFAULT_TYPE; } else { file_type = NULL; for (j = 0; j < NUM_HTTP_HEADERS; j++) { if (!strcmp(file_ext, g_psHTTPHeaders[j].extension)) { file_type = g_psHTTPHeaders[j].content_type; break; } } if (file_type == NULL) { printf("failed to get file type for extension \"%s\", using default.\n", file_ext); file_type = HTTP_HDR_DEFAULT_TYPE; } } /* Content-Length is used for persistent connections in HTTP/1.1 but also for download progress in older versions @todo: just use a big-enough buffer and let the HTTPD send spaces? */ if (provide_content_len) { char intbuf[MAX_PATH_LEN]; int content_len = file_size; memset(intbuf, 0, sizeof(intbuf)); cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH]; cur_len = strlen(cur_string); fprintf(data_file, NEWLINE "/* \"%s%d\r\n\" (%d+ bytes) */" NEWLINE, cur_string, content_len, cur_len+2); written += file_put_ascii(data_file, cur_string, cur_len, &i); if (precalcChksum) { memcpy(&hdr_buf[hdr_len], cur_string, cur_len); hdr_len += cur_len; } _itoa(content_len, intbuf, 10); strcat(intbuf, "\r\n"); cur_len = strlen(intbuf); written += file_put_ascii(data_file, intbuf, cur_len, &i); i = 0; if (precalcChksum) { memcpy(&hdr_buf[hdr_len], intbuf, cur_len); hdr_len += cur_len; } } if (provide_last_modified) { char modbuf[256]; struct stat stat_data; struct tm* t; memset(modbuf, 0, sizeof(modbuf)); memset(&stat_data, 0, sizeof(stat_data)); cur_string = modbuf; strcpy(modbuf, "Last-Modified: "); if (stat(filename, &stat_data) != 0) { printf("stat(%s) failed with error %d\n", filename, errno); exit(-1); } t = gmtime(&stat_data.st_mtime); if (t == NULL) { printf("gmtime() failed with error %d\n", errno); exit(-1); } strftime(&modbuf[15], sizeof(modbuf)-15, "%a, %d %b %Y %H:%M:%S GMT", t); cur_len = strlen(cur_string); fprintf(data_file, NEWLINE "/* \"%s\"\r\n\" (%d+ bytes) */" NEWLINE, cur_string, cur_len+2); written += file_put_ascii(data_file, cur_string, cur_len, &i); if (precalcChksum) { memcpy(&hdr_buf[hdr_len], cur_string, cur_len); hdr_len += cur_len; } modbuf[0] = 0; strcat(modbuf, "\r\n"); cur_len = strlen(modbuf); written += file_put_ascii(data_file, modbuf, cur_len, &i); i = 0; if (precalcChksum) { memcpy(&hdr_buf[hdr_len], modbuf, cur_len); hdr_len += cur_len; } } /* HTTP/1.1 implements persistent connections */ if (useHttp11) { if (provide_content_len) { cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_KEEPALIVE]; } else { /* no Content-Length available, so a persistent connection is no possible because the client does not know the data length */ cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE]; } cur_len = strlen(cur_string); fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); written += file_put_ascii(data_file, cur_string, cur_len, &i); i = 0; if (precalcChksum) { memcpy(&hdr_buf[hdr_len], cur_string, cur_len); hdr_len += cur_len; } } #if MAKEFS_SUPPORT_DEFLATE if (is_compressed) { /* tell the client about the deflate encoding */ LWIP_ASSERT("error", deflateNonSsiFiles); cur_string = "Content-Encoding: deflate\r\n"; cur_len = strlen(cur_string); fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); written += file_put_ascii(data_file, cur_string, cur_len, &i); i = 0; } #else LWIP_UNUSED_ARG(is_compressed); #endif /* write content-type, ATTENTION: this includes the double-CRLF! */ cur_string = file_type; cur_len = strlen(cur_string); fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); written += file_put_ascii(data_file, cur_string, cur_len, &i); i = 0; /* ATTENTION: headers are done now (double-CRLF has been written!) */ if (precalcChksum) { memcpy(&hdr_buf[hdr_len], cur_string, cur_len); hdr_len += cur_len; LWIP_ASSERT("hdr_len <= 0xffff", hdr_len <= 0xffff); LWIP_ASSERT("strlen(hdr_buf) == hdr_len", strlen(hdr_buf) == hdr_len); acc = ~inet_chksum(hdr_buf, (u16_t)hdr_len); *http_hdr_len = (u16_t)hdr_len; *http_hdr_chksum = acc; } return written; }
int file_write_http_header(FILE *data_file, const char *filename, int file_size, u16_t *http_hdr_len, u16_t *http_hdr_chksum) { int i = 0; int response_type = HTTP_HDR_OK; int file_type = HTTP_HDR_DEFAULT_TYPE; const char *cur_string; size_t cur_len; int written = 0; size_t hdr_len = 0; u16_t acc; const char *file_ext; int j; memset(hdr_buf, 0, sizeof(hdr_buf)); if (useHttp11) { response_type = HTTP_HDR_OK_11; } fprintf(data_file, NEWLINE "/* HTTP header */"); if (strstr(filename, "404") == filename) { response_type = HTTP_HDR_NOT_FOUND; if (useHttp11) { response_type = HTTP_HDR_NOT_FOUND_11; } } else if (strstr(filename, "400") == filename) { response_type = HTTP_HDR_BAD_REQUEST; if (useHttp11) { response_type = HTTP_HDR_BAD_REQUEST_11; } } else if (strstr(filename, "501") == filename) { response_type = HTTP_HDR_NOT_IMPL; if (useHttp11) { response_type = HTTP_HDR_NOT_IMPL_11; } } cur_string = g_psHTTPHeaderStrings[response_type]; cur_len = strlen(cur_string); fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); written += file_put_ascii(data_file, cur_string, cur_len, &i); i = 0; if (precalcChksum) { memcpy(&hdr_buf[hdr_len], cur_string, cur_len); hdr_len += cur_len; } cur_string = serverID; cur_len = strlen(cur_string); fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); written += file_put_ascii(data_file, cur_string, cur_len, &i); i = 0; if (precalcChksum) { memcpy(&hdr_buf[hdr_len], cur_string, cur_len); hdr_len += cur_len; } file_ext = filename; while(strstr(file_ext, ".") != NULL) { file_ext = strstr(file_ext, "."); file_ext++; } if((file_ext == NULL) || (*file_ext == 0)) { printf("failed to get extension for file \"%s\", using default.\n", filename); } else { for(j = 0; j < NUM_HTTP_HEADERS; j++) { if(!strcmp(file_ext, g_psHTTPHeaders[j].extension)) { file_type = g_psHTTPHeaders[j].headerIndex; break; } } if (j >= NUM_HTTP_HEADERS) { printf("failed to get file type for extension \"%s\", using default.\n", file_ext); file_type = HTTP_HDR_DEFAULT_TYPE; } } if (useHttp11) { char intbuf[MAX_PATH_LEN]; memset(intbuf, 0, sizeof(intbuf)); cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH]; cur_len = strlen(cur_string); fprintf(data_file, NEWLINE "/* \"%s%d\r\n\" (%d+ bytes) */" NEWLINE, cur_string, file_size, cur_len+2); written += file_put_ascii(data_file, cur_string, cur_len, &i); if (precalcChksum) { memcpy(&hdr_buf[hdr_len], cur_string, cur_len); hdr_len += cur_len; } _itoa(file_size, intbuf, 10); strcat(intbuf, "\r\n"); cur_len = strlen(intbuf); written += file_put_ascii(data_file, intbuf, cur_len, &i); i = 0; if (precalcChksum) { memcpy(&hdr_buf[hdr_len], intbuf, cur_len); hdr_len += cur_len; } cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE]; cur_len = strlen(cur_string); fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); written += file_put_ascii(data_file, cur_string, cur_len, &i); i = 0; if (precalcChksum) { memcpy(&hdr_buf[hdr_len], cur_string, cur_len); hdr_len += cur_len; } } cur_string = g_psHTTPHeaderStrings[file_type]; cur_len = strlen(cur_string); fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); written += file_put_ascii(data_file, cur_string, cur_len, &i); i = 0; if (precalcChksum) { memcpy(&hdr_buf[hdr_len], cur_string, cur_len); hdr_len += cur_len; LWIP_ASSERT("hdr_len <= 0xffff", hdr_len <= 0xffff); LWIP_ASSERT("strlen(hdr_buf) == hdr_len", strlen(hdr_buf) == hdr_len); acc = ~inet_chksum(hdr_buf, (u16_t)hdr_len); *http_hdr_len = (u16_t)hdr_len; *http_hdr_chksum = acc; } return written; }
int process_file(FILE *data_file, FILE *struct_file, const char *filename) { char varname[MAX_PATH_LEN]; int i = 0; char qualifiedName[MAX_PATH_LEN]; int file_size; u16_t http_hdr_chksum = 0; u16_t http_hdr_len = 0; int chksum_count = 0; u8_t flags = 0; const char* flags_str; u8_t has_content_len; u8_t* file_data; int is_compressed = 0; /* create qualified name (@todo: prepend slash or not?) */ sprintf(qualifiedName,"%s/%s", curSubdir, filename); /* create C variable name */ strcpy(varname, qualifiedName); /* convert slashes & dots to underscores */ fix_filename_for_c(varname, MAX_PATH_LEN); register_filename(varname); #if ALIGN_PAYLOAD /* to force even alignment of array, type 1 */ fprintf(data_file, "#if FSDATA_FILE_ALIGNMENT==1" NEWLINE); fprintf(data_file, "static const " PAYLOAD_ALIGN_TYPE " dummy_align_%s = %d;" NEWLINE, varname, payload_alingment_dummy_counter++); fprintf(data_file, "#endif" NEWLINE); #endif /* ALIGN_PAYLOAD */ fprintf(data_file, "static const unsigned char FSDATA_ALIGN_PRE data_%s[] FSDATA_ALIGN_POST = {" NEWLINE, varname); /* encode source file name (used by file system, not returned to browser) */ fprintf(data_file, "/* %s (%d chars) */" NEWLINE, qualifiedName, strlen(qualifiedName)+1); file_put_ascii(data_file, qualifiedName, strlen(qualifiedName)+1, &i); #if ALIGN_PAYLOAD /* pad to even number of bytes to assure payload is on aligned boundary */ while(i % PAYLOAD_ALIGNMENT != 0) { fprintf(data_file, "0x%02.2x,", 0); i++; } #endif /* ALIGN_PAYLOAD */ fprintf(data_file, NEWLINE); has_content_len = !is_ssi_file(filename); file_data = get_file_data(filename, &file_size, includeHttpHeader && has_content_len, &is_compressed); if (includeHttpHeader) { file_write_http_header(data_file, filename, file_size, &http_hdr_len, &http_hdr_chksum, has_content_len, is_compressed); flags = FS_FILE_FLAGS_HEADER_INCLUDED; if (has_content_len) { flags |= FS_FILE_FLAGS_HEADER_PERSISTENT; } } if (precalcChksum) { chksum_count = write_checksums(struct_file, varname, http_hdr_len, http_hdr_chksum, file_data, file_size); } /* build declaration of struct fsdata_file in temp file */ fprintf(struct_file, "const struct fsdata_file file_%s[] = { {" NEWLINE, varname); fprintf(struct_file, "file_%s," NEWLINE, lastFileVar); fprintf(struct_file, "data_%s," NEWLINE, varname); fprintf(struct_file, "data_%s + %d," NEWLINE, varname, i); fprintf(struct_file, "sizeof(data_%s) - %d," NEWLINE, varname, i); switch(flags) { case(FS_FILE_FLAGS_HEADER_INCLUDED): flags_str = "FS_FILE_FLAGS_HEADER_INCLUDED"; break; case(FS_FILE_FLAGS_HEADER_PERSISTENT): flags_str = "FS_FILE_FLAGS_HEADER_PERSISTENT"; break; case(FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT): flags_str = "FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT"; break; default: flags_str = "0"; break; } fprintf(struct_file, "%s," NEWLINE, flags_str); if (precalcChksum) { fprintf(struct_file, "#if HTTPD_PRECALCULATED_CHECKSUM" NEWLINE); fprintf(struct_file, "%d, chksums_%s," NEWLINE, chksum_count, varname); fprintf(struct_file, "#endif /* HTTPD_PRECALCULATED_CHECKSUM */" NEWLINE); } fprintf(struct_file, "}};" NEWLINE NEWLINE); strcpy(lastFileVar, varname); /* write actual file contents */ i = 0; fprintf(data_file, NEWLINE "/* raw file data (%d bytes) */" NEWLINE, file_size); process_file_data(data_file, file_data, file_size); fprintf(data_file, "};" NEWLINE NEWLINE); free(file_data); return 0; }
int process_file(FILE *data_file, FILE *struct_file, const char *filename) { char *pch; char varname[MAX_PATH_LEN]; int i = 0; char qualifiedName[MAX_PATH_LEN]; int file_size; u16_t http_hdr_chksum = 0; u16_t http_hdr_len = 0; int chksum_count = 0; /* create qualified name (TODO: prepend slash or not?) */ sprintf(qualifiedName,"%s/%s", curSubdir, filename); /* create C variable name */ strcpy(varname, qualifiedName); /* convert slashes & dots to underscores */ while ((pch = strpbrk(varname, "./\\")) != NULL) { *pch = '_'; } #if ALIGN_PAYLOAD /* to force even alignment of array */ fprintf(data_file, "static const " PAYLOAD_ALIGN_TYPE " dummy_align_%s = %d;" NEWLINE, varname, payload_alingment_dummy_counter++); #endif /* ALIGN_PAYLOAD */ fprintf(data_file, "static const unsigned char data_%s[] = {" NEWLINE, varname); /* encode source file name (used by file system, not returned to browser) */ fprintf(data_file, "/* %s (%d chars) */" NEWLINE, qualifiedName, strlen(qualifiedName)+1); file_put_ascii(data_file, qualifiedName, strlen(qualifiedName)+1, &i); #if ALIGN_PAYLOAD /* pad to even number of bytes to assure payload is on aligned boundary */ while(i % PAYLOAD_ALIGNMENT != 0) { fprintf(data_file, "0x%02.2x,", 0); i++; } #endif /* ALIGN_PAYLOAD */ fprintf(data_file, NEWLINE); file_size = get_file_size(filename); if (includeHttpHeader) { file_write_http_header(data_file, filename, file_size, &http_hdr_len, &http_hdr_chksum); } if (precalcChksum) { chksum_count = write_checksums(struct_file, filename, varname, http_hdr_len, http_hdr_chksum); } /* build declaration of struct fsdata_file in temp file */ fprintf(struct_file, "const struct fsdata_file file_%s[] = { {" NEWLINE, varname); fprintf(struct_file, "file_%s," NEWLINE, lastFileVar); fprintf(struct_file, "data_%s," NEWLINE, varname); fprintf(struct_file, "data_%s + %d," NEWLINE, varname, i); fprintf(struct_file, "sizeof(data_%s) - %d," NEWLINE, varname, i); fprintf(struct_file, "%d," NEWLINE, includeHttpHeader); if (precalcChksum) { fprintf(struct_file, "#if HTTPD_PRECALCULATED_CHECKSUM" NEWLINE); fprintf(struct_file, "%d, chksums_%s," NEWLINE, chksum_count, varname); fprintf(struct_file, "#endif /* HTTPD_PRECALCULATED_CHECKSUM */" NEWLINE); } fprintf(struct_file, "}};" NEWLINE NEWLINE); strcpy(lastFileVar, varname); /* write actual file contents */ i = 0; fprintf(data_file, NEWLINE "/* raw file data (%d bytes) */" NEWLINE, file_size); process_file_data(filename, data_file); fprintf(data_file, "};" NEWLINE NEWLINE); return 0; }