Compare commits
No commits in common. "main" and "1.1" have entirely different histories.
25 changed files with 231 additions and 2146 deletions
|
@ -172,8 +172,6 @@ jobs:
|
||||||
cmake -S . -B buildRelease -DCMAKE_BUILD_TYPE=Release
|
cmake -S . -B buildRelease -DCMAKE_BUILD_TYPE=Release
|
||||||
make -C buildRelease c_simple_http
|
make -C buildRelease c_simple_http
|
||||||
|
|
||||||
strip --strip-unneeded buildRelease/c_simple_http
|
|
||||||
|
|
||||||
popd >&/dev/null
|
popd >&/dev/null
|
||||||
zstd --ultra -20 c_simple_http_clone/buildRelease/c_simple_http -o "${BUILD_ASSET_NAME}"
|
zstd --ultra -20 c_simple_http_clone/buildRelease/c_simple_http -o "${BUILD_ASSET_NAME}"
|
||||||
|
|
||||||
|
@ -235,8 +233,6 @@ jobs:
|
||||||
cmake -S . -B buildRelease -DCMAKE_BUILD_TYPE=Release
|
cmake -S . -B buildRelease -DCMAKE_BUILD_TYPE=Release
|
||||||
make -C buildRelease c_simple_http
|
make -C buildRelease c_simple_http
|
||||||
|
|
||||||
strip --strip-unneeded buildRelease/c_simple_http
|
|
||||||
|
|
||||||
popd >&/dev/null
|
popd >&/dev/null
|
||||||
zstd --ultra -20 c_simple_http_clone/buildRelease/c_simple_http -o "${BUILD_ASSET_NAME}"
|
zstd --ultra -20 c_simple_http_clone/buildRelease/c_simple_http -o "${BUILD_ASSET_NAME}"
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@ set(c_simple_http_SOURCES
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/helpers.c"
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/helpers.c"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/html_cache.c"
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/html_cache.c"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/static.c"
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/static.c"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/generate.c"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/third_party/SimpleArchiver/src/helpers.c"
|
"${CMAKE_CURRENT_SOURCE_DIR}/third_party/SimpleArchiver/src/helpers.c"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/third_party/SimpleArchiver/src/data_structures/linked_list.c"
|
"${CMAKE_CURRENT_SOURCE_DIR}/third_party/SimpleArchiver/src/data_structures/linked_list.c"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/third_party/SimpleArchiver/src/data_structures/hash_map.c"
|
"${CMAKE_CURRENT_SOURCE_DIR}/third_party/SimpleArchiver/src/data_structures/hash_map.c"
|
||||||
|
|
73
Changelog.md
73
Changelog.md
|
@ -2,75 +2,6 @@
|
||||||
|
|
||||||
## Upcoming Changes
|
## Upcoming Changes
|
||||||
|
|
||||||
## Version 1.5
|
|
||||||
|
|
||||||
Add flag `--generate-static-enable-overwrite`. This flag enables overwriting of
|
|
||||||
files from static-dir to generate-dir (if static-dir was specified). Previous
|
|
||||||
implementation relied on `--generate-enable-ovewrite` for this behavior.
|
|
||||||
|
|
||||||
Minor refactorings related to `printf` and `uintX_t`/`size_t` types.
|
|
||||||
|
|
||||||
## Version 1.4
|
|
||||||
|
|
||||||
Implemented "IF", "ELSEIF", "ELSE", "ENDIF", and "INDEX" for templates.
|
|
||||||
|
|
||||||
IF is used like: `{{{!IF Variable==SomeString}}}`.
|
|
||||||
Not equals can also be used: `{{{!IF Variable!=OtherString}}}`.
|
|
||||||
ELSEIF is used like: `{{{!ELSEIF Variable==AnotherString}}}`.
|
|
||||||
Not equals can also be used: `{{{!ELSEIF Variable!=AnotherOtherString}}}`.
|
|
||||||
ELSE is used like: `{{{!ELSE}}}`.
|
|
||||||
ENDIF is used like: `{{{!ENDIF}}}`.
|
|
||||||
INDEX is used like: `{{{!INDEX ArrayVar[2]}}}`.
|
|
||||||
|
|
||||||
Implemented "FOREACH" and "ENDFOREACH" for templates.
|
|
||||||
|
|
||||||
FOREACH is used like:
|
|
||||||
|
|
||||||
PATH=/
|
|
||||||
HTML='''
|
|
||||||
{{{!FOREACH ArrayVar}}}
|
|
||||||
{{{ArrayVar}}}
|
|
||||||
{{{!ENDFOREACH}}}'''
|
|
||||||
ArrayVar=FirstValue
|
|
||||||
ArrayVar=SecondValue
|
|
||||||
ArrayVar=ThirdValue
|
|
||||||
|
|
||||||
For multiple variables to expand in FOREACH:
|
|
||||||
|
|
||||||
PATH=/
|
|
||||||
HTML='''
|
|
||||||
{{{!FOREACH ArrayVar!ArrayVarSecond!ArrayVarThird}}}
|
|
||||||
{{{ArrayVar}}}
|
|
||||||
{{{ArrayVarSecond}}}
|
|
||||||
{{{ArrayVarThird}}}
|
|
||||||
{{{!ENDFOREACH}}}'''
|
|
||||||
ArrayVar=FirstVarOnce
|
|
||||||
ArrayVar=FirstVarTwice
|
|
||||||
ArrayVarSecond=SecondVarOnce
|
|
||||||
ArrayVarSecond=SecondVarTwice
|
|
||||||
ArrayVarThird=ThirdVarOnce
|
|
||||||
ArrayVarThird=ThirdVarTwice
|
|
||||||
|
|
||||||
Implemented nestable "IF" and "FOREACH" expressions in templates. In other
|
|
||||||
words, there can be `{{{!IF}}}` inside other IF/FOREACH blocks, and vice versa.
|
|
||||||
|
|
||||||
## Version 1.3
|
|
||||||
|
|
||||||
Fix internal erronous buffer declaration.
|
|
||||||
|
|
||||||
Fix internal missing NULL check.
|
|
||||||
|
|
||||||
## Version 1.2
|
|
||||||
|
|
||||||
Add the `--generate-dir=<DIR>` option, which will generate all html into the
|
|
||||||
given directory. This requires `--config=<CONFIG_FILE>`.
|
|
||||||
`--generate-enable-overwrite` is required to overwrite existing files when using
|
|
||||||
`--generate-dir=<DIR>`.
|
|
||||||
|
|
||||||
If `--enable-static-dir=<DIR>` is also specified with generate, then the files
|
|
||||||
in the given directory will be copied into the directory specified with
|
|
||||||
`--generate-dir=<DIR>`.
|
|
||||||
|
|
||||||
## Version 1.1
|
## Version 1.1
|
||||||
|
|
||||||
Some refactoring of code handling parsing the config file.
|
Some refactoring of code handling parsing the config file.
|
||||||
|
@ -87,7 +18,3 @@ Features:
|
||||||
- Reload configuration on SIGUSR1 or by listening (enabled by cmd parameter).
|
- Reload configuration on SIGUSR1 or by listening (enabled by cmd parameter).
|
||||||
- Cache served html (enabled by cmd parameter).
|
- Cache served html (enabled by cmd parameter).
|
||||||
- Serve static files from "static-dir" (enabled by cmd parameter).
|
- Serve static files from "static-dir" (enabled by cmd parameter).
|
||||||
|
|
||||||
<!--
|
|
||||||
vim: textwidth=80 et sw=2 ts=2 sts=2
|
|
||||||
-->
|
|
||||||
|
|
4
Makefile
4
Makefile
|
@ -44,8 +44,7 @@ HEADERS = \
|
||||||
src/http_template.h \
|
src/http_template.h \
|
||||||
src/helpers.h \
|
src/helpers.h \
|
||||||
src/html_cache.h \
|
src/html_cache.h \
|
||||||
src/static.h \
|
src/static.h
|
||||||
src/generate.h
|
|
||||||
|
|
||||||
SOURCES = \
|
SOURCES = \
|
||||||
src/main.c \
|
src/main.c \
|
||||||
|
@ -60,7 +59,6 @@ SOURCES = \
|
||||||
src/helpers.c \
|
src/helpers.c \
|
||||||
src/html_cache.c \
|
src/html_cache.c \
|
||||||
src/static.c \
|
src/static.c \
|
||||||
src/generate.c \
|
|
||||||
third_party/SimpleArchiver/src/helpers.c \
|
third_party/SimpleArchiver/src/helpers.c \
|
||||||
third_party/SimpleArchiver/src/data_structures/linked_list.c \
|
third_party/SimpleArchiver/src/data_structures/linked_list.c \
|
||||||
third_party/SimpleArchiver/src/data_structures/hash_map.c \
|
third_party/SimpleArchiver/src/data_structures/hash_map.c \
|
||||||
|
|
|
@ -15,9 +15,6 @@ A simple HTTP/1.1 server written in C.
|
||||||
--enable-cache-dir=<DIR>
|
--enable-cache-dir=<DIR>
|
||||||
--cache-entry-lifetime-seconds=<SECONDS>
|
--cache-entry-lifetime-seconds=<SECONDS>
|
||||||
--enable-static-dir=<DIR>
|
--enable-static-dir=<DIR>
|
||||||
--generate-dir=<DIR>
|
|
||||||
--generate-enable-overwrite
|
|
||||||
--generate-static-enable-overwrite
|
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
<b>Each File ONE</b><br>
|
|
|
@ -1 +0,0 @@
|
||||||
<b>Each File TWO</b><br>
|
|
|
@ -1 +0,0 @@
|
||||||
<b>Each File ZERO</b><br>
|
|
|
@ -1,6 +1,6 @@
|
||||||
PATH=/
|
PATH=/
|
||||||
HTML='''
|
HTML='''
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
|
@ -24,131 +24,14 @@ HTML='''
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h2>Test IF/FOREACH Expr</h2>
|
<h1>Test HTML</h1><br>
|
||||||
|
<h2>{{{Var}}}</h2>
|
||||||
Outer IF<br>
|
<h3><a href="/inner">To inner.</a></h3>
|
||||||
<pre>
|
</body>
|
||||||
{{{!IF ThisValue==true}}}
|
|
||||||
ThisValue is <b>true</b>.<br>
|
|
||||||
{{{!FOREACH ArrayValue}}}
|
|
||||||
{{{!IF ThisOtherValue==true}}}
|
|
||||||
{{{ArrayValue}}}<br>
|
|
||||||
ThisOtherValue is <b>true</b>.<br>
|
|
||||||
{{{Var}}}<br>
|
|
||||||
{{{!ELSE}}}
|
|
||||||
{{{ArrayValue}}}<br>
|
|
||||||
ThisOtherValue is <b>NOT true</b>.<br>
|
|
||||||
{{{Var}}}<br>
|
|
||||||
{{{!ENDIF}}}
|
|
||||||
{{{!ENDFOREACH}}}
|
|
||||||
{{{!ELSE}}}
|
|
||||||
ThisValue is <b>NOT true</b>.<br>
|
|
||||||
{{{!FOREACH ArrayValueSecond}}}
|
|
||||||
{{{!IF ThisOtherValue==true}}}
|
|
||||||
{{{ArrayValueSecond}}}<br>
|
|
||||||
ThisOtherValue is <b>true</b>.<br>
|
|
||||||
{{{Var}}}<br>
|
|
||||||
{{{!ELSE}}}
|
|
||||||
{{{ArrayValueSecond}}}<br>
|
|
||||||
ThisOtherValue is <b>NOT true</b>.<br>
|
|
||||||
{{{Var}}}<br>
|
|
||||||
{{{!ENDIF}}}
|
|
||||||
{{{!ENDFOREACH}}}
|
|
||||||
{{{!ENDIF}}}
|
|
||||||
</pre><br>
|
|
||||||
|
|
||||||
Outer FOREACH<br>
|
|
||||||
<pre>
|
|
||||||
{{{!FOREACH ArrayValue}}}
|
|
||||||
{{{ArrayValue}}}<br>
|
|
||||||
{{{!IF ThisValue==true}}}
|
|
||||||
ThisValue is <b>true</b>.<br>
|
|
||||||
{{{!FOREACH ArrayValueSecond}}}
|
|
||||||
{{{ArrayValueSecond}}}<br>
|
|
||||||
{{{!IF ThisOtherValue==true}}}
|
|
||||||
ThisOtherValue is <b>true</b>.<br>
|
|
||||||
{{{Var}}}<br>
|
|
||||||
{{{!ELSE}}}
|
|
||||||
ThisOtherValue is <b>NOT true</b>.<br>
|
|
||||||
{{{Var}}}<br>
|
|
||||||
{{{!ENDIF}}}
|
|
||||||
{{{!ENDFOREACH}}}
|
|
||||||
{{{!ELSE}}}
|
|
||||||
ThisValue is <b>NOT true</b>.<br>
|
|
||||||
{{{!FOREACH ArrayValueSecond}}}
|
|
||||||
{{{ArrayValueSecond}}}<br>
|
|
||||||
{{{!IF ThisOtherValue==true}}}
|
|
||||||
ThisOtherValue is <b>true</b>.<br>
|
|
||||||
{{{Var}}}<br>
|
|
||||||
{{{!ELSE}}}
|
|
||||||
ThisOtherValue is <b>NOT true</b>.<br>
|
|
||||||
{{{Var}}}<br>
|
|
||||||
{{{!ENDIF}}}
|
|
||||||
{{{!ENDFOREACH}}}
|
|
||||||
{{{!ENDIF}}}
|
|
||||||
{{{!ENDFOREACH}}}
|
|
||||||
</pre><br>
|
|
||||||
|
|
||||||
Nested FOREACH:<br>
|
|
||||||
<pre>
|
|
||||||
{{{!FOREACH ArrayValue}}}
|
|
||||||
{{{ArrayValue}}}
|
|
||||||
{{{!FOREACH ArrayValueSecond}}}
|
|
||||||
{{{ArrayValueSecond}}}
|
|
||||||
{{{!FOREACH ArrayValueThird}}}
|
|
||||||
{{{ArrayValueThird}}}
|
|
||||||
{{{!FOREACH ArrayValueFourth}}}
|
|
||||||
{{{ArrayValueFourth}}}
|
|
||||||
{{{!FOREACH Each_FILE}}}
|
|
||||||
{{{Each_FILE}}}
|
|
||||||
{{{!ENDFOREACH}}}
|
|
||||||
{{{!ENDFOREACH}}}
|
|
||||||
{{{!ENDFOREACH}}}
|
|
||||||
{{{!ENDFOREACH}}}
|
|
||||||
{{{!ENDFOREACH}}}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<br><h2><a href="/inner">inner</a></h2>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
Var='''Test var value'''
|
Var='''Test var value'''
|
||||||
ThisValue=true
|
|
||||||
ThisOtherValue=true
|
|
||||||
|
|
||||||
ArrayValue=1_IDX_Zero
|
|
||||||
ArrayValue=1_IDX_One
|
|
||||||
ArrayValue=1_IDX_Two
|
|
||||||
|
|
||||||
ArrayValueSecond=2_IDX_Zero
|
|
||||||
ArrayValueSecond=2_IDX_One
|
|
||||||
ArrayValueSecond=2_IDX_Two
|
|
||||||
|
|
||||||
ArrayValueThird=3_IDX_Zero
|
|
||||||
ArrayValueThird=3_IDX_One
|
|
||||||
ArrayValueThird=3_IDX_Two
|
|
||||||
|
|
||||||
ArrayValueFourth=4_IDX_Zero
|
|
||||||
ArrayValueFourth=4_IDX_One
|
|
||||||
ArrayValueFourth=4_IDX_Two
|
|
||||||
|
|
||||||
EachTestHead='''First Entry Head'''
|
|
||||||
EachTestMid='''First Entry Mid'''
|
|
||||||
EachTestTail='''First Entry Tail'''
|
|
||||||
|
|
||||||
EachTestHead='''Second Entry Head'''
|
|
||||||
EachTestMid='''Second Entry Mid'''
|
|
||||||
EachTestTail='''Second Entry Tail'''
|
|
||||||
|
|
||||||
EachTestHead='''Third Entry Head'''
|
|
||||||
EachTestMid='''Third Entry Mid'''
|
|
||||||
EachTestTail='''Third Entry Tail'''
|
|
||||||
|
|
||||||
Each_FILE='''example_config/each_file_zero.html'''
|
|
||||||
Each_FILE='''example_config/each_file_one.html'''
|
|
||||||
Each_FILE='''example_config/each_file_two.html'''
|
|
||||||
|
|
||||||
PATH=/inner
|
PATH=/inner
|
||||||
HTML_FILE='''example_config/inner.html'''
|
HTML_FILE='''example_config/inner.html'''
|
||||||
|
|
|
@ -44,9 +44,6 @@ void print_usage(void) {
|
||||||
puts(" --enable-cache-dir=<DIR>");
|
puts(" --enable-cache-dir=<DIR>");
|
||||||
puts(" --cache-entry-lifetime-seconds=<SECONDS>");
|
puts(" --cache-entry-lifetime-seconds=<SECONDS>");
|
||||||
puts(" --enable-static-dir=<DIR>");
|
puts(" --enable-static-dir=<DIR>");
|
||||||
puts(" --generate-dir=<DIR>");
|
|
||||||
puts(" --generate-enable-overwrite");
|
|
||||||
puts(" --generate-static-enable-overwrite");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Args parse_args(int32_t argc, char **argv) {
|
Args parse_args(int32_t argc, char **argv) {
|
||||||
|
@ -129,7 +126,7 @@ Args parse_args(int32_t argc, char **argv) {
|
||||||
exit(1);
|
exit(1);
|
||||||
} else {
|
} else {
|
||||||
printf(
|
printf(
|
||||||
"NOTICE set cache-entry-lifetime to %zu\n",
|
"NOTICE set cache-entry-lifetime to %lu\n",
|
||||||
args.cache_lifespan_seconds);
|
args.cache_lifespan_seconds);
|
||||||
}
|
}
|
||||||
} else if (strncmp(argv[0], "--enable-static-dir=", 20) == 0) {
|
} else if (strncmp(argv[0], "--enable-static-dir=", 20) == 0) {
|
||||||
|
@ -155,43 +152,6 @@ Args parse_args(int32_t argc, char **argv) {
|
||||||
printf("Directory \"%s\" exists.\n", args.static_dir);
|
printf("Directory \"%s\" exists.\n", args.static_dir);
|
||||||
}
|
}
|
||||||
closedir(d);
|
closedir(d);
|
||||||
} else if (strncmp(argv[0], "--generate-dir=", 15) == 0) {
|
|
||||||
args.generate_dir = argv[0] + 15;
|
|
||||||
// Check if it actually is an existing directory.
|
|
||||||
DIR *d = opendir(args.generate_dir);
|
|
||||||
if (d == NULL) {
|
|
||||||
if (errno == ENOENT) {
|
|
||||||
printf(
|
|
||||||
"Directory \"%s\" doesn't exist, creating it...\n",
|
|
||||||
args.generate_dir);
|
|
||||||
int ret = mkdir(
|
|
||||||
args.generate_dir,
|
|
||||||
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
|
||||||
if (ret == -1) {
|
|
||||||
fprintf(
|
|
||||||
stderr,
|
|
||||||
"ERROR Failed to create new directory (errno %d)\n",
|
|
||||||
errno);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(
|
|
||||||
stderr,
|
|
||||||
"ERROR Failed to open directory \"%s\" (errno %d)!\n",
|
|
||||||
args.generate_dir,
|
|
||||||
errno);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
printf("Directory \"%s\" exists.\n", args.generate_dir);
|
|
||||||
}
|
|
||||||
if (d) {
|
|
||||||
closedir(d);
|
|
||||||
}
|
|
||||||
} else if (strcmp(argv[0], "--generate-enable-overwrite") == 0) {
|
|
||||||
args.flags |= 4;
|
|
||||||
} else if (strcmp(argv[0], "--generate-static-enable-overwrite") == 0) {
|
|
||||||
args.flags |= 8;
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "ERROR: Invalid args!\n");
|
fprintf(stderr, "ERROR: Invalid args!\n");
|
||||||
print_usage();
|
print_usage();
|
||||||
|
|
|
@ -28,8 +28,6 @@ typedef struct Args {
|
||||||
// xxxx xxx1 - disable peer addr print.
|
// xxxx xxx1 - disable peer addr print.
|
||||||
// xxxx xx0x - disable listen on config file for reloading.
|
// xxxx xx0x - disable listen on config file for reloading.
|
||||||
// xxxx xx1x - enable listen on config file for reloading.
|
// xxxx xx1x - enable listen on config file for reloading.
|
||||||
// xxxx x1xx - enable overwrite on generate.
|
|
||||||
// xxxx 1xxx - enable overwrite on generate for static dir.
|
|
||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
// Does not need to be free'd, this should point to a string in argv.
|
// Does not need to be free'd, this should point to a string in argv.
|
||||||
|
@ -43,9 +41,6 @@ typedef struct Args {
|
||||||
// Non-NULL if static-dir is specified and files in the dir are to be served.
|
// Non-NULL if static-dir is specified and files in the dir are to be served.
|
||||||
// Does not need to be free'd since it points to a string in argv.
|
// Does not need to be free'd since it points to a string in argv.
|
||||||
const char *static_dir;
|
const char *static_dir;
|
||||||
// Non-NULL if generate-dir is specified.
|
|
||||||
// Does not need to be free'd since it points to a string in argv.
|
|
||||||
const char *generate_dir;
|
|
||||||
} Args;
|
} Args;
|
||||||
|
|
||||||
void print_usage(void);
|
void print_usage(void);
|
||||||
|
|
90
src/config.c
90
src/config.c
|
@ -36,23 +36,6 @@ typedef struct C_SIMPLE_HTTP_INTERNAL_RequiredCheck {
|
||||||
const SDArchiverLinkedList *required;
|
const SDArchiverLinkedList *required;
|
||||||
} C_SIMPLE_HTTP_INTERNAL_RequiredCheck;
|
} C_SIMPLE_HTTP_INTERNAL_RequiredCheck;
|
||||||
|
|
||||||
void c_simple_http_cleanup_config_value(
|
|
||||||
C_SIMPLE_HTTP_ConfigValue *config_value) {
|
|
||||||
if (config_value) {
|
|
||||||
if (config_value->next) {
|
|
||||||
c_simple_http_cleanup_config_value(config_value->next);
|
|
||||||
}
|
|
||||||
if(config_value->value) {
|
|
||||||
free(config_value->value);
|
|
||||||
}
|
|
||||||
free(config_value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void c_simple_http_cleanup_config_value_void_ptr(void *config_value) {
|
|
||||||
c_simple_http_cleanup_config_value(config_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
int c_simple_http_required_iter_fn(void *data, void *ud) {
|
int c_simple_http_required_iter_fn(void *data, void *ud) {
|
||||||
C_SIMPLE_HTTP_INTERNAL_RequiredIter *req_iter_struct = ud;
|
C_SIMPLE_HTTP_INTERNAL_RequiredIter *req_iter_struct = ud;
|
||||||
uint32_t data_str_length = (uint32_t)strlen(data) + 1;
|
uint32_t data_str_length = (uint32_t)strlen(data) + 1;
|
||||||
|
@ -143,6 +126,7 @@ void internal_double_quote_decrement(uint_fast8_t *double_quote_count,
|
||||||
/// Returns non-zero if config should be returned.
|
/// Returns non-zero if config should be returned.
|
||||||
int internal_check_add_value(uint32_t *state,
|
int internal_check_add_value(uint32_t *state,
|
||||||
char **key_buf,
|
char **key_buf,
|
||||||
|
uint32_t *key_capacity,
|
||||||
uint32_t *key_idx,
|
uint32_t *key_idx,
|
||||||
char **value_buf,
|
char **value_buf,
|
||||||
uint32_t *value_capacity,
|
uint32_t *value_capacity,
|
||||||
|
@ -204,26 +188,21 @@ int internal_check_add_value(uint32_t *state,
|
||||||
SDArchiverHashMap *hash_map = simple_archiver_hash_map_init();
|
SDArchiverHashMap *hash_map = simple_archiver_hash_map_init();
|
||||||
unsigned char *key = malloc(separating_key_size);
|
unsigned char *key = malloc(separating_key_size);
|
||||||
strncpy((char*)key, separating_key, separating_key_size);
|
strncpy((char*)key, separating_key, separating_key_size);
|
||||||
C_SIMPLE_HTTP_ConfigValue *config_value =
|
unsigned char *value = malloc(*value_idx);
|
||||||
malloc(sizeof(C_SIMPLE_HTTP_ConfigValue));
|
memcpy(value, *value_buf, (*value_idx));
|
||||||
config_value->value = malloc(*value_idx);
|
if (simple_archiver_hash_map_insert(hash_map,
|
||||||
config_value->next = NULL;
|
value,
|
||||||
memcpy(config_value->value, *value_buf, (*value_idx));
|
key,
|
||||||
if (simple_archiver_hash_map_insert(
|
separating_key_size,
|
||||||
hash_map,
|
NULL,
|
||||||
config_value,
|
NULL) != 0) {
|
||||||
key,
|
|
||||||
separating_key_size,
|
|
||||||
c_simple_http_cleanup_config_value_void_ptr,
|
|
||||||
NULL) != 0) {
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"ERROR: Failed to create hash map for new separating_key "
|
"ERROR: Failed to create hash map for new separating_key "
|
||||||
"block!\n");
|
"block!\n");
|
||||||
c_simple_http_clean_up_parsed_config(config);
|
c_simple_http_clean_up_parsed_config(config);
|
||||||
config->hash_map = NULL;
|
config->hash_map = NULL;
|
||||||
free(key);
|
free(key);
|
||||||
free(config_value->value);
|
free(value);
|
||||||
free(config_value);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,7 +213,7 @@ int internal_check_add_value(uint32_t *state,
|
||||||
if (simple_archiver_hash_map_insert(
|
if (simple_archiver_hash_map_insert(
|
||||||
config->hash_map,
|
config->hash_map,
|
||||||
wrapper,
|
wrapper,
|
||||||
config_value->value,
|
value,
|
||||||
(*value_idx),
|
(*value_idx),
|
||||||
c_simple_http_hash_map_wrapper_cleanup_hashmap_fn,
|
c_simple_http_hash_map_wrapper_cleanup_hashmap_fn,
|
||||||
simple_archiver_helper_datastructure_cleanup_nop) != 0) {
|
simple_archiver_helper_datastructure_cleanup_nop) != 0) {
|
||||||
|
@ -245,7 +224,7 @@ int internal_check_add_value(uint32_t *state,
|
||||||
c_simple_http_hash_map_wrapper_cleanup(wrapper);
|
c_simple_http_hash_map_wrapper_cleanup(wrapper);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
simple_archiver_list_add(paths, config_value->value,
|
simple_archiver_list_add(paths, value,
|
||||||
simple_archiver_helper_datastructure_cleanup_nop);
|
simple_archiver_helper_datastructure_cleanup_nop);
|
||||||
} else if (!(*current_separating_key_value)) {
|
} else if (!(*current_separating_key_value)) {
|
||||||
fprintf(
|
fprintf(
|
||||||
|
@ -276,37 +255,20 @@ int internal_check_add_value(uint32_t *state,
|
||||||
unsigned char *value = malloc(*value_idx);
|
unsigned char *value = malloc(*value_idx);
|
||||||
memcpy(value, *value_buf, (*value_idx));
|
memcpy(value, *value_buf, (*value_idx));
|
||||||
|
|
||||||
// Check if key already exists in wrapped hash-map.
|
if (simple_archiver_hash_map_insert(hash_map_wrapper->paths,
|
||||||
C_SIMPLE_HTTP_ConfigValue *config_value =
|
value,
|
||||||
simple_archiver_hash_map_get(hash_map_wrapper->paths, key, *key_idx);
|
key,
|
||||||
if (config_value) {
|
*key_idx,
|
||||||
while(config_value->next) {
|
NULL,
|
||||||
config_value = config_value->next;
|
NULL) != 0) {
|
||||||
}
|
fprintf(stderr,
|
||||||
config_value->next = malloc(sizeof(C_SIMPLE_HTTP_ConfigValue));
|
"ERROR: Internal error failed to insert into hash map with path "
|
||||||
config_value->next->value = (char*)value;
|
"\"%s\"!", (*current_separating_key_value));
|
||||||
config_value->next->next = NULL;
|
c_simple_http_clean_up_parsed_config(config);
|
||||||
|
config->hash_map = NULL;
|
||||||
free(key);
|
free(key);
|
||||||
} else {
|
free(value);
|
||||||
config_value = malloc(sizeof(C_SIMPLE_HTTP_ConfigValue));
|
return 1;
|
||||||
config_value->value = (char*)value;
|
|
||||||
config_value->next = NULL;
|
|
||||||
if (simple_archiver_hash_map_insert(
|
|
||||||
hash_map_wrapper->paths,
|
|
||||||
config_value,
|
|
||||||
key,
|
|
||||||
*key_idx,
|
|
||||||
c_simple_http_cleanup_config_value_void_ptr,
|
|
||||||
NULL) != 0) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"ERROR: Internal error failed to insert into hash map with path "
|
|
||||||
"\"%s\"!", (*current_separating_key_value));
|
|
||||||
c_simple_http_clean_up_parsed_config(config);
|
|
||||||
config->hash_map = NULL;
|
|
||||||
free(key);
|
|
||||||
free(value);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(*key_idx) = 0;
|
(*key_idx) = 0;
|
||||||
|
@ -534,6 +496,7 @@ C_SIMPLE_HTTP_ParsedConfig c_simple_http_parse_config(
|
||||||
} else {
|
} else {
|
||||||
if (internal_check_add_value(&state,
|
if (internal_check_add_value(&state,
|
||||||
&key_buf,
|
&key_buf,
|
||||||
|
&key_capacity,
|
||||||
&key_idx,
|
&key_idx,
|
||||||
&value_buf,
|
&value_buf,
|
||||||
&value_capacity,
|
&value_capacity,
|
||||||
|
@ -557,6 +520,7 @@ C_SIMPLE_HTTP_ParsedConfig c_simple_http_parse_config(
|
||||||
|
|
||||||
if (internal_check_add_value(&state,
|
if (internal_check_add_value(&state,
|
||||||
&key_buf,
|
&key_buf,
|
||||||
|
&key_capacity,
|
||||||
&key_idx,
|
&key_idx,
|
||||||
&value_buf,
|
&value_buf,
|
||||||
&value_capacity,
|
&value_capacity,
|
||||||
|
|
17
src/config.h
17
src/config.h
|
@ -25,14 +25,6 @@ typedef struct C_SIMPLE_HTTP_ParsedConfig {
|
||||||
/// Each entry in this data structure is a hash map where its value for the
|
/// Each entry in this data structure is a hash map where its value for the
|
||||||
/// key "PATH" is the path it represents. The "key" value should match the
|
/// key "PATH" is the path it represents. The "key" value should match the
|
||||||
/// mentioned value for "PATH".
|
/// mentioned value for "PATH".
|
||||||
///
|
|
||||||
/// An example mapping for this structure (based on current example config):
|
|
||||||
/// KEY: "/", VALUE: HashMapWrapper struct
|
|
||||||
/// KEY: "/inner", VALUE: HashMapWrapper struct
|
|
||||||
/// KEY: "/inner/further", VALUE: HashMapWrapper struct
|
|
||||||
///
|
|
||||||
/// Each HashMapWrapper struct's hash-map has the following:
|
|
||||||
/// KEY: VAR_NAME, VALUE: ConfigValue struct
|
|
||||||
union {
|
union {
|
||||||
SDArchiverHashMap *paths;
|
SDArchiverHashMap *paths;
|
||||||
SDArchiverHashMap *hash_map;
|
SDArchiverHashMap *hash_map;
|
||||||
|
@ -41,15 +33,6 @@ typedef struct C_SIMPLE_HTTP_ParsedConfig {
|
||||||
|
|
||||||
typedef C_SIMPLE_HTTP_ParsedConfig C_SIMPLE_HTTP_HashMapWrapper;
|
typedef C_SIMPLE_HTTP_ParsedConfig C_SIMPLE_HTTP_HashMapWrapper;
|
||||||
|
|
||||||
typedef struct C_SIMPLE_HTTP_ConfigValue {
|
|
||||||
char *value;
|
|
||||||
struct C_SIMPLE_HTTP_ConfigValue *next;
|
|
||||||
} C_SIMPLE_HTTP_ConfigValue;
|
|
||||||
|
|
||||||
void c_simple_http_cleanup_config_value(
|
|
||||||
C_SIMPLE_HTTP_ConfigValue *config_value);
|
|
||||||
void c_simple_http_cleanup_config_value_void_ptr(void *config_value);
|
|
||||||
|
|
||||||
/// Each line in the config should be a key-value pair separated by an equals
|
/// Each line in the config should be a key-value pair separated by an equals
|
||||||
/// sign "=". All whitespace is ignored unless if the value is "quoted". A part
|
/// sign "=". All whitespace is ignored unless if the value is "quoted". A part
|
||||||
/// of a string can be "quoted" if it is surrounded by three single-quotes or
|
/// of a string can be "quoted" if it is surrounded by three single-quotes or
|
||||||
|
|
175
src/generate.c
175
src/generate.c
|
@ -1,175 +0,0 @@
|
||||||
// ISC License
|
|
||||||
//
|
|
||||||
// Copyright (c) 2024 Stephen Seo
|
|
||||||
//
|
|
||||||
// Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
|
||||||
// copyright notice and this permission notice appear in all copies.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
||||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
||||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
||||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
||||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
||||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
||||||
// PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
|
|
||||||
#include "generate.h"
|
|
||||||
|
|
||||||
// Standard library includes.
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
// Linux/Unix includes.
|
|
||||||
#include <libgen.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
// Local includes.
|
|
||||||
#include "helpers.h"
|
|
||||||
#include "http_template.h"
|
|
||||||
|
|
||||||
// Third party includes.
|
|
||||||
#include <SimpleArchiver/src/helpers.h>
|
|
||||||
#include <SimpleArchiver/src/data_structures/hash_map.h>
|
|
||||||
#include <SimpleArchiver/src/data_structures/linked_list.h>
|
|
||||||
|
|
||||||
int c_simple_http_generate_paths_fn(const void *key,
|
|
||||||
size_t key_size,
|
|
||||||
__attribute__((unused)) const void *value,
|
|
||||||
void *ud) {
|
|
||||||
const char *path = key;
|
|
||||||
const ConnectionContext *ctx = ud;
|
|
||||||
const char *generate_dir = ctx->args->generate_dir;
|
|
||||||
|
|
||||||
const unsigned long path_len = key_size - 1;
|
|
||||||
const unsigned long generate_dir_len = strlen(generate_dir);
|
|
||||||
|
|
||||||
__attribute__((cleanup(simple_archiver_list_free)))
|
|
||||||
SDArchiverLinkedList *string_parts = simple_archiver_list_init();
|
|
||||||
|
|
||||||
// Add generate_dir as first path of paths to join.
|
|
||||||
c_simple_http_add_string_part(string_parts, generate_dir, 0);
|
|
||||||
|
|
||||||
// Ensure next character after generate_dir contains a '/' if generate_dir
|
|
||||||
// didn't contain one at the end.
|
|
||||||
if (generate_dir_len > 0 && generate_dir[generate_dir_len - 1] != '/') {
|
|
||||||
c_simple_http_add_string_part(string_parts, "/", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append the path.
|
|
||||||
if (strcmp(path, "/") != 0) {
|
|
||||||
// Is not root.
|
|
||||||
uint32_t idx = 0;
|
|
||||||
while (idx <= path_len && path[idx] == '/') {
|
|
||||||
++idx;
|
|
||||||
}
|
|
||||||
c_simple_http_add_string_part(string_parts, path + idx, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the final '/'.
|
|
||||||
if (path_len > 0 && path[path_len - 1] != '/') {
|
|
||||||
c_simple_http_add_string_part(string_parts, "/", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the ending "index.html".
|
|
||||||
c_simple_http_add_string_part(string_parts, "index.html", 0);
|
|
||||||
|
|
||||||
// Get the combined string.
|
|
||||||
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
|
||||||
char *generated_path = c_simple_http_combine_string_parts(string_parts);
|
|
||||||
if (!generated_path) {
|
|
||||||
fprintf(stderr, "ERROR Failed to get generated path (path: %s)!\n", path);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ctx->args->flags & 4) == 0) {
|
|
||||||
// Overwrite not enabled, check if file already exists.
|
|
||||||
FILE *fd = fopen(generated_path, "rb");
|
|
||||||
if (fd) {
|
|
||||||
fclose(fd);
|
|
||||||
fprintf(
|
|
||||||
stderr,
|
|
||||||
"WARNING Path \"%s\" exists and \"--generate-enable-overwrite\" not "
|
|
||||||
"specified, skipping!\n",
|
|
||||||
generated_path);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the required dirs exist.
|
|
||||||
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
|
||||||
char *generated_path_dup = strdup(generated_path);
|
|
||||||
|
|
||||||
uint_fast8_t did_make_generated_path_dir = 0;
|
|
||||||
char *generated_path_dir = dirname(generated_path_dup);
|
|
||||||
if (generated_path_dir) {
|
|
||||||
DIR *fd = opendir(generated_path_dir);
|
|
||||||
if (!fd) {
|
|
||||||
if (errno == ENOENT) {
|
|
||||||
c_simple_http_helper_mkdir_tree(generated_path_dir);
|
|
||||||
did_make_generated_path_dir = 1;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr,
|
|
||||||
"ERROR opendir on path dirname failed unexpectedly (path: %s)!"
|
|
||||||
"\n",
|
|
||||||
path);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Directory already exists.
|
|
||||||
closedir(fd);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr,
|
|
||||||
"ERROR Failed to get dirname of generated path dir (path: %s)"
|
|
||||||
"!\n",
|
|
||||||
path);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate the html.
|
|
||||||
size_t html_buf_size = 0;
|
|
||||||
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
|
||||||
char *html_buf = c_simple_http_path_to_generated(path,
|
|
||||||
ctx->parsed,
|
|
||||||
&html_buf_size,
|
|
||||||
NULL);
|
|
||||||
if (!html_buf || html_buf_size == 0) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"WARNING Failed to generate html for generate (path: %s), "
|
|
||||||
"skipping!\n",
|
|
||||||
path);
|
|
||||||
if (did_make_generated_path_dir) {
|
|
||||||
if (rmdir(generated_path_dir) == -1) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"WARNING rmdir on generated_path_dir failed, errno: %d\n",
|
|
||||||
errno);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the html.
|
|
||||||
FILE *fd = fopen(generated_path, "wb");
|
|
||||||
if (!fd) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"WARNING Failed to open \"%s\" for writing, skipping!\n",
|
|
||||||
generated_path);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
unsigned long fwrite_ret = fwrite(html_buf, 1, html_buf_size, fd);
|
|
||||||
if (fwrite_ret < html_buf_size) {
|
|
||||||
fclose(fd);
|
|
||||||
unlink(generated_path);
|
|
||||||
fprintf(stderr,
|
|
||||||
"ERROR Unable to write entirely to \"%s\"!\n",
|
|
||||||
generated_path);
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
fclose(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
// ISC License
|
|
||||||
//
|
|
||||||
// Copyright (c) 2024 Stephen Seo
|
|
||||||
//
|
|
||||||
// Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
|
||||||
// copyright notice and this permission notice appear in all copies.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
||||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
||||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
||||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
||||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
||||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
||||||
// PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef SEODISPARATE_COM_C_SIMPLE_HTTP_GENERATE_H_
|
|
||||||
#define SEODISPARATE_COM_C_SIMPLE_HTTP_GENERATE_H_
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
/// See this function's usage in main.c.
|
|
||||||
int c_simple_http_generate_paths_fn(const void *key,
|
|
||||||
size_t key_size,
|
|
||||||
const void *value,
|
|
||||||
void *ud);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// vim: et ts=2 sts=2 sw=2
|
|
108
src/helpers.c
108
src/helpers.c
|
@ -17,7 +17,6 @@
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
// Standard library includes.
|
// Standard library includes.
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -25,6 +24,7 @@
|
||||||
// libc includes.
|
// libc includes.
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
|
||||||
|
@ -32,9 +32,7 @@ int c_simple_http_internal_get_string_part_full_size(void *data, void *ud) {
|
||||||
C_SIMPLE_HTTP_String_Part *part = data;
|
C_SIMPLE_HTTP_String_Part *part = data;
|
||||||
size_t *count = ud;
|
size_t *count = ud;
|
||||||
|
|
||||||
if (part->size > 0) {
|
*count += part->size - 1;
|
||||||
*count += part->size - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -89,36 +87,9 @@ void c_simple_http_add_string_part(
|
||||||
C_SIMPLE_HTTP_String_Part *string_part =
|
C_SIMPLE_HTTP_String_Part *string_part =
|
||||||
malloc(sizeof(C_SIMPLE_HTTP_String_Part));
|
malloc(sizeof(C_SIMPLE_HTTP_String_Part));
|
||||||
|
|
||||||
if (c_string) {
|
string_part->size = strlen(c_string) + 1;
|
||||||
string_part->size = strlen(c_string) + 1;
|
string_part->buf = malloc(string_part->size);
|
||||||
string_part->buf = malloc(string_part->size);
|
memcpy(string_part->buf, c_string, string_part->size);
|
||||||
memcpy(string_part->buf, c_string, string_part->size);
|
|
||||||
} else {
|
|
||||||
string_part->size = 0;
|
|
||||||
string_part->buf = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
string_part->extra = extra;
|
|
||||||
simple_archiver_list_add(
|
|
||||||
list, string_part, c_simple_http_cleanup_string_part);
|
|
||||||
}
|
|
||||||
|
|
||||||
void c_simple_http_add_string_part_sized(
|
|
||||||
SDArchiverLinkedList *list,
|
|
||||||
const char *buffer,
|
|
||||||
size_t size,
|
|
||||||
uintptr_t extra) {
|
|
||||||
C_SIMPLE_HTTP_String_Part *string_part =
|
|
||||||
malloc(sizeof(C_SIMPLE_HTTP_String_Part));
|
|
||||||
|
|
||||||
if (buffer && size > 0) {
|
|
||||||
string_part->size = size;
|
|
||||||
string_part->buf = malloc(string_part->size - 1);
|
|
||||||
memcpy(string_part->buf, buffer, string_part->size - 1);
|
|
||||||
} else {
|
|
||||||
string_part->size = 0;
|
|
||||||
string_part->buf = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
string_part->extra = extra;
|
string_part->extra = extra;
|
||||||
|
|
||||||
|
@ -287,73 +258,4 @@ int c_simple_http_helper_mkdir_tree(const char *path) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void c_simple_http_cleanup_DIR(DIR **fd) {
|
|
||||||
if (fd && *fd) {
|
|
||||||
closedir(*fd);
|
|
||||||
*fd = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char *c_simple_http_FILE_to_c_str(const char *filename, uint64_t *size_out) {
|
|
||||||
FILE *fd = fopen(filename, "rb");
|
|
||||||
if (!fd) {
|
|
||||||
fprintf(stderr, "ERROR Failed to open %s!\n", filename);
|
|
||||||
return NULL;
|
|
||||||
} else if (fseek(fd, 0, SEEK_END) != 0) {
|
|
||||||
fprintf(stderr, "ERROR Failed to seek to end of %s!\n", filename);
|
|
||||||
fclose(fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
long size = ftell(fd);
|
|
||||||
if (size < 0) {
|
|
||||||
fprintf(stderr, "ERROR Failed to get seek pos of end of %s!\n", filename);
|
|
||||||
fclose(fd);
|
|
||||||
return NULL;
|
|
||||||
} else if (size == 0) {
|
|
||||||
fprintf(stderr, "ERROR Size of file \"%s\" is zero!\n", filename);
|
|
||||||
fclose(fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (size_out) {
|
|
||||||
*size_out = (uint64_t)size;
|
|
||||||
}
|
|
||||||
char *buf = malloc((uint64_t)size + 1);
|
|
||||||
if (fseek(fd, 0, SEEK_SET) != 0) {
|
|
||||||
fprintf(stderr, "ERROR Failed to seek to beginning of %s!\n", filename);
|
|
||||||
free(buf);
|
|
||||||
fclose(fd);
|
|
||||||
return NULL;
|
|
||||||
} else if (fread(buf, 1, (uint64_t)size, fd) != (uint64_t)size) {
|
|
||||||
fprintf(stderr, "ERROR Failed to read from file %s!\n", filename);
|
|
||||||
free(buf);
|
|
||||||
fclose(fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[size] = 0;
|
|
||||||
|
|
||||||
fclose(fd);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t c_simple_http_trim_end_whitespace(char *c_str) {
|
|
||||||
size_t trimmed = 0;
|
|
||||||
|
|
||||||
uint64_t idx= strlen(c_str);
|
|
||||||
for (; idx-- > 0;) {
|
|
||||||
if (c_str[idx] == ' '
|
|
||||||
|| c_str[idx] == '\n'
|
|
||||||
|| c_str[idx] == '\r'
|
|
||||||
|| c_str[idx] == '\t') {
|
|
||||||
c_str[idx] = 0;
|
|
||||||
++trimmed;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return trimmed;
|
|
||||||
}
|
|
||||||
|
|
||||||
// vim: et ts=2 sts=2 sw=2
|
// vim: et ts=2 sts=2 sw=2
|
||||||
|
|
|
@ -21,24 +21,9 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
// libc includes.
|
|
||||||
#include <time.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
|
|
||||||
// Local includes.
|
|
||||||
#include "config.h"
|
|
||||||
#include "arg_parse.h"
|
|
||||||
|
|
||||||
// Third-party includes.
|
// Third-party includes.
|
||||||
#include <SimpleArchiver/src/data_structures/linked_list.h>
|
#include <SimpleArchiver/src/data_structures/linked_list.h>
|
||||||
|
|
||||||
typedef struct ConnectionContext {
|
|
||||||
char *buf;
|
|
||||||
const Args *args;
|
|
||||||
C_SIMPLE_HTTP_ParsedConfig *parsed;
|
|
||||||
struct timespec current_time;
|
|
||||||
} ConnectionContext;
|
|
||||||
|
|
||||||
typedef struct C_SIMPLE_HTTP_String_Part {
|
typedef struct C_SIMPLE_HTTP_String_Part {
|
||||||
char *buf;
|
char *buf;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
@ -56,16 +41,6 @@ void c_simple_http_cleanup_string_part(void *data);
|
||||||
void c_simple_http_add_string_part(
|
void c_simple_http_add_string_part(
|
||||||
SDArchiverLinkedList *list, const char *c_string, uintptr_t extra);
|
SDArchiverLinkedList *list, const char *c_string, uintptr_t extra);
|
||||||
|
|
||||||
/// Puts a malloced instance of String_Part into the list.
|
|
||||||
/// The given c_string will be copied into a newly malloced buffer.
|
|
||||||
/// "size" must include NULL if "buffer" is a c_string.
|
|
||||||
/// If there is no NULL at the end, "size" must be +1 actual size.
|
|
||||||
void c_simple_http_add_string_part_sized(
|
|
||||||
SDArchiverLinkedList *list,
|
|
||||||
const char *buffer,
|
|
||||||
size_t size,
|
|
||||||
uintptr_t extra);
|
|
||||||
|
|
||||||
/// Combines all String_Parts in the list and returns it as a single buffer.
|
/// Combines all String_Parts in the list and returns it as a single buffer.
|
||||||
char *c_simple_http_combine_string_parts(const SDArchiverLinkedList *list);
|
char *c_simple_http_combine_string_parts(const SDArchiverLinkedList *list);
|
||||||
|
|
||||||
|
@ -88,15 +63,6 @@ char *c_simple_http_helper_unescape_uri(const char *uri);
|
||||||
/// Other return values are errors.
|
/// Other return values are errors.
|
||||||
int c_simple_http_helper_mkdir_tree(const char *dirpath);
|
int c_simple_http_helper_mkdir_tree(const char *dirpath);
|
||||||
|
|
||||||
void c_simple_http_cleanup_DIR(DIR **fd);
|
|
||||||
|
|
||||||
/// Must be free'd if non-NULL.
|
|
||||||
char *c_simple_http_FILE_to_c_str(const char *filename, uint64_t *size_out);
|
|
||||||
|
|
||||||
/// Trims by placing NULL bytes in place of whitespace at the end of c_str.
|
|
||||||
/// Returns number of whitespace trimmed.
|
|
||||||
size_t c_simple_http_trim_end_whitespace(char *c_str);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// vim: et ts=2 sts=2 sw=2
|
// vim: et ts=2 sts=2 sw=2
|
||||||
|
|
|
@ -38,12 +38,8 @@
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "http_template.h"
|
#include "http_template.h"
|
||||||
|
|
||||||
int c_simple_http_internal_write_filenames_to_cache_file(
|
int c_simple_http_internal_write_filenames_to_cache_file(void *data, void *ud) {
|
||||||
const void *key,
|
char *filename = data;
|
||||||
__attribute__((unused)) size_t key_size,
|
|
||||||
__attribute__((unused)) const void *value,
|
|
||||||
void *ud) {
|
|
||||||
const char *filename = key;
|
|
||||||
FILE *cache_fd = ud;
|
FILE *cache_fd = ud;
|
||||||
|
|
||||||
const size_t filename_size = strlen(filename);
|
const size_t filename_size = strlen(filename);
|
||||||
|
@ -440,8 +436,8 @@ CACHE_FILE_WRITE_CHECK:
|
||||||
return -5;
|
return -5;
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((cleanup(simple_archiver_hash_map_free)))
|
__attribute__((cleanup(simple_archiver_list_free)))
|
||||||
SDArchiverHashMap *used_filenames = NULL;
|
SDArchiverLinkedList *used_filenames = NULL;
|
||||||
|
|
||||||
size_t generated_html_size = 0;
|
size_t generated_html_size = 0;
|
||||||
|
|
||||||
|
@ -456,10 +452,10 @@ CACHE_FILE_WRITE_CHECK:
|
||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (simple_archiver_hash_map_iter(
|
if (simple_archiver_list_get(
|
||||||
used_filenames,
|
used_filenames,
|
||||||
c_simple_http_internal_write_filenames_to_cache_file,
|
c_simple_http_internal_write_filenames_to_cache_file,
|
||||||
cache_fd) != 0) {
|
cache_fd)) {
|
||||||
fprintf(stderr, "ERROR Failed to write filenames to cache file!\n");
|
fprintf(stderr, "ERROR Failed to write filenames to cache file!\n");
|
||||||
return -6;
|
return -6;
|
||||||
} else if (fwrite("--- BEGIN HTML ---\n", 1, 19, cache_fd) != 19) {
|
} else if (fwrite("--- BEGIN HTML ---\n", 1, 19, cache_fd) != 19) {
|
||||||
|
|
1283
src/http_template.c
1283
src/http_template.c
File diff suppressed because it is too large
Load diff
|
@ -17,16 +17,13 @@
|
||||||
#ifndef SEODISPARATE_COM_C_SIMPLE_HTTP_HTTP_TEMPLATE_H_
|
#ifndef SEODISPARATE_COM_C_SIMPLE_HTTP_HTTP_TEMPLATE_H_
|
||||||
#define SEODISPARATE_COM_C_SIMPLE_HTTP_HTTP_TEMPLATE_H_
|
#define SEODISPARATE_COM_C_SIMPLE_HTTP_HTTP_TEMPLATE_H_
|
||||||
|
|
||||||
|
#include "http.h"
|
||||||
|
|
||||||
// Standard library includes.
|
// Standard library includes.
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
// Third-party includes.
|
// Third-party includes.
|
||||||
#include <SimpleArchiver/src/data_structures/linked_list.h>
|
#include <SimpleArchiver/src/data_structures/linked_list.h>
|
||||||
#include <SimpleArchiver/src/data_structures/hash_map.h>
|
|
||||||
|
|
||||||
// Local includes.
|
|
||||||
#include "http.h"
|
|
||||||
|
|
||||||
// Returns non-NULL on success, which must be free'd after use. Takes a path
|
// Returns non-NULL on success, which must be free'd after use. Takes a path
|
||||||
// string and templates and returns the generated HTML. If "output_buf_size" is
|
// string and templates and returns the generated HTML. If "output_buf_size" is
|
||||||
|
@ -38,7 +35,7 @@ char *c_simple_http_path_to_generated(
|
||||||
const char *path,
|
const char *path,
|
||||||
const C_SIMPLE_HTTP_HTTPTemplates *templates,
|
const C_SIMPLE_HTTP_HTTPTemplates *templates,
|
||||||
size_t *output_buf_size,
|
size_t *output_buf_size,
|
||||||
SDArchiverHashMap **files_set_out);
|
SDArchiverLinkedList **files_list_out);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
51
src/main.c
51
src/main.c
|
@ -19,7 +19,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
// Linux/Unix includes.
|
// Linux/Unix includes.
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
@ -34,17 +33,13 @@
|
||||||
|
|
||||||
// Third party includes.
|
// Third party includes.
|
||||||
#include <SimpleArchiver/src/helpers.h>
|
#include <SimpleArchiver/src/helpers.h>
|
||||||
#include <SimpleArchiver/src/data_structures/hash_map.h>
|
|
||||||
#include <SimpleArchiver/src/data_structures/linked_list.h>
|
|
||||||
|
|
||||||
// Local includes.
|
// Local includes.
|
||||||
#include "arg_parse.h"
|
#include "arg_parse.h"
|
||||||
#include "big_endian.h"
|
#include "big_endian.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "http_template.h"
|
|
||||||
#include "tcp_socket.h"
|
#include "tcp_socket.h"
|
||||||
#include "signal_handling.h"
|
#include "signal_handling.h"
|
||||||
#include "generate.h"
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "http.h"
|
#include "http.h"
|
||||||
|
@ -79,6 +74,13 @@ typedef struct ConnectionItem {
|
||||||
struct in6_addr peer_addr;
|
struct in6_addr peer_addr;
|
||||||
} ConnectionItem;
|
} ConnectionItem;
|
||||||
|
|
||||||
|
typedef struct ConnectionContext {
|
||||||
|
char *buf;
|
||||||
|
const Args *args;
|
||||||
|
C_SIMPLE_HTTP_ParsedConfig *parsed;
|
||||||
|
struct timespec current_time;
|
||||||
|
} ConnectionContext;
|
||||||
|
|
||||||
void c_simple_http_cleanup_connection_item(void *data) {
|
void c_simple_http_cleanup_connection_item(void *data) {
|
||||||
ConnectionItem *citem = data;
|
ConnectionItem *citem = data;
|
||||||
if (citem) {
|
if (citem) {
|
||||||
|
@ -233,7 +235,7 @@ int c_simple_http_manage_connections(void *data, void *ud) {
|
||||||
snprintf(
|
snprintf(
|
||||||
content_length_buf + content_length_buf_size,
|
content_length_buf + content_length_buf_size,
|
||||||
127 - content_length_buf_size,
|
127 - content_length_buf_size,
|
||||||
"%zu\n%n",
|
"%lu\n%n",
|
||||||
response_size,
|
response_size,
|
||||||
&written);
|
&written);
|
||||||
if (written <= 0) {
|
if (written <= 0) {
|
||||||
|
@ -305,7 +307,7 @@ int c_simple_http_manage_connections(void *data, void *ud) {
|
||||||
snprintf(
|
snprintf(
|
||||||
content_length_buf,
|
content_length_buf,
|
||||||
content_str_len + 1 + 16 + 1,
|
content_str_len + 1 + 16 + 1,
|
||||||
"Content-Length: %" PRIu64 "\n",
|
"Content-Length: %lu\n",
|
||||||
file_info.buf_size);
|
file_info.buf_size);
|
||||||
CHECK_ERROR_WRITE_NO_FD(write(
|
CHECK_ERROR_WRITE_NO_FD(write(
|
||||||
citem->fd, content_length_buf, content_str_len + 1 + 16));
|
citem->fd, content_length_buf, content_str_len + 1 + 16));
|
||||||
|
@ -346,34 +348,6 @@ int main(int argc, char **argv) {
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If generate-dir is specified, the program must stop after generating or
|
|
||||||
// failure.
|
|
||||||
if (args.generate_dir) {
|
|
||||||
ConnectionContext ctx;
|
|
||||||
ctx.args = &args;
|
|
||||||
ctx.parsed = &parsed_config;
|
|
||||||
printf("Generating html files to \"%s\"...\n", args.generate_dir);
|
|
||||||
if (simple_archiver_hash_map_iter(parsed_config.paths,
|
|
||||||
c_simple_http_generate_paths_fn,
|
|
||||||
&ctx)) {
|
|
||||||
fprintf(stderr, "ERROR during generating!\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
puts("Finished generating.");
|
|
||||||
if (args.static_dir) {
|
|
||||||
puts("Static dir option specified, copying over static dir entries...");
|
|
||||||
if (c_simple_http_static_copy_over_dir(args.static_dir,
|
|
||||||
args.generate_dir,
|
|
||||||
(args.flags & 8) != 0 ? 1 : 0)
|
|
||||||
!= 0) {
|
|
||||||
fprintf(stderr, "ERROR during static-dir-entires copying!\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
puts("Finished copying over static-dir files.");
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((cleanup(cleanup_tcp_socket))) int tcp_socket =
|
__attribute__((cleanup(cleanup_tcp_socket))) int tcp_socket =
|
||||||
create_tcp_socket(args.port);
|
create_tcp_socket(args.port);
|
||||||
if (tcp_socket == -1) {
|
if (tcp_socket == -1) {
|
||||||
|
@ -386,8 +360,7 @@ int main(int argc, char **argv) {
|
||||||
socklen_t size = sizeof(ipv6_addr);
|
socklen_t size = sizeof(ipv6_addr);
|
||||||
int ret = getsockname(tcp_socket, (struct sockaddr*)&ipv6_addr, &size);
|
int ret = getsockname(tcp_socket, (struct sockaddr*)&ipv6_addr, &size);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
printf("Listening on port: %" PRIu16 "\n",
|
printf("Listening on port: %u\n", u16_be_swap(ipv6_addr.sin6_port));
|
||||||
u16_be_swap(ipv6_addr.sin6_port));
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(
|
fprintf(
|
||||||
stderr,
|
stderr,
|
||||||
|
@ -464,7 +437,7 @@ int main(int argc, char **argv) {
|
||||||
++config_try_reload_attempts;
|
++config_try_reload_attempts;
|
||||||
fprintf(
|
fprintf(
|
||||||
stderr,
|
stderr,
|
||||||
"Attempting to reload config now (try %" PRIu32 " of %u)...\n",
|
"Attempting to reload config now (try %u of %u)...\n",
|
||||||
config_try_reload_attempts,
|
config_try_reload_attempts,
|
||||||
C_SIMPLE_HTTP_TRY_CONFIG_RELOAD_MAX_ATTEMPTS);
|
C_SIMPLE_HTTP_TRY_CONFIG_RELOAD_MAX_ATTEMPTS);
|
||||||
C_SIMPLE_HTTP_ParsedConfig new_parsed_config =
|
C_SIMPLE_HTTP_ParsedConfig new_parsed_config =
|
||||||
|
@ -534,7 +507,7 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
} else if (read_ret > 0) {
|
} else if (read_ret > 0) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
printf("DEBUG inotify_event->mask: %" PRIx32 "\n", inotify_event->mask);
|
printf("DEBUG inotify_event->mask: %x\n", inotify_event->mask);
|
||||||
#endif
|
#endif
|
||||||
if ((inotify_event->mask & IN_MODIFY) != 0
|
if ((inotify_event->mask & IN_MODIFY) != 0
|
||||||
|| (inotify_event->mask & IN_CLOSE_WRITE) != 0) {
|
|| (inotify_event->mask & IN_CLOSE_WRITE) != 0) {
|
||||||
|
|
168
src/static.c
168
src/static.c
|
@ -31,17 +31,10 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <libgen.h>
|
|
||||||
|
|
||||||
// Third party includes.
|
// Third party includes.
|
||||||
#include "SimpleArchiver/src/data_structures/linked_list.h"
|
|
||||||
#include "SimpleArchiver/src/helpers.h"
|
#include "SimpleArchiver/src/helpers.h"
|
||||||
|
|
||||||
// Local includes.
|
|
||||||
#include "helpers.h"
|
|
||||||
|
|
||||||
char **environ;
|
char **environ;
|
||||||
|
|
||||||
void internal_fd_cleanup_helper(int *fd) {
|
void internal_fd_cleanup_helper(int *fd) {
|
||||||
|
@ -187,9 +180,7 @@ C_SIMPLE_HTTP_StaticFileInfo c_simple_http_get_file(
|
||||||
|
|
||||||
if (fd == NULL) {
|
if (fd == NULL) {
|
||||||
fprintf(
|
fprintf(
|
||||||
stderr,
|
stderr, "WARNING Failed to open path \"%s\" in static dir!\n", path + idx);
|
||||||
"WARNING Failed to open path \"%s\" in static dir!\n",
|
|
||||||
path + idx);
|
|
||||||
file_info.result = STATIC_FILE_RESULT_404NotFound;
|
file_info.result = STATIC_FILE_RESULT_404NotFound;
|
||||||
return file_info;
|
return file_info;
|
||||||
}
|
}
|
||||||
|
@ -340,161 +331,4 @@ int c_simple_http_static_validate_path(const char *path) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int c_simple_http_static_copy_over_dir(const char *from,
|
|
||||||
const char *to,
|
|
||||||
uint_fast8_t overwrite_enabled) {
|
|
||||||
__attribute__((cleanup(c_simple_http_cleanup_DIR)))
|
|
||||||
DIR *from_fd = opendir(from);
|
|
||||||
if (!from_fd) {
|
|
||||||
fprintf(stderr, "ERROR Failed to open directory \"%s\"!\n", from);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned long from_len = strlen(from);
|
|
||||||
const unsigned long to_len = strlen(to);
|
|
||||||
|
|
||||||
struct dirent *dir_entry = NULL;
|
|
||||||
do {
|
|
||||||
dir_entry = readdir(from_fd);
|
|
||||||
if (!dir_entry) {
|
|
||||||
break;
|
|
||||||
} else if (strcmp(dir_entry->d_name, ".") == 0
|
|
||||||
|| strcmp(dir_entry->d_name, "..") == 0) {
|
|
||||||
continue;
|
|
||||||
} else if (dir_entry->d_type == DT_DIR) {
|
|
||||||
// Dir entry is a directory.
|
|
||||||
__attribute__((cleanup(simple_archiver_list_free)))
|
|
||||||
SDArchiverLinkedList *string_parts = simple_archiver_list_init();
|
|
||||||
c_simple_http_add_string_part(string_parts, from, 0);
|
|
||||||
if (from_len > 0 && from[from_len - 1] != '/') {
|
|
||||||
c_simple_http_add_string_part(string_parts, "/", 0);
|
|
||||||
}
|
|
||||||
c_simple_http_add_string_part(string_parts, dir_entry->d_name, 0);
|
|
||||||
|
|
||||||
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
|
||||||
char *combined_from = c_simple_http_combine_string_parts(string_parts);
|
|
||||||
|
|
||||||
simple_archiver_list_free(&string_parts);
|
|
||||||
string_parts = simple_archiver_list_init();
|
|
||||||
c_simple_http_add_string_part(string_parts, to, 0);
|
|
||||||
if (to_len > 0 && to[to_len - 1] != '/') {
|
|
||||||
c_simple_http_add_string_part(string_parts, "/", 0);
|
|
||||||
}
|
|
||||||
c_simple_http_add_string_part(string_parts, dir_entry->d_name, 0);
|
|
||||||
|
|
||||||
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
|
||||||
char *combined_to = c_simple_http_combine_string_parts(string_parts);
|
|
||||||
|
|
||||||
int ret = c_simple_http_static_copy_over_dir(combined_from,
|
|
||||||
combined_to,
|
|
||||||
overwrite_enabled);
|
|
||||||
if (ret != 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
} else if (dir_entry->d_type == DT_REG) {
|
|
||||||
// Dir entry is a file.
|
|
||||||
__attribute__((cleanup(simple_archiver_list_free)))
|
|
||||||
SDArchiverLinkedList *string_parts = simple_archiver_list_init();
|
|
||||||
c_simple_http_add_string_part(string_parts, from, 0);
|
|
||||||
if (from_len > 0 && from[from_len - 1] != '/') {
|
|
||||||
c_simple_http_add_string_part(string_parts, "/", 0);
|
|
||||||
}
|
|
||||||
c_simple_http_add_string_part(string_parts, dir_entry->d_name, 0);
|
|
||||||
|
|
||||||
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
|
||||||
char *combined_from = c_simple_http_combine_string_parts(string_parts);
|
|
||||||
|
|
||||||
simple_archiver_list_free(&string_parts);
|
|
||||||
string_parts = simple_archiver_list_init();
|
|
||||||
c_simple_http_add_string_part(string_parts, to, 0);
|
|
||||||
if (to_len > 0 && to[to_len - 1] != '/') {
|
|
||||||
c_simple_http_add_string_part(string_parts, "/", 0);
|
|
||||||
}
|
|
||||||
c_simple_http_add_string_part(string_parts, dir_entry->d_name, 0);
|
|
||||||
|
|
||||||
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
|
||||||
char *combined_to = c_simple_http_combine_string_parts(string_parts);
|
|
||||||
|
|
||||||
if (!overwrite_enabled) {
|
|
||||||
__attribute__((cleanup(simple_archiver_helper_cleanup_FILE)))
|
|
||||||
FILE *fd = fopen(combined_to, "rb");
|
|
||||||
if (fd) {
|
|
||||||
fprintf(
|
|
||||||
stderr,
|
|
||||||
"WARNING \"%s\" already exists and "
|
|
||||||
"--generate-static-enable-overwrite not specified, skipping!\n",
|
|
||||||
combined_to);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
|
||||||
char *combined_to_dup = strdup(combined_to);
|
|
||||||
char *combined_to_dirname = dirname(combined_to_dup);
|
|
||||||
|
|
||||||
int ret = c_simple_http_helper_mkdir_tree(combined_to_dirname);
|
|
||||||
if (ret != 0 && ret != 1) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"ERROR Failed to create directory \"%s\"!\n",
|
|
||||||
combined_to_dirname);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((cleanup(simple_archiver_helper_cleanup_FILE)))
|
|
||||||
FILE *from_file_fd = fopen(combined_from, "rb");
|
|
||||||
if (!from_file_fd) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"ERROR Failed to open file \"%s\" for reading!\n",
|
|
||||||
combined_from);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((cleanup(simple_archiver_helper_cleanup_FILE)))
|
|
||||||
FILE *to_file_fd = fopen(combined_to, "wb");
|
|
||||||
if (!to_file_fd) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"ERROR Failed to open file \"%s\" for writing!\n",
|
|
||||||
combined_to);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char buf[1024];
|
|
||||||
size_t fread_ret;
|
|
||||||
unsigned long fwrite_ret;
|
|
||||||
while (!feof(from_file_fd)
|
|
||||||
&& !ferror(from_file_fd)
|
|
||||||
&& !ferror(to_file_fd)) {
|
|
||||||
fread_ret = fread(buf, 1, 1024, from_file_fd);
|
|
||||||
if (fread_ret > 0) {
|
|
||||||
fwrite_ret = fwrite(buf, 1, fread_ret, to_file_fd);
|
|
||||||
if (fwrite_ret < fread_ret) {
|
|
||||||
fprintf(
|
|
||||||
stderr,
|
|
||||||
"ERROR Writing to file \"%s\" (not all bytes written)!\n",
|
|
||||||
combined_to);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ferror(from_file_fd)) {
|
|
||||||
fprintf(stderr, "ERROR Reading from file \"%s\"!\n", combined_from);
|
|
||||||
return 1;
|
|
||||||
} else if (ferror(to_file_fd)) {
|
|
||||||
fprintf(stderr, "ERROR Writing to file \"%s\"!\n", combined_to);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s -> %s\n", combined_from, combined_to);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr,
|
|
||||||
"WARNING Non-dir and non-file \"%s/%s\", skipping...\n",
|
|
||||||
from,
|
|
||||||
dir_entry->d_name);
|
|
||||||
}
|
|
||||||
} while (dir_entry != NULL);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// vim: et ts=2 sts=2 sw=2
|
// vim: et ts=2 sts=2 sw=2
|
||||||
|
|
|
@ -51,11 +51,6 @@ C_SIMPLE_HTTP_StaticFileInfo c_simple_http_get_file(
|
||||||
/// Returns zero if OK.
|
/// Returns zero if OK.
|
||||||
int c_simple_http_static_validate_path(const char *path);
|
int c_simple_http_static_validate_path(const char *path);
|
||||||
|
|
||||||
/// Copies all files in "from" into "to". Returns non-zero on failure.
|
|
||||||
int c_simple_http_static_copy_over_dir(const char *from,
|
|
||||||
const char *to,
|
|
||||||
uint_fast8_t overwrite_enabled);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// vim: et ts=2 sts=2 sw=2
|
// vim: et ts=2 sts=2 sw=2
|
||||||
|
|
123
src/test.c
123
src/test.c
|
@ -3,7 +3,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
// POSIX includes.
|
// POSIX includes.
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -29,10 +28,7 @@ static int32_t checks_passed = 0;
|
||||||
|
|
||||||
#define RETURN() \
|
#define RETURN() \
|
||||||
do { \
|
do { \
|
||||||
fprintf(stderr, \
|
fprintf(stderr, "checked %d\npassed %d\n", checks_checked, checks_passed);\
|
||||||
"checked %" PRId32 "\npassed %" PRId32 "\n", \
|
|
||||||
checks_checked, \
|
|
||||||
checks_passed); \
|
|
||||||
return checks_checked == checks_passed ? 0 : 1; \
|
return checks_checked == checks_passed ? 0 : 1; \
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
|
@ -103,13 +99,9 @@ void test_internal_cleanup_delete_temporary_file(const char **filename) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int test_internal_check_matching_string_in_list(
|
int test_internal_check_matching_string_in_list(void *value, void *ud) {
|
||||||
const void *key,
|
if (value && ud) {
|
||||||
__attribute__((unused)) size_t key_size,
|
if (strcmp(value, ud) == 0) {
|
||||||
__attribute__((unused)) const void *value,
|
|
||||||
void *ud) {
|
|
||||||
if (key && ud) {
|
|
||||||
if (strcmp(key, ud) == 0) {
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,53 +173,46 @@ int main(int argc, char **argv) {
|
||||||
simple_archiver_hash_map_get(templates.paths, "/", 2);
|
simple_archiver_hash_map_get(templates.paths, "/", 2);
|
||||||
ASSERT_TRUE(first_path_map_wrapper);
|
ASSERT_TRUE(first_path_map_wrapper);
|
||||||
|
|
||||||
C_SIMPLE_HTTP_ConfigValue *value =
|
const char *value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "PATH", 5);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "PATH", 5);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
ASSERT_TRUE(value->value);
|
ASSERT_STREQ(value, "/");
|
||||||
ASSERT_STREQ(value->value, "/");
|
|
||||||
|
|
||||||
value =
|
value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "HTML", 5);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "HTML", 5);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
ASSERT_TRUE(value->value);
|
|
||||||
// printf("%s\n", value);
|
// printf("%s\n", value);
|
||||||
ASSERT_STREQ(value->value, " one two three ");
|
ASSERT_STREQ(value, " one two three ");
|
||||||
|
|
||||||
value =
|
value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST", 5);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST", 5);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
ASSERT_TRUE(value->value);
|
|
||||||
// printf("%s\n", value);
|
// printf("%s\n", value);
|
||||||
ASSERT_STREQ(value->value, " \"one two \"three ");
|
ASSERT_STREQ(value, " \"one two \"three ");
|
||||||
|
|
||||||
value =
|
value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST2", 6);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST2", 6);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
ASSERT_TRUE(value->value);
|
|
||||||
// printf("%s\n", value);
|
// printf("%s\n", value);
|
||||||
ASSERT_STREQ(value->value, "'\"onetwo\"three''");
|
ASSERT_STREQ(value, "'\"onetwo\"three''");
|
||||||
|
|
||||||
value =
|
value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST3", 6);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST3", 6);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
ASSERT_TRUE(value->value);
|
|
||||||
// printf("%s\n", value);
|
// printf("%s\n", value);
|
||||||
ASSERT_STREQ(value->value, " \"one two \"three ''");
|
ASSERT_STREQ(value, " \"one two \"three ''");
|
||||||
|
|
||||||
value =
|
value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST4", 6);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST4", 6);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
ASSERT_TRUE(value->value);
|
|
||||||
// printf("%s\n", value);
|
// printf("%s\n", value);
|
||||||
ASSERT_STREQ(value->value, " \"\"\"one two \"\"\"three ");
|
ASSERT_STREQ(value, " \"\"\"one two \"\"\"three ");
|
||||||
|
|
||||||
value =
|
value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST5", 6);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST5", 6);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
ASSERT_TRUE(value->value);
|
|
||||||
// printf("%s\n", value);
|
// printf("%s\n", value);
|
||||||
ASSERT_STREQ(value->value, " '''one two '''three ");
|
ASSERT_STREQ(value, " '''one two '''three ");
|
||||||
|
|
||||||
simple_archiver_list_free(&required_names);
|
simple_archiver_list_free(&required_names);
|
||||||
required_names = simple_archiver_list_init();
|
required_names = simple_archiver_list_init();
|
||||||
|
@ -286,18 +271,18 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
size_t output_buf_size;
|
size_t output_buf_size;
|
||||||
|
|
||||||
__attribute__((cleanup(simple_archiver_hash_map_free)))
|
__attribute__((cleanup(simple_archiver_list_free)))
|
||||||
SDArchiverHashMap *filenames_set = NULL;
|
SDArchiverLinkedList *filenames_list = NULL;
|
||||||
|
|
||||||
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
||||||
char *buf = c_simple_http_path_to_generated(
|
char *buf = c_simple_http_path_to_generated(
|
||||||
"/", &config, &output_buf_size, &filenames_set);
|
"/", &config, &output_buf_size, &filenames_list);
|
||||||
ASSERT_TRUE(buf != NULL);
|
ASSERT_TRUE(buf != NULL);
|
||||||
ASSERT_TRUE(strcmp(buf, "<h1>Test</h1>") == 0);
|
ASSERT_TRUE(strcmp(buf, "<h1>Test</h1>") == 0);
|
||||||
CHECK_TRUE(output_buf_size == 13);
|
CHECK_TRUE(output_buf_size == 13);
|
||||||
CHECK_TRUE(filenames_set->count == 0);
|
CHECK_TRUE(filenames_list->count == 0);
|
||||||
simple_archiver_helper_cleanup_c_string(&buf);
|
simple_archiver_helper_cleanup_c_string(&buf);
|
||||||
simple_archiver_hash_map_free(&filenames_set);
|
simple_archiver_list_free(&filenames_list);
|
||||||
|
|
||||||
__attribute__((cleanup(test_internal_cleanup_delete_temporary_file)))
|
__attribute__((cleanup(test_internal_cleanup_delete_temporary_file)))
|
||||||
const char *test_http_template_filename2 =
|
const char *test_http_template_filename2 =
|
||||||
|
@ -329,7 +314,7 @@ int main(int argc, char **argv) {
|
||||||
ASSERT_TRUE(config.paths != NULL);
|
ASSERT_TRUE(config.paths != NULL);
|
||||||
|
|
||||||
buf = c_simple_http_path_to_generated(
|
buf = c_simple_http_path_to_generated(
|
||||||
"/", &config, &output_buf_size, &filenames_set);
|
"/", &config, &output_buf_size, &filenames_list);
|
||||||
ASSERT_TRUE(buf != NULL);
|
ASSERT_TRUE(buf != NULL);
|
||||||
//printf("%s\n", buf);
|
//printf("%s\n", buf);
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(
|
||||||
|
@ -338,9 +323,9 @@ int main(int argc, char **argv) {
|
||||||
"<h1> Some text. </h1><br><h2> More text. </h2>")
|
"<h1> Some text. </h1><br><h2> More text. </h2>")
|
||||||
== 0);
|
== 0);
|
||||||
CHECK_TRUE(output_buf_size == 46);
|
CHECK_TRUE(output_buf_size == 46);
|
||||||
CHECK_TRUE(filenames_set->count == 0);
|
CHECK_TRUE(filenames_list->count == 0);
|
||||||
simple_archiver_helper_cleanup_c_string(&buf);
|
simple_archiver_helper_cleanup_c_string(&buf);
|
||||||
simple_archiver_hash_map_free(&filenames_set);
|
simple_archiver_list_free(&filenames_list);
|
||||||
|
|
||||||
__attribute__((cleanup(test_internal_cleanup_delete_temporary_file)))
|
__attribute__((cleanup(test_internal_cleanup_delete_temporary_file)))
|
||||||
const char *test_http_template_filename3 =
|
const char *test_http_template_filename3 =
|
||||||
|
@ -395,7 +380,7 @@ int main(int argc, char **argv) {
|
||||||
ASSERT_TRUE(config.paths != NULL);
|
ASSERT_TRUE(config.paths != NULL);
|
||||||
|
|
||||||
buf = c_simple_http_path_to_generated(
|
buf = c_simple_http_path_to_generated(
|
||||||
"/", &config, &output_buf_size, &filenames_set);
|
"/", &config, &output_buf_size, &filenames_list);
|
||||||
ASSERT_TRUE(buf != NULL);
|
ASSERT_TRUE(buf != NULL);
|
||||||
//printf("%s\n", buf);
|
//printf("%s\n", buf);
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(
|
||||||
|
@ -404,14 +389,14 @@ int main(int argc, char **argv) {
|
||||||
"<h1> testVar text. </h1><br><h2> testVar2 text. </h2>")
|
"<h1> testVar text. </h1><br><h2> testVar2 text. </h2>")
|
||||||
== 0);
|
== 0);
|
||||||
CHECK_TRUE(output_buf_size == 53);
|
CHECK_TRUE(output_buf_size == 53);
|
||||||
CHECK_TRUE(filenames_set->count == 1);
|
CHECK_TRUE(filenames_list->count == 1);
|
||||||
CHECK_TRUE(simple_archiver_hash_map_iter(
|
CHECK_TRUE(simple_archiver_list_get(
|
||||||
filenames_set,
|
filenames_list,
|
||||||
test_internal_check_matching_string_in_list,
|
test_internal_check_matching_string_in_list,
|
||||||
(void*)test_http_template_html_filename)
|
(void*)test_http_template_html_filename)
|
||||||
!= 0);
|
!= NULL);
|
||||||
simple_archiver_helper_cleanup_c_string(&buf);
|
simple_archiver_helper_cleanup_c_string(&buf);
|
||||||
simple_archiver_hash_map_free(&filenames_set);
|
simple_archiver_list_free(&filenames_list);
|
||||||
|
|
||||||
__attribute__((cleanup(test_internal_cleanup_delete_temporary_file)))
|
__attribute__((cleanup(test_internal_cleanup_delete_temporary_file)))
|
||||||
const char *test_http_template_filename4 =
|
const char *test_http_template_filename4 =
|
||||||
|
@ -486,7 +471,7 @@ int main(int argc, char **argv) {
|
||||||
ASSERT_TRUE(config.paths != NULL);
|
ASSERT_TRUE(config.paths != NULL);
|
||||||
|
|
||||||
buf = c_simple_http_path_to_generated(
|
buf = c_simple_http_path_to_generated(
|
||||||
"/", &config, &output_buf_size, &filenames_set);
|
"/", &config, &output_buf_size, &filenames_list);
|
||||||
ASSERT_TRUE(buf != NULL);
|
ASSERT_TRUE(buf != NULL);
|
||||||
//printf("%s\n", buf);
|
//printf("%s\n", buf);
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(
|
||||||
|
@ -495,17 +480,17 @@ int main(int argc, char **argv) {
|
||||||
"<h1> some test text in test var file. </h1>")
|
"<h1> some test text in test var file. </h1>")
|
||||||
== 0);
|
== 0);
|
||||||
CHECK_TRUE(output_buf_size == 43);
|
CHECK_TRUE(output_buf_size == 43);
|
||||||
CHECK_TRUE(filenames_set->count == 2);
|
CHECK_TRUE(filenames_list->count == 2);
|
||||||
CHECK_TRUE(simple_archiver_hash_map_iter(
|
CHECK_TRUE(simple_archiver_list_get(
|
||||||
filenames_set,
|
filenames_list,
|
||||||
test_internal_check_matching_string_in_list,
|
test_internal_check_matching_string_in_list,
|
||||||
(void*)test_http_template_html_filename2)
|
(void*)test_http_template_html_filename2)
|
||||||
!= 0);
|
!= NULL);
|
||||||
CHECK_TRUE(simple_archiver_hash_map_iter(
|
CHECK_TRUE(simple_archiver_list_get(
|
||||||
filenames_set,
|
filenames_list,
|
||||||
test_internal_check_matching_string_in_list,
|
test_internal_check_matching_string_in_list,
|
||||||
(void*)test_http_template_html_var_filename)
|
(void*)test_http_template_html_var_filename)
|
||||||
!= 0);
|
!= NULL);
|
||||||
simple_archiver_helper_cleanup_c_string(&buf);
|
simple_archiver_helper_cleanup_c_string(&buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -628,46 +613,6 @@ int main(int argc, char **argv) {
|
||||||
CHECK_TRUE(ret == 0);
|
CHECK_TRUE(ret == 0);
|
||||||
CHECK_TRUE(ret2 == 0);
|
CHECK_TRUE(ret2 == 0);
|
||||||
CHECK_TRUE(ret3 == 0);
|
CHECK_TRUE(ret3 == 0);
|
||||||
|
|
||||||
buf = strdup("EndingWithThreeTabs\t\t\t");
|
|
||||||
CHECK_TRUE(c_simple_http_trim_end_whitespace(buf) == 3);
|
|
||||||
CHECK_TRUE(buf[18] == 's');
|
|
||||||
CHECK_TRUE(buf[19] == 0);
|
|
||||||
CHECK_TRUE(buf[20] == 0);
|
|
||||||
CHECK_TRUE(buf[21] == 0);
|
|
||||||
CHECK_TRUE(buf[22] == 0);
|
|
||||||
free(buf);
|
|
||||||
buf = NULL;
|
|
||||||
|
|
||||||
buf = strdup("EndingWithThreeSpaces ");
|
|
||||||
CHECK_TRUE(c_simple_http_trim_end_whitespace(buf) == 3);
|
|
||||||
CHECK_TRUE(buf[20] == 's');
|
|
||||||
CHECK_TRUE(buf[21] == 0);
|
|
||||||
CHECK_TRUE(buf[22] == 0);
|
|
||||||
CHECK_TRUE(buf[23] == 0);
|
|
||||||
CHECK_TRUE(buf[24] == 0);
|
|
||||||
free(buf);
|
|
||||||
buf = NULL;
|
|
||||||
|
|
||||||
buf = strdup("EndingWithThreeNewlines\n\n\n");
|
|
||||||
CHECK_TRUE(c_simple_http_trim_end_whitespace(buf) == 3);
|
|
||||||
CHECK_TRUE(buf[22] == 's');
|
|
||||||
CHECK_TRUE(buf[23] == 0);
|
|
||||||
CHECK_TRUE(buf[24] == 0);
|
|
||||||
CHECK_TRUE(buf[25] == 0);
|
|
||||||
CHECK_TRUE(buf[26] == 0);
|
|
||||||
free(buf);
|
|
||||||
buf = NULL;
|
|
||||||
|
|
||||||
buf = strdup("EndingWithThreeCarraigeReturns\r\r\r");
|
|
||||||
CHECK_TRUE(c_simple_http_trim_end_whitespace(buf) == 3);
|
|
||||||
CHECK_TRUE(buf[29] == 's');
|
|
||||||
CHECK_TRUE(buf[30] == 0);
|
|
||||||
CHECK_TRUE(buf[31] == 0);
|
|
||||||
CHECK_TRUE(buf[32] == 0);
|
|
||||||
CHECK_TRUE(buf[33] == 0);
|
|
||||||
free(buf);
|
|
||||||
buf = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test html_cache.
|
// Test html_cache.
|
||||||
|
|
2
third_party/SimpleArchiver
vendored
2
third_party/SimpleArchiver
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 78a36b48dbd3888f56e26ac71115e5f775a74c2c
|
Subproject commit b256350fbcf170ef3d70e9cf7c6dfa0618e47ef4
|
Loading…
Reference in a new issue