Fix issues in demo templates
This commit is contained in:
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
*.o
|
*.o
|
||||||
*.out
|
*.out
|
||||||
*.exe
|
*.exe
|
||||||
+5559
-5559
File diff suppressed because it is too large
Load Diff
+526
-526
File diff suppressed because it is too large
Load Diff
+909
-909
File diff suppressed because it is too large
Load Diff
+27
-27
@@ -1,27 +1,27 @@
|
|||||||
/*
|
/*
|
||||||
* Written by Solar Designer <solar at openwall.com> in 2000-2011.
|
* Written by Solar Designer <solar at openwall.com> in 2000-2011.
|
||||||
* No copyright is claimed, and the software is hereby placed in the public
|
* No copyright is claimed, and the software is hereby placed in the public
|
||||||
* domain. In case this attempt to disclaim copyright and place the software
|
* domain. In case this attempt to disclaim copyright and place the software
|
||||||
* in the public domain is deemed null and void, then the software is
|
* in the public domain is deemed null and void, then the software is
|
||||||
* Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
|
* Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
|
||||||
* general public under the following terms:
|
* general public under the following terms:
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted.
|
* modification, are permitted.
|
||||||
*
|
*
|
||||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||||
*
|
*
|
||||||
* See crypt_blowfish.c for more information.
|
* See crypt_blowfish.c for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _CRYPT_BLOWFISH_H
|
#ifndef _CRYPT_BLOWFISH_H
|
||||||
#define _CRYPT_BLOWFISH_H
|
#define _CRYPT_BLOWFISH_H
|
||||||
|
|
||||||
extern int _crypt_output_magic(const char *setting, char *output, int size);
|
extern int _crypt_output_magic(const char *setting, char *output, int size);
|
||||||
extern char *_crypt_blowfish_rn(const char *key, const char *setting,
|
extern char *_crypt_blowfish_rn(const char *key, const char *setting,
|
||||||
char *output, int size);
|
char *output, int size);
|
||||||
extern char *_crypt_gensalt_blowfish_rn(const char *prefix,
|
extern char *_crypt_gensalt_blowfish_rn(const char *prefix,
|
||||||
unsigned long count,
|
unsigned long count,
|
||||||
const char *input, int size, char *output, int output_size);
|
const char *input, int size, char *output, int output_size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,90 +1,90 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
typedef struct WL_Runtime WL_Runtime;
|
typedef struct WL_Runtime WL_Runtime;
|
||||||
typedef struct WL_Compiler WL_Compiler;
|
typedef struct WL_Compiler WL_Compiler;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int len;
|
int len;
|
||||||
} WL_String;
|
} WL_String;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int len;
|
int len;
|
||||||
int cur;
|
int cur;
|
||||||
} WL_Arena;
|
} WL_Arena;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int len;
|
int len;
|
||||||
} WL_Program;
|
} WL_Program;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WL_ADD_ERROR,
|
WL_ADD_ERROR,
|
||||||
WL_ADD_AGAIN,
|
WL_ADD_AGAIN,
|
||||||
WL_ADD_LINK,
|
WL_ADD_LINK,
|
||||||
} WL_AddResultType;
|
} WL_AddResultType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
WL_AddResultType type;
|
WL_AddResultType type;
|
||||||
WL_String path;
|
WL_String path;
|
||||||
} WL_AddResult;
|
} WL_AddResult;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WL_EVAL_NONE,
|
WL_EVAL_NONE,
|
||||||
WL_EVAL_DONE,
|
WL_EVAL_DONE,
|
||||||
WL_EVAL_ERROR,
|
WL_EVAL_ERROR,
|
||||||
WL_EVAL_OUTPUT,
|
WL_EVAL_OUTPUT,
|
||||||
WL_EVAL_SYSVAR,
|
WL_EVAL_SYSVAR,
|
||||||
WL_EVAL_SYSCALL,
|
WL_EVAL_SYSCALL,
|
||||||
} WL_EvalResultType;
|
} WL_EvalResultType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
WL_EvalResultType type;
|
WL_EvalResultType type;
|
||||||
WL_String str;
|
WL_String str;
|
||||||
} WL_EvalResult;
|
} WL_EvalResult;
|
||||||
|
|
||||||
WL_Compiler* wl_compiler_init (WL_Arena *arena);
|
WL_Compiler* wl_compiler_init (WL_Arena *arena);
|
||||||
WL_AddResult wl_compiler_add (WL_Compiler *compiler, WL_String path, WL_String content);
|
WL_AddResult wl_compiler_add (WL_Compiler *compiler, WL_String path, WL_String content);
|
||||||
int wl_compiler_link (WL_Compiler *compiler, WL_Program *program);
|
int wl_compiler_link (WL_Compiler *compiler, WL_Program *program);
|
||||||
WL_String wl_compiler_error (WL_Compiler *compiler);
|
WL_String wl_compiler_error (WL_Compiler *compiler);
|
||||||
int wl_dump_ast (WL_Compiler *compiler, char *dst, int cap);
|
int wl_dump_ast (WL_Compiler *compiler, char *dst, int cap);
|
||||||
void wl_dump_program (WL_Program program);
|
void wl_dump_program (WL_Program program);
|
||||||
|
|
||||||
WL_Runtime* wl_runtime_init (WL_Arena *arena, WL_Program program);
|
WL_Runtime* wl_runtime_init (WL_Arena *arena, WL_Program program);
|
||||||
WL_EvalResult wl_runtime_eval (WL_Runtime *rt);
|
WL_EvalResult wl_runtime_eval (WL_Runtime *rt);
|
||||||
WL_String wl_runtime_error (WL_Runtime *rt);
|
WL_String wl_runtime_error (WL_Runtime *rt);
|
||||||
void wl_runtime_dump (WL_Runtime *rt);
|
void wl_runtime_dump (WL_Runtime *rt);
|
||||||
|
|
||||||
bool wl_streq (WL_String a, char *b, int blen);
|
bool wl_streq (WL_String a, char *b, int blen);
|
||||||
int wl_arg_count (WL_Runtime *rt);
|
int wl_arg_count (WL_Runtime *rt);
|
||||||
bool wl_arg_none (WL_Runtime *rt, int idx);
|
bool wl_arg_none (WL_Runtime *rt, int idx);
|
||||||
bool wl_arg_bool (WL_Runtime *rt, int idx, bool *x);
|
bool wl_arg_bool (WL_Runtime *rt, int idx, bool *x);
|
||||||
bool wl_arg_s64 (WL_Runtime *rt, int idx, int64_t *x);
|
bool wl_arg_s64 (WL_Runtime *rt, int idx, int64_t *x);
|
||||||
bool wl_arg_f64 (WL_Runtime *rt, int idx, double *x);
|
bool wl_arg_f64 (WL_Runtime *rt, int idx, double *x);
|
||||||
bool wl_arg_str (WL_Runtime *rt, int idx, WL_String *x);
|
bool wl_arg_str (WL_Runtime *rt, int idx, WL_String *x);
|
||||||
bool wl_arg_array (WL_Runtime *rt, int idx);
|
bool wl_arg_array (WL_Runtime *rt, int idx);
|
||||||
bool wl_arg_map (WL_Runtime *rt, int idx);
|
bool wl_arg_map (WL_Runtime *rt, int idx);
|
||||||
bool wl_peek_none (WL_Runtime *rt, int off);
|
bool wl_peek_none (WL_Runtime *rt, int off);
|
||||||
bool wl_peek_bool (WL_Runtime *rt, int off, bool *x);
|
bool wl_peek_bool (WL_Runtime *rt, int off, bool *x);
|
||||||
bool wl_peek_s64 (WL_Runtime *rt, int off, int64_t *x);
|
bool wl_peek_s64 (WL_Runtime *rt, int off, int64_t *x);
|
||||||
bool wl_peek_f64 (WL_Runtime *rt, int off, double *x);
|
bool wl_peek_f64 (WL_Runtime *rt, int off, double *x);
|
||||||
bool wl_peek_str (WL_Runtime *rt, int off, WL_String *x);
|
bool wl_peek_str (WL_Runtime *rt, int off, WL_String *x);
|
||||||
bool wl_pop_any (WL_Runtime *rt);
|
bool wl_pop_any (WL_Runtime *rt);
|
||||||
bool wl_pop_none (WL_Runtime *rt);
|
bool wl_pop_none (WL_Runtime *rt);
|
||||||
bool wl_pop_bool (WL_Runtime *rt, bool *x);
|
bool wl_pop_bool (WL_Runtime *rt, bool *x);
|
||||||
bool wl_pop_s64 (WL_Runtime *rt, int64_t *x);
|
bool wl_pop_s64 (WL_Runtime *rt, int64_t *x);
|
||||||
bool wl_pop_f64 (WL_Runtime *rt, double *x);
|
bool wl_pop_f64 (WL_Runtime *rt, double *x);
|
||||||
bool wl_pop_str (WL_Runtime *rt, WL_String *x);
|
bool wl_pop_str (WL_Runtime *rt, WL_String *x);
|
||||||
void wl_push_none (WL_Runtime *rt);
|
void wl_push_none (WL_Runtime *rt);
|
||||||
void wl_push_true (WL_Runtime *rt);
|
void wl_push_true (WL_Runtime *rt);
|
||||||
void wl_push_false (WL_Runtime *rt);
|
void wl_push_false (WL_Runtime *rt);
|
||||||
void wl_push_s64 (WL_Runtime *rt, int64_t x);
|
void wl_push_s64 (WL_Runtime *rt, int64_t x);
|
||||||
void wl_push_f64 (WL_Runtime *rt, double x);
|
void wl_push_f64 (WL_Runtime *rt, double x);
|
||||||
void wl_push_str (WL_Runtime *rt, WL_String x);
|
void wl_push_str (WL_Runtime *rt, WL_String x);
|
||||||
void wl_push_array (WL_Runtime *rt, int cap);
|
void wl_push_array (WL_Runtime *rt, int cap);
|
||||||
void wl_push_map (WL_Runtime *rt, int cap);
|
void wl_push_map (WL_Runtime *rt, int cap);
|
||||||
void wl_push_arg (WL_Runtime *rt, int idx);
|
void wl_push_arg (WL_Runtime *rt, int idx);
|
||||||
void wl_insert (WL_Runtime *rt);
|
void wl_insert (WL_Runtime *rt);
|
||||||
void wl_append (WL_Runtime *rt);
|
void wl_append (WL_Runtime *rt);
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
Copyright © 2025 Francesco Cozzuto
|
Copyright © 2025 Francesco Cozzuto
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
@@ -1,25 +1,25 @@
|
|||||||
FLAGS = -Wall -Wextra -O0 -g3 -I.
|
FLAGS = -Wall -Wextra -O0 -g3 -I.
|
||||||
|
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
EXT = .exe
|
EXT = .exe
|
||||||
FLAGS += -lws2_32 -lbcrypt
|
FLAGS += -lws2_32 -lbcrypt
|
||||||
else
|
else
|
||||||
EXT = .out
|
EXT = .out
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: cweb.h cozisnews$(EXT)
|
all: cweb.h cozisnews$(EXT)
|
||||||
|
|
||||||
cweb.h: src/main.c src/main.h
|
cweb.h: src/main.c src/main.h
|
||||||
python amalg.py
|
python amalg.py
|
||||||
|
|
||||||
cweb.o: cweb.c
|
cweb.o: cweb.c
|
||||||
gcc $< -o $@ -I3p
|
gcc $< -o $@ -I3p
|
||||||
|
|
||||||
sqlite3.o: 3p/sqlite3.c
|
sqlite3.o: 3p/sqlite3.c
|
||||||
gcc -c -o $@ $<
|
gcc -c -o $@ $<
|
||||||
|
|
||||||
cozisnews$(EXT): demo/main.c sqlite3.o
|
cozisnews$(EXT): demo/main.c sqlite3.o
|
||||||
gcc -o $@ demo/main.c sqlite3.o $(FLAGS) -I3p
|
gcc -o $@ demo/main.c sqlite3.o $(FLAGS) -I3p
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm *.o *.out *.exe
|
rm *.o *.out *.exe
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# cWEB
|
# cWEB
|
||||||
|
|
||||||
cWEB is a framework for web development designed for small scale production environments and tooling. It's distributed as a single header file and has minimal dependencies.
|
cWEB is a framework for web development designed for small scale production environments and tooling. It's distributed as a single header file and has minimal dependencies.
|
||||||
|
|
||||||
cWEB is single header file web framework for C designed for small scale production environments and tooling :D
|
cWEB is single header file web framework for C designed for small scale production environments and tooling :D
|
||||||
|
|
||||||
(In progress)
|
(In progress)
|
||||||
@@ -1,112 +1,112 @@
|
|||||||
class Amalgamator:
|
class Amalgamator:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.out = ""
|
self.out = ""
|
||||||
|
|
||||||
def append_text(self, text):
|
def append_text(self, text):
|
||||||
self.out += text
|
self.out += text
|
||||||
|
|
||||||
def append_file(self, file):
|
def append_file(self, file):
|
||||||
|
|
||||||
self.out += "\n"
|
self.out += "\n"
|
||||||
self.out += "////////////////////////////////////////////////////////////////////////////////////////\n"
|
self.out += "////////////////////////////////////////////////////////////////////////////////////////\n"
|
||||||
self.out += "// " + file + "\n"
|
self.out += "// " + file + "\n"
|
||||||
self.out += "////////////////////////////////////////////////////////////////////////////////////////\n"
|
self.out += "////////////////////////////////////////////////////////////////////////////////////////\n"
|
||||||
self.out += "\n"
|
self.out += "\n"
|
||||||
self.out += "#line 1 \"" + file + "\"\n"
|
self.out += "#line 1 \"" + file + "\"\n"
|
||||||
self.out += open(file).read()
|
self.out += open(file).read()
|
||||||
|
|
||||||
if len(self.out) > 0 and self.out[len(self.out)-1] != '\n':
|
if len(self.out) > 0 and self.out[len(self.out)-1] != '\n':
|
||||||
self.out += "\n"
|
self.out += "\n"
|
||||||
|
|
||||||
def save(self, file):
|
def save(self, file):
|
||||||
open(file, 'w').write(self.out)
|
open(file, 'w').write(self.out)
|
||||||
|
|
||||||
desc = """
|
desc = """
|
||||||
// This file was generated automatically. Do not modify directly!
|
// This file was generated automatically. Do not modify directly!
|
||||||
"""
|
"""
|
||||||
|
|
||||||
header = Amalgamator()
|
header = Amalgamator()
|
||||||
|
|
||||||
header.append_text("""/*
|
header.append_text("""/*
|
||||||
Copyright © 2025 Francesco Cozzuto
|
Copyright © 2025 Francesco Cozzuto
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the “Software”),
|
copy of this software and associated documentation files (the “Software”),
|
||||||
to deal in the Software without restriction, including without limitation
|
to deal in the Software without restriction, including without limitation
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
Software is furnished to do so, subject to the following conditions:
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
OTHER DEALINGS IN THE SOFTWARE.
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
""")
|
""")
|
||||||
|
|
||||||
header.append_text("#ifndef CWEB_INCLUDED\n")
|
header.append_text("#ifndef CWEB_INCLUDED\n")
|
||||||
header.append_text("#define CWEB_INCLUDED\n")
|
header.append_text("#define CWEB_INCLUDED\n")
|
||||||
header.append_file("src/main.h")
|
header.append_file("src/main.h")
|
||||||
header.append_text("#endif // CWEB_INCLUDED\n")
|
header.append_text("#endif // CWEB_INCLUDED\n")
|
||||||
|
|
||||||
header.append_text("#ifdef CWEB_IMPLEMENTATION\n")
|
header.append_text("#ifdef CWEB_IMPLEMENTATION\n")
|
||||||
|
|
||||||
header.append_text("#define CWEB_AMALGAMATION\n")
|
header.append_text("#define CWEB_AMALGAMATION\n")
|
||||||
header.append_text("#define WL_NOINCLUDE\n")
|
header.append_text("#define WL_NOINCLUDE\n")
|
||||||
header.append_text("#define HTTP_NOINCLUDE\n")
|
header.append_text("#define HTTP_NOINCLUDE\n")
|
||||||
header.append_text("#define CRYPT_BLOWFISH_NOINCLUDE\n")
|
header.append_text("#define CRYPT_BLOWFISH_NOINCLUDE\n")
|
||||||
|
|
||||||
header.append_text("#undef MIN\n")
|
header.append_text("#undef MIN\n")
|
||||||
header.append_text("#undef MAX\n")
|
header.append_text("#undef MAX\n")
|
||||||
header.append_text("#undef ASSERT\n")
|
header.append_text("#undef ASSERT\n")
|
||||||
header.append_text("#undef SIZEOF\n")
|
header.append_text("#undef SIZEOF\n")
|
||||||
header.append_text("#undef TRACE\n")
|
header.append_text("#undef TRACE\n")
|
||||||
|
|
||||||
header.append_file("3p/chttp.h")
|
header.append_file("3p/chttp.h")
|
||||||
header.append_file("3p/chttp.c")
|
header.append_file("3p/chttp.c")
|
||||||
|
|
||||||
header.append_text("#undef MIN\n")
|
header.append_text("#undef MIN\n")
|
||||||
header.append_text("#undef MAX\n")
|
header.append_text("#undef MAX\n")
|
||||||
header.append_text("#undef ASSERT\n")
|
header.append_text("#undef ASSERT\n")
|
||||||
header.append_text("#undef SIZEOF\n")
|
header.append_text("#undef SIZEOF\n")
|
||||||
header.append_text("#undef TRACE\n")
|
header.append_text("#undef TRACE\n")
|
||||||
|
|
||||||
header.append_text("#define Scanner WL_Scanner\n")
|
header.append_text("#define Scanner WL_Scanner\n")
|
||||||
header.append_text("#define Token WL_Token\n")
|
header.append_text("#define Token WL_Token\n")
|
||||||
header.append_text("#define is_space is_space__wl\n")
|
header.append_text("#define is_space is_space__wl\n")
|
||||||
header.append_text("#define is_digit is_digit__wl\n")
|
header.append_text("#define is_digit is_digit__wl\n")
|
||||||
header.append_text("#define is_alpha is_alpha__wl\n")
|
header.append_text("#define is_alpha is_alpha__wl\n")
|
||||||
header.append_text("#define is_printable is_printable__wl\n")
|
header.append_text("#define is_printable is_printable__wl\n")
|
||||||
header.append_text("#define is_hex_digit is_hex_digit__wl\n")
|
header.append_text("#define is_hex_digit is_hex_digit__wl\n")
|
||||||
header.append_text("#define hex_digit_to_int hex_digit_to_int__wl\n")
|
header.append_text("#define hex_digit_to_int hex_digit_to_int__wl\n")
|
||||||
header.append_text("#define consume_str consume_str__wl\n")
|
header.append_text("#define consume_str consume_str__wl\n")
|
||||||
|
|
||||||
header.append_file("3p/wl.h")
|
header.append_file("3p/wl.h")
|
||||||
header.append_file("3p/wl.c")
|
header.append_file("3p/wl.c")
|
||||||
|
|
||||||
header.append_text("#undef Scanner\n")
|
header.append_text("#undef Scanner\n")
|
||||||
header.append_text("#undef Token\n")
|
header.append_text("#undef Token\n")
|
||||||
header.append_text("#undef is_space\n")
|
header.append_text("#undef is_space\n")
|
||||||
header.append_text("#undef is_digit\n")
|
header.append_text("#undef is_digit\n")
|
||||||
header.append_text("#undef is_alpha\n")
|
header.append_text("#undef is_alpha\n")
|
||||||
header.append_text("#undef is_printable\n")
|
header.append_text("#undef is_printable\n")
|
||||||
header.append_text("#undef is_hex_digit\n")
|
header.append_text("#undef is_hex_digit\n")
|
||||||
header.append_text("#undef hex_digit_to_int\n")
|
header.append_text("#undef hex_digit_to_int\n")
|
||||||
|
|
||||||
header.append_text("#undef MIN\n")
|
header.append_text("#undef MIN\n")
|
||||||
header.append_text("#undef MAX\n")
|
header.append_text("#undef MAX\n")
|
||||||
header.append_text("#undef ASSERT\n")
|
header.append_text("#undef ASSERT\n")
|
||||||
header.append_text("#undef SIZEOF\n")
|
header.append_text("#undef SIZEOF\n")
|
||||||
|
|
||||||
header.append_file("3p/crypt_blowfish.h")
|
header.append_file("3p/crypt_blowfish.h")
|
||||||
header.append_file("3p/crypt_blowfish.c")
|
header.append_file("3p/crypt_blowfish.c")
|
||||||
header.append_file("src/main.c")
|
header.append_file("src/main.c")
|
||||||
|
|
||||||
header.append_text("#endif // CWEB_IMPLEMENTATION\n")
|
header.append_text("#endif // CWEB_IMPLEMENTATION\n")
|
||||||
header.save("cweb.h")
|
header.save("cweb.h")
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
Copyright � 2025 Francesco Cozzuto
|
Copyright © 2025 Francesco Cozzuto
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the �Software�),
|
copy of this software and associated documentation files (the “Software”),
|
||||||
to deal in the Software without restriction, including without limitation
|
to deal in the Software without restriction, including without limitation
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
@@ -11,7 +11,7 @@ Software is furnished to do so, subject to the following conditions:
|
|||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED �AS IS�, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
@@ -26,7 +26,7 @@ OTHER DEALINGS IN THE SOFTWARE.
|
|||||||
// src/main.h
|
// src/main.h
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/main.h"
|
#line 1 "src/main.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
@@ -358,7 +358,7 @@ int cweb_check_password(CWEB_String pass, CWEB_PasswordHash hash);
|
|||||||
// 3p/chttp.h
|
// 3p/chttp.h
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "3p/chttp.h"
|
#line 1 "3p/chttp.h"
|
||||||
#ifndef HTTP_AMALGAMATION
|
#ifndef HTTP_AMALGAMATION
|
||||||
#define HTTP_AMALGAMATION
|
#define HTTP_AMALGAMATION
|
||||||
|
|
||||||
@@ -368,7 +368,7 @@ int cweb_check_password(CWEB_String pass, CWEB_PasswordHash hash);
|
|||||||
// src/basic.h
|
// src/basic.h
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/basic.h"
|
#line 1 "src/basic.h"
|
||||||
#ifndef CHTTP_BASIC_INCLUDED
|
#ifndef CHTTP_BASIC_INCLUDED
|
||||||
#define CHTTP_BASIC_INCLUDED
|
#define CHTTP_BASIC_INCLUDED
|
||||||
|
|
||||||
@@ -455,7 +455,7 @@ void print_bytes(HTTP_String prefix, HTTP_String src);
|
|||||||
// src/parse.h
|
// src/parse.h
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/parse.h"
|
#line 1 "src/parse.h"
|
||||||
#ifndef PARSE_INCLUDED
|
#ifndef PARSE_INCLUDED
|
||||||
#define PARSE_INCLUDED
|
#define PARSE_INCLUDED
|
||||||
|
|
||||||
@@ -561,7 +561,7 @@ int http_get_param_i (HTTP_String body, HTTP_String str);
|
|||||||
// src/engine.h
|
// src/engine.h
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/engine.h"
|
#line 1 "src/engine.h"
|
||||||
#ifndef HTTP_ENGINE_INCLUDED
|
#ifndef HTTP_ENGINE_INCLUDED
|
||||||
#define HTTP_ENGINE_INCLUDED
|
#define HTTP_ENGINE_INCLUDED
|
||||||
|
|
||||||
@@ -689,7 +689,7 @@ void http_engine_undo (HTTP_Engine *eng);
|
|||||||
// src/cert.h
|
// src/cert.h
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/cert.h"
|
#line 1 "src/cert.h"
|
||||||
#ifndef CERT_INCLUDED
|
#ifndef CERT_INCLUDED
|
||||||
#define CERT_INCLUDED
|
#define CERT_INCLUDED
|
||||||
|
|
||||||
@@ -720,7 +720,7 @@ int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
|||||||
// src/client.h
|
// src/client.h
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/client.h"
|
#line 1 "src/client.h"
|
||||||
#ifndef CLIENT_INCLUDED
|
#ifndef CLIENT_INCLUDED
|
||||||
#define CLIENT_INCLUDED
|
#define CLIENT_INCLUDED
|
||||||
|
|
||||||
@@ -824,7 +824,7 @@ HTTP_Response *http_post(HTTP_String url,
|
|||||||
// src/server.h
|
// src/server.h
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/server.h"
|
#line 1 "src/server.h"
|
||||||
#ifndef HTTP_SERVER_INCLUDED
|
#ifndef HTTP_SERVER_INCLUDED
|
||||||
#define HTTP_SERVER_INCLUDED
|
#define HTTP_SERVER_INCLUDED
|
||||||
|
|
||||||
@@ -865,7 +865,7 @@ void http_response_builder_done (HTTP_ResponseBuilder res);
|
|||||||
// src/router.h
|
// src/router.h
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/router.h"
|
#line 1 "src/router.h"
|
||||||
#ifndef HTTP_ROUTER_INCLUDED
|
#ifndef HTTP_ROUTER_INCLUDED
|
||||||
#define HTTP_ROUTER_INCLUDED
|
#define HTTP_ROUTER_INCLUDED
|
||||||
|
|
||||||
@@ -890,7 +890,7 @@ int http_serve (char *addr, int port, HTTP_Router *router);
|
|||||||
// 3p/chttp.c
|
// 3p/chttp.c
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "3p/chttp.c"
|
#line 1 "3p/chttp.c"
|
||||||
#ifndef HTTP_NOINCLUDE
|
#ifndef HTTP_NOINCLUDE
|
||||||
#include "chttp.h"
|
#include "chttp.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -899,7 +899,7 @@ int http_serve (char *addr, int port, HTTP_Router *router);
|
|||||||
// src/sec.h
|
// src/sec.h
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/sec.h"
|
#line 1 "src/sec.h"
|
||||||
#ifndef SEC_INCLUDED
|
#ifndef SEC_INCLUDED
|
||||||
#define SEC_INCLUDED
|
#define SEC_INCLUDED
|
||||||
|
|
||||||
@@ -960,7 +960,7 @@ void secure_context_free(SecureContext *sec);
|
|||||||
// src/socket_raw.h
|
// src/socket_raw.h
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/socket_raw.h"
|
#line 1 "src/socket_raw.h"
|
||||||
#ifndef SOCKET_RAW_INCLUDED
|
#ifndef SOCKET_RAW_INCLUDED
|
||||||
#define SOCKET_RAW_INCLUDED
|
#define SOCKET_RAW_INCLUDED
|
||||||
|
|
||||||
@@ -1001,7 +1001,7 @@ RAW_SOCKET listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int b
|
|||||||
// src/socket.h
|
// src/socket.h
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/socket.h"
|
#line 1 "src/socket.h"
|
||||||
#ifndef SOCKET_INCLUDED
|
#ifndef SOCKET_INCLUDED
|
||||||
#define SOCKET_INCLUDED
|
#define SOCKET_INCLUDED
|
||||||
|
|
||||||
@@ -1082,7 +1082,7 @@ void* socket_get_user_data(Socket *sock);
|
|||||||
// src/socket_pool.h
|
// src/socket_pool.h
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/socket_pool.h"
|
#line 1 "src/socket_pool.h"
|
||||||
#ifndef SOCKET_POOL_INCLUDED
|
#ifndef SOCKET_POOL_INCLUDED
|
||||||
#define SOCKET_POOL_INCLUDED
|
#define SOCKET_POOL_INCLUDED
|
||||||
|
|
||||||
@@ -1148,7 +1148,7 @@ bool socket_pool_secure(SocketPool *pool, SocketHandle handle);
|
|||||||
// src/basic.c
|
// src/basic.c
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/basic.c"
|
#line 1 "src/basic.c"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -1257,7 +1257,7 @@ void print_bytes(HTTP_String prefix, HTTP_String src)
|
|||||||
// src/parse.c
|
// src/parse.c
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/parse.c"
|
#line 1 "src/parse.c"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -2564,7 +2564,7 @@ int http_get_param_i(HTTP_String body, HTTP_String str)
|
|||||||
// src/engine.c
|
// src/engine.c
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/engine.c"
|
#line 1 "src/engine.c"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -3558,7 +3558,7 @@ void http_engine_undo(HTTP_Engine *eng)
|
|||||||
// src/cert.c
|
// src/cert.c
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/cert.c"
|
#line 1 "src/cert.c"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -3733,7 +3733,7 @@ int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
|||||||
// src/sec.c
|
// src/sec.c
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/sec.c"
|
#line 1 "src/sec.c"
|
||||||
#ifndef HTTP_AMALGAMATION
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "sec.h"
|
#include "sec.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -3959,7 +3959,7 @@ int secure_context_add_cert(SecureContext *sec,
|
|||||||
// src/socket_raw.c
|
// src/socket_raw.c
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/socket_raw.c"
|
#line 1 "src/socket_raw.c"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -4071,7 +4071,7 @@ RAW_SOCKET listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int b
|
|||||||
// src/socket.c
|
// src/socket.c
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/socket.c"
|
#line 1 "src/socket.c"
|
||||||
#include <stdio.h> // snprintf
|
#include <stdio.h> // snprintf
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -4867,7 +4867,7 @@ void *socket_get_user_data(Socket *sock)
|
|||||||
// src/socket_pool.c
|
// src/socket_pool.c
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/socket_pool.c"
|
#line 1 "src/socket_pool.c"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@@ -5230,7 +5230,7 @@ bool socket_pool_secure(SocketPool *pool, SocketHandle handle)
|
|||||||
// src/client.c
|
// src/client.c
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/client.c"
|
#line 1 "src/client.c"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -5689,7 +5689,7 @@ HTTP_Response *http_post(HTTP_String url, HTTP_String *headers, int num_headers,
|
|||||||
// src/server.c
|
// src/server.c
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/server.c"
|
#line 1 "src/server.c"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -6002,7 +6002,7 @@ void http_response_builder_done(HTTP_ResponseBuilder res)
|
|||||||
// src/router.c
|
// src/router.c
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/router.c"
|
#line 1 "src/router.c"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
@@ -6469,7 +6469,7 @@ int http_serve(char *addr, int port, HTTP_Router *router)
|
|||||||
// 3p/wl.h
|
// 3p/wl.h
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "3p/wl.h"
|
#line 1 "3p/wl.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
@@ -6565,7 +6565,7 @@ void wl_append (WL_Runtime *rt);
|
|||||||
// 3p/wl.c
|
// 3p/wl.c
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "3p/wl.c"
|
#line 1 "3p/wl.c"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -12448,7 +12448,7 @@ void wl_runtime_dump(WL_Runtime *rt)
|
|||||||
// 3p/crypt_blowfish.h
|
// 3p/crypt_blowfish.h
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "3p/crypt_blowfish.h"
|
#line 1 "3p/crypt_blowfish.h"
|
||||||
/*
|
/*
|
||||||
* Written by Solar Designer <solar at openwall.com> in 2000-2011.
|
* Written by Solar Designer <solar at openwall.com> in 2000-2011.
|
||||||
* No copyright is claimed, and the software is hereby placed in the public
|
* No copyright is claimed, and the software is hereby placed in the public
|
||||||
@@ -12481,7 +12481,7 @@ extern char *_crypt_gensalt_blowfish_rn(const char *prefix,
|
|||||||
// 3p/crypt_blowfish.c
|
// 3p/crypt_blowfish.c
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "3p/crypt_blowfish.c"
|
#line 1 "3p/crypt_blowfish.c"
|
||||||
/*
|
/*
|
||||||
* The crypt_blowfish homepage is:
|
* The crypt_blowfish homepage is:
|
||||||
*
|
*
|
||||||
@@ -13396,7 +13396,7 @@ char *_crypt_gensalt_blowfish_rn(const char *prefix, unsigned long count,
|
|||||||
// src/main.c
|
// src/main.c
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//#line 1 "src/main.c"
|
#line 1 "src/main.c"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -14072,7 +14072,7 @@ static int sqlite3utils_prepare(SQLiteCache *cache, sqlite3_stmt **pstmt, char *
|
|||||||
if (cache->items[i].stmt == NULL) {
|
if (cache->items[i].stmt == NULL) {
|
||||||
|
|
||||||
sqlite3_stmt *stmt;
|
sqlite3_stmt *stmt;
|
||||||
int ret = sqlite3_prepare_v2(cache->db, fmt, -1, &stmt, NULL);
|
int ret = sqlite3_prepare_v2(cache->db, fmt, fmtlen, &stmt, NULL);
|
||||||
if (ret != SQLITE_OK) {
|
if (ret != SQLITE_OK) {
|
||||||
fprintf(stderr, "Failed to prepare statement: %s (%s:%d)\n", sqlite3_errmsg(cache->db), __FILE__, __LINE__); // TODO
|
fprintf(stderr, "Failed to prepare statement: %s (%s:%d)\n", sqlite3_errmsg(cache->db), __FILE__, __LINE__); // TODO
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
+374
-373
@@ -1,373 +1,374 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#define CWEB_IMPLEMENTATION
|
#define CWEB_IMPLEMENTATION
|
||||||
#include "../cweb.h"
|
#include "../cweb.h"
|
||||||
|
|
||||||
#define USERNAME_LIMIT 64
|
#define USERNAME_LIMIT 64
|
||||||
|
|
||||||
bool valid_name(CWEB_String str)
|
bool valid_name(CWEB_String str)
|
||||||
{
|
{
|
||||||
(void) str; // TODO
|
(void) str; // TODO
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool valid_email(CWEB_String str)
|
bool valid_email(CWEB_String str)
|
||||||
{
|
{
|
||||||
(void) str; // TODO
|
(void) str; // TODO
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool valid_pass(CWEB_String str)
|
bool valid_pass(CWEB_String str)
|
||||||
{
|
{
|
||||||
(void) str; // TODO
|
(void) str; // TODO
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool valid_post_title(CWEB_String str)
|
bool valid_post_title(CWEB_String str)
|
||||||
{
|
{
|
||||||
(void) str; // TODO
|
(void) str; // TODO
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool valid_post_content(CWEB_String str)
|
bool valid_post_content(CWEB_String str)
|
||||||
{
|
{
|
||||||
(void) str; // TODO
|
(void) str; // TODO
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool valid_link(CWEB_String str)
|
bool valid_link(CWEB_String str)
|
||||||
{
|
{
|
||||||
(void) str;
|
(void) str;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool valid_comment_content(CWEB_String str)
|
bool valid_comment_content(CWEB_String str)
|
||||||
{
|
{
|
||||||
(void) str;
|
(void) str;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check for the correct methods at each endpoint
|
// TODO: check for the correct methods at each endpoint
|
||||||
|
|
||||||
static int user_exists(CWEB *cweb, CWEB_String name, CWEB_String pass)
|
static int user_exists(CWEB *cweb, CWEB_String name, CWEB_String pass)
|
||||||
{
|
{
|
||||||
CWEB_QueryResult res = cweb_database_select(cweb, "SELECT id, hash FROM Users WHERE username=?", name);
|
CWEB_QueryResult res = cweb_database_select(cweb, "SELECT id, hash FROM Users WHERE username=?", name);
|
||||||
|
|
||||||
int64_t user_id;
|
int64_t user_id;
|
||||||
CWEB_PasswordHash hash;
|
CWEB_PasswordHash hash;
|
||||||
int ret = cweb_next_query_row(&res, &user_id, &hash);
|
int ret = cweb_next_query_row(&res, &user_id, &hash);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
cweb_free_query_result(&res);
|
cweb_free_query_result(&res);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
cweb_free_query_result(&res);
|
cweb_free_query_result(&res);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = cweb_check_password(pass, hash);
|
ret = cweb_check_password(pass, hash);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
cweb_free_query_result(&res);
|
cweb_free_query_result(&res);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
cweb_free_query_result(&res);
|
cweb_free_query_result(&res);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return user_id;
|
return user_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void endpoint_api_login(CWEB *cweb, CWEB_Request *req)
|
static void endpoint_api_login(CWEB *cweb, CWEB_Request *req)
|
||||||
{
|
{
|
||||||
if (cweb_get_user_id(req) != -1) {
|
if (cweb_get_user_id(req) != -1) {
|
||||||
cweb_respond_redirect(req, CWEB_STR("/index"));
|
cweb_respond_redirect(req, CWEB_STR("/index"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CWEB_String name = cweb_get_param_s(req, CWEB_STR("username"));
|
CWEB_String name = cweb_get_param_s(req, CWEB_STR("username"));
|
||||||
CWEB_String pass = cweb_get_param_s(req, CWEB_STR("password"));
|
CWEB_String pass = cweb_get_param_s(req, CWEB_STR("password"));
|
||||||
if (!valid_name(name) || !valid_pass(pass)) {
|
if (!valid_name(name) || !valid_pass(pass)) {
|
||||||
cweb_respond_basic(req, 400, CWEB_STR("Invalid credentials"));
|
cweb_respond_basic(req, 400, CWEB_STR("Invalid credentials"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = user_exists(cweb, name, pass);
|
int ret = user_exists(cweb, name, pass);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
cweb_respond_basic(req, 500, CWEB_STR("Internal error"));
|
cweb_respond_basic(req, 500, CWEB_STR("Internal error"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
cweb_respond_basic(req, 400, CWEB_STR("Invalid credentials"));
|
cweb_respond_basic(req, 400, CWEB_STR("Invalid credentials"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cweb_set_user_id(req, ret) < 0) {
|
if (cweb_set_user_id(req, ret) < 0) {
|
||||||
cweb_respond_basic(req, 500, CWEB_STR("Internal error"));
|
cweb_respond_basic(req, 500, CWEB_STR("Internal error"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cweb_respond_redirect(req, CWEB_STR("/index"));
|
cweb_respond_redirect(req, CWEB_STR("/index"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void endpoint_api_signup(CWEB *cweb, CWEB_Request *req)
|
static void endpoint_api_signup(CWEB *cweb, CWEB_Request *req)
|
||||||
{
|
{
|
||||||
if (cweb_get_user_id(req) != -1) {
|
if (cweb_get_user_id(req) != -1) {
|
||||||
cweb_respond_redirect(req, CWEB_STR("/index"));
|
cweb_respond_redirect(req, CWEB_STR("/index"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CWEB_String name = cweb_get_param_s(req, CWEB_STR("username"));
|
CWEB_String name = cweb_get_param_s(req, CWEB_STR("username"));
|
||||||
CWEB_String email = cweb_get_param_s(req, CWEB_STR("email"));
|
CWEB_String email = cweb_get_param_s(req, CWEB_STR("email"));
|
||||||
CWEB_String pass1 = cweb_get_param_s(req, CWEB_STR("password1"));
|
CWEB_String pass1 = cweb_get_param_s(req, CWEB_STR("password1"));
|
||||||
CWEB_String pass2 = cweb_get_param_s(req, CWEB_STR("password2"));
|
CWEB_String pass2 = cweb_get_param_s(req, CWEB_STR("password2"));
|
||||||
|
|
||||||
if (!valid_name(name) || !valid_email(email) || !valid_pass(pass1)) {
|
if (!valid_name(name) || !valid_email(email) || !valid_pass(pass1)) {
|
||||||
cweb_respond_basic(req, 400, CWEB_STR("Invalid credentials"));
|
cweb_respond_basic(req, 400, CWEB_STR("Invalid credentials"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cweb_streq(pass1, pass2)) {
|
if (!cweb_streq(pass1, pass2)) {
|
||||||
cweb_respond_basic(req, 400, CWEB_STR("The password was repeated incorrectly"));
|
cweb_respond_basic(req, 400, CWEB_STR("The password was repeated incorrectly"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CWEB_PasswordHash hash;
|
CWEB_PasswordHash hash;
|
||||||
int ret = cweb_hash_password(pass1, 12, &hash);
|
int ret = cweb_hash_password(pass1, 12, &hash);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
cweb_respond_basic(req, 500, CWEB_STR("Internal error"));
|
cweb_respond_basic(req, 500, CWEB_STR("Internal error"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t insert_id = cweb_database_insert(cweb, "INSERT INTO Users(username, email, hash) VALUES (?, ?, ?)", name, email, hash);
|
int64_t insert_id = cweb_database_insert(cweb, "INSERT INTO Users(username, email, hash) VALUES (?, ?, ?)", name, email, hash);
|
||||||
if (insert_id < 0) {
|
if (insert_id < 0) {
|
||||||
// TODO: What if the user exists?
|
// TODO: What if the user exists?
|
||||||
cweb_respond_basic(req, 500, CWEB_STR("Internal error"));
|
cweb_respond_basic(req, 500, CWEB_STR("Internal error"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cweb_set_user_id(req, insert_id) < 0) {
|
if (cweb_set_user_id(req, insert_id) < 0) {
|
||||||
cweb_respond_basic(req, 500, CWEB_STR("Internal error"));
|
cweb_respond_basic(req, 500, CWEB_STR("Internal error"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cweb_respond_redirect(req, CWEB_STR("/index"));
|
cweb_respond_redirect(req, CWEB_STR("/index"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void endpoint_api_logout(CWEB *cweb, CWEB_Request *req)
|
static void endpoint_api_logout(CWEB *cweb, CWEB_Request *req)
|
||||||
{
|
{
|
||||||
(void) cweb;
|
(void) cweb;
|
||||||
|
|
||||||
cweb_set_user_id(req, -1);
|
cweb_set_user_id(req, -1);
|
||||||
cweb_respond_redirect(req, CWEB_STR("/index"));
|
cweb_respond_redirect(req, CWEB_STR("/index"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void endpoint_api_post(CWEB *cweb, CWEB_Request *req)
|
static void endpoint_api_post(CWEB *cweb, CWEB_Request *req)
|
||||||
{
|
{
|
||||||
int user_id = cweb_get_user_id(req);
|
int user_id = cweb_get_user_id(req);
|
||||||
if (user_id == -1) {
|
if (user_id == -1) {
|
||||||
cweb_respond_redirect(req, CWEB_STR("/index"));
|
cweb_respond_redirect(req, CWEB_STR("/index"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CWEB_String title = cweb_get_param_s(req, CWEB_STR("title"));
|
CWEB_String title = cweb_get_param_s(req, CWEB_STR("title"));
|
||||||
CWEB_String link = cweb_get_param_s(req, CWEB_STR("link"));
|
CWEB_String link = cweb_get_param_s(req, CWEB_STR("link"));
|
||||||
CWEB_String content = cweb_get_param_s(req, CWEB_STR("content"));
|
CWEB_String content = cweb_get_param_s(req, CWEB_STR("content"));
|
||||||
CWEB_String csrf = cweb_get_param_s(req, CWEB_STR("csrf"));
|
CWEB_String csrf = cweb_get_param_s(req, CWEB_STR("csrf"));
|
||||||
|
|
||||||
if (!cweb_streq(cweb_get_csrf(req), csrf)) {
|
if (!cweb_streq(cweb_get_csrf(req), csrf)) {
|
||||||
cweb_respond_basic(req, 400, CWEB_STR("Invalid request"));
|
cweb_respond_basic(req, 400, CWEB_STR("Invalid request"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!valid_post_title(title)) {
|
if (!valid_post_title(title)) {
|
||||||
cweb_respond_basic(req, 400, CWEB_STR("Invalid title"));
|
cweb_respond_basic(req, 400, CWEB_STR("Invalid title"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!valid_link(link)) {
|
if (!valid_link(link)) {
|
||||||
cweb_respond_basic(req, 400, CWEB_STR("Invalid link"));
|
cweb_respond_basic(req, 400, CWEB_STR("Invalid link"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!valid_post_content(content)) {
|
if (!valid_post_content(content)) {
|
||||||
cweb_respond_basic(req, 400, CWEB_STR("Invalid content"));
|
cweb_respond_basic(req, 400, CWEB_STR("Invalid content"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_link = false;
|
bool is_link = false;
|
||||||
if (link.len > 0) {
|
if (link.len > 0) {
|
||||||
is_link = true;
|
is_link = true;
|
||||||
content = link;
|
content = link;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t insert_id = cweb_database_insert(cweb,
|
int64_t insert_id = cweb_database_insert(cweb,
|
||||||
"INSERT INTO Posts(author, title, is_link, content) VALUES (?, ?, ?, ?)",
|
"INSERT INTO Posts(author, title, is_link, content) VALUES (?, ?, ?, ?)",
|
||||||
user_id, title, is_link, content);
|
user_id, title, is_link, content);
|
||||||
|
|
||||||
if (insert_id < 0) {
|
if (insert_id < 0) {
|
||||||
cweb_respond_basic(req, 500, CWEB_STR("Internal error"));
|
cweb_respond_basic(req, 500, CWEB_STR("Internal error"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int post_id = (int) insert_id;
|
int post_id = (int) insert_id;
|
||||||
|
|
||||||
CWEB_String target = cweb_format(req, "/post?id={}", post_id);
|
CWEB_String target = cweb_format(req, "/post?id={}", post_id);
|
||||||
cweb_respond_redirect(req, target);
|
cweb_respond_redirect(req, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void endpoint_api_comment(CWEB *cweb, CWEB_Request *req)
|
static void endpoint_api_comment(CWEB *cweb, CWEB_Request *req)
|
||||||
{
|
{
|
||||||
int user_id = cweb_get_user_id(req);
|
int user_id = cweb_get_user_id(req);
|
||||||
if (user_id == -1) {
|
if (user_id == -1) {
|
||||||
cweb_respond_basic(req, 400, CWEB_STR("You are not logged in"));
|
cweb_respond_basic(req, 400, CWEB_STR("You are not logged in"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parent_post = cweb_get_param_i(req, CWEB_STR("parent_post"));
|
int parent_post = cweb_get_param_i(req, CWEB_STR("parent_post"));
|
||||||
int parent_comment = cweb_get_param_i(req, CWEB_STR("parent_comment"));
|
int parent_comment = cweb_get_param_i(req, CWEB_STR("parent_comment"));
|
||||||
CWEB_String content = cweb_get_param_s(req, CWEB_STR("content"));
|
CWEB_String content = cweb_get_param_s(req, CWEB_STR("content"));
|
||||||
CWEB_String csrf2 = cweb_get_param_s(req, CWEB_STR("csrf"));
|
CWEB_String csrf2 = cweb_get_param_s(req, CWEB_STR("csrf"));
|
||||||
|
|
||||||
if (!cweb_streq(cweb_get_csrf(req), csrf2)) {
|
if (!cweb_streq(cweb_get_csrf(req), csrf2)) {
|
||||||
cweb_respond_basic(req, 400, CWEB_STR("Invalid request"));
|
cweb_respond_basic(req, 400, CWEB_STR("Invalid request"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
content = cweb_trim(content);
|
content = cweb_trim(content);
|
||||||
if (!valid_comment_content(content)) {
|
if (!valid_comment_content(content)) {
|
||||||
cweb_respond_basic(req, 400, CWEB_STR("Invalid content"));
|
cweb_respond_basic(req, 400, CWEB_STR("Invalid content"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t insert_id;
|
int64_t insert_id;
|
||||||
if (parent_comment == -1) insert_id = cweb_database_insert(cweb, "INSERT INTO Comments(author, content, parent_post) VALUES (?, ?, ?)", user_id, content, parent_post);
|
if (parent_comment == -1) insert_id = cweb_database_insert(cweb, "INSERT INTO Comments(author, content, parent_post) VALUES (?, ?, ?)", user_id, content, parent_post);
|
||||||
else insert_id = cweb_database_insert(cweb, "INSERT INTO Comments(author, content, parent_post, parent_comment) VALUES (?, ?, ?, ?)", user_id, content, parent_post, parent_comment);
|
else insert_id = cweb_database_insert(cweb, "INSERT INTO Comments(author, content, parent_post, parent_comment) VALUES (?, ?, ?, ?)", user_id, content, parent_post, parent_comment);
|
||||||
if (insert_id < 0) {
|
if (insert_id < 0) {
|
||||||
cweb_respond_basic(req, 500, CWEB_STR("Internal error"));
|
cweb_respond_basic(req, 500, CWEB_STR("Internal error"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CWEB_String target = cweb_format(req, "/post?id={}", parent_post);
|
CWEB_String target = cweb_format(req, "/post?id={}", parent_post);
|
||||||
cweb_respond_redirect(req, target);
|
cweb_respond_redirect(req, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void endpoint_index(CWEB *cweb, CWEB_Request *req)
|
static void endpoint_index(CWEB *cweb, CWEB_Request *req)
|
||||||
{
|
{
|
||||||
(void) cweb;
|
(void) cweb;
|
||||||
|
|
||||||
cweb_respond_template(req, 200, CWEB_STR("demo/pages/index.wl"), -1);
|
cweb_respond_template(req, 200, CWEB_STR("demo/pages/index.wl"), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void endpoint_write(CWEB *cweb, CWEB_Request *req)
|
static void endpoint_write(CWEB *cweb, CWEB_Request *req)
|
||||||
{
|
{
|
||||||
(void) cweb;
|
(void) cweb;
|
||||||
|
|
||||||
if (cweb_get_user_id(req) == -1) {
|
if (cweb_get_user_id(req) == -1) {
|
||||||
cweb_respond_redirect(req, CWEB_STR("/index"));
|
cweb_respond_redirect(req, CWEB_STR("/index"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cweb_respond_template(req, 200, CWEB_STR("demo/pages/write.wl"), -1);
|
cweb_respond_template(req, 200, CWEB_STR("demo/pages/write.wl"), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void endpoint_login(CWEB *cweb, CWEB_Request *req)
|
static void endpoint_login(CWEB *cweb, CWEB_Request *req)
|
||||||
{
|
{
|
||||||
(void) cweb;
|
(void) cweb;
|
||||||
|
|
||||||
if (cweb_get_user_id(req) != -1) {
|
if (cweb_get_user_id(req) != -1) {
|
||||||
cweb_respond_redirect(req, CWEB_STR("/index"));
|
cweb_respond_redirect(req, CWEB_STR("/index"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cweb_respond_template(req, 200, CWEB_STR("demo/pages/login.wl"), -1);
|
cweb_respond_template(req, 200, CWEB_STR("demo/pages/login.wl"), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void endpoint_signup(CWEB *cweb, CWEB_Request *req)
|
static void endpoint_signup(CWEB *cweb, CWEB_Request *req)
|
||||||
{
|
{
|
||||||
(void) cweb;
|
(void) cweb;
|
||||||
|
|
||||||
if (cweb_get_user_id(req) != -1) {
|
if (cweb_get_user_id(req) != -1) {
|
||||||
cweb_respond_redirect(req, CWEB_STR("/index"));
|
cweb_respond_redirect(req, CWEB_STR("/index"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cweb_respond_template(req, 200, CWEB_STR("demo/pages/signup.wl"), -1);
|
cweb_respond_template(req, 200, CWEB_STR("demo/pages/signup.wl"), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void endpoint_post(CWEB *cweb, CWEB_Request *req)
|
static void endpoint_post(CWEB *cweb, CWEB_Request *req)
|
||||||
{
|
{
|
||||||
int post_id = cweb_get_param_i(req, CWEB_STR("id"));
|
int post_id = cweb_get_param_i(req, CWEB_STR("id"));
|
||||||
if (post_id < 0) {
|
if (post_id < 0) {
|
||||||
cweb_respond_template(req, 404, CWEB_STR("demo/pages/notfound.wl"), -1);
|
cweb_respond_template(req, 404, CWEB_STR("demo/pages/notfound.wl"), -1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CWEB_QueryResult res = cweb_database_select(cweb, "SELECT COUNT(*) FROM Posts WHERE id=?", post_id);
|
CWEB_QueryResult res = cweb_database_select(cweb, "SELECT COUNT(*) FROM Posts WHERE id=?", post_id);
|
||||||
|
|
||||||
int num;
|
int num;
|
||||||
if (cweb_next_query_row(&res, &num) != 1) {
|
if (cweb_next_query_row(&res, &num) != 1) {
|
||||||
cweb_respond_basic(req, 500, CWEB_STR(""));
|
cweb_respond_basic(req, 500, CWEB_STR(""));
|
||||||
cweb_free_query_result(&res);
|
cweb_free_query_result(&res);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cweb_free_query_result(&res);
|
cweb_free_query_result(&res);
|
||||||
|
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
cweb_respond_basic(req, 500, CWEB_STR(""));
|
cweb_respond_basic(req, 500, CWEB_STR(""));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num == 0) {
|
if (num == 0) {
|
||||||
cweb_respond_template(req, 404, CWEB_STR("demo/pages/notfound.wl"), -1);
|
cweb_respond_template(req, 404, CWEB_STR("demo/pages/notfound.wl"), -1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cweb_respond_template(req, 200, CWEB_STR("demo/pages/post.wl"), post_id);
|
cweb_respond_template(req, 200, CWEB_STR("demo/pages/post.wl"), post_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void endpoint_fallback(CWEB *cweb, CWEB_Request *req)
|
static void endpoint_fallback(CWEB *cweb, CWEB_Request *req)
|
||||||
{
|
{
|
||||||
(void) cweb;
|
(void) cweb;
|
||||||
|
|
||||||
cweb_respond_template(req, 404, CWEB_STR("demo/pages/notfound.wl"), -1);
|
cweb_respond_template(req, 404, CWEB_STR("demo/pages/notfound.wl"), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
CWEB_String addr = CWEB_STR("127.0.0.1");
|
CWEB_String addr = CWEB_STR("127.0.0.1");
|
||||||
uint16_t port = 8080;
|
uint16_t port = 8080;
|
||||||
CWEB_String database_file = CWEB_STR(":memory:");
|
CWEB_String database_file = CWEB_STR(":memory:");
|
||||||
CWEB_String schema_file = CWEB_STR("demo/schema.sql");
|
CWEB_String schema_file = CWEB_STR("demo/schema.sql");
|
||||||
|
|
||||||
if (cweb_global_init() < 0)
|
if (cweb_global_init() < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
CWEB *cweb = cweb_init(addr, port);
|
CWEB *cweb = cweb_init(addr, port);
|
||||||
if (cweb == NULL) {
|
if (cweb == NULL) {
|
||||||
cweb_global_free();
|
cweb_global_free();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cweb_enable_database(cweb, database_file, schema_file) < 0) {
|
if (cweb_enable_database(cweb, database_file, schema_file) < 0) {
|
||||||
cweb_free(cweb);
|
cweb_free(cweb);
|
||||||
cweb_global_free();
|
cweb_global_free();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cweb_trace_sql(cweb, true);
|
cweb_trace_sql(cweb, true);
|
||||||
|
cweb_enable_template_cache(cweb, false);
|
||||||
for (;;) {
|
|
||||||
CWEB_Request *req = cweb_wait(cweb);
|
for (;;) {
|
||||||
if (0) {}
|
CWEB_Request *req = cweb_wait(cweb);
|
||||||
else if (cweb_match_endpoint(req, CWEB_STR("/api/login"))) endpoint_api_login(cweb, req);
|
if (0) {}
|
||||||
else if (cweb_match_endpoint(req, CWEB_STR("/api/signup"))) endpoint_api_signup(cweb, req);
|
else if (cweb_match_endpoint(req, CWEB_STR("/api/login"))) endpoint_api_login(cweb, req);
|
||||||
else if (cweb_match_endpoint(req, CWEB_STR("/api/logout"))) endpoint_api_logout(cweb, req);
|
else if (cweb_match_endpoint(req, CWEB_STR("/api/signup"))) endpoint_api_signup(cweb, req);
|
||||||
else if (cweb_match_endpoint(req, CWEB_STR("/api/post"))) endpoint_api_post(cweb, req);
|
else if (cweb_match_endpoint(req, CWEB_STR("/api/logout"))) endpoint_api_logout(cweb, req);
|
||||||
else if (cweb_match_endpoint(req, CWEB_STR("/api/comment"))) endpoint_api_comment(cweb, req);
|
else if (cweb_match_endpoint(req, CWEB_STR("/api/post"))) endpoint_api_post(cweb, req);
|
||||||
else if (cweb_match_endpoint(req, CWEB_STR("/index"))) endpoint_index(cweb, req);
|
else if (cweb_match_endpoint(req, CWEB_STR("/api/comment"))) endpoint_api_comment(cweb, req);
|
||||||
else if (cweb_match_endpoint(req, CWEB_STR("/write"))) endpoint_write(cweb, req);
|
else if (cweb_match_endpoint(req, CWEB_STR("/index"))) endpoint_index(cweb, req);
|
||||||
else if (cweb_match_endpoint(req, CWEB_STR("/login"))) endpoint_login(cweb, req);
|
else if (cweb_match_endpoint(req, CWEB_STR("/write"))) endpoint_write(cweb, req);
|
||||||
else if (cweb_match_endpoint(req, CWEB_STR("/signup"))) endpoint_signup(cweb, req);
|
else if (cweb_match_endpoint(req, CWEB_STR("/login"))) endpoint_login(cweb, req);
|
||||||
else if (cweb_match_endpoint(req, CWEB_STR("/post"))) endpoint_post(cweb, req);
|
else if (cweb_match_endpoint(req, CWEB_STR("/signup"))) endpoint_signup(cweb, req);
|
||||||
else endpoint_fallback(cweb, req);
|
else if (cweb_match_endpoint(req, CWEB_STR("/post"))) endpoint_post(cweb, req);
|
||||||
}
|
else endpoint_fallback(cweb, req);
|
||||||
|
}
|
||||||
cweb_free(cweb);
|
|
||||||
cweb_global_free();
|
cweb_free(cweb);
|
||||||
return 0;
|
cweb_global_free();
|
||||||
}
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
+66
-66
@@ -1,67 +1,67 @@
|
|||||||
include "page.wl"
|
include "page.wl"
|
||||||
|
|
||||||
let posts = $query("SELECT P.id, P.title, P.is_link, P.content, (SELECT COUNT(*) FROM Comments as C WHERE c.parent_post=P.id) as num_comments, CURRENT_TIMESTAMP as date FROM Posts as P")
|
let posts = $query("SELECT P.id, P.title, P.is_link, P.content, (SELECT COUNT(*) FROM Comments as C WHERE c.parent_post=P.id) as num_comments, CURRENT_TIMESTAMP as date FROM Posts as P")
|
||||||
|
|
||||||
if posts == none:
|
if posts == none:
|
||||||
posts = []
|
posts = []
|
||||||
|
|
||||||
let style =
|
let style =
|
||||||
<style>
|
<style>
|
||||||
.item {
|
.item {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
border-bottom: 1px solid #E8D4A9;
|
border-bottom: 1px solid #E8D4A9;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
.item:last-child {
|
.item:last-child {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
.item span {
|
.item span {
|
||||||
color: #7A5F2A;
|
color: #7A5F2A;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.item div {
|
.item div {
|
||||||
color: #E8D4A9;
|
color: #E8D4A9;
|
||||||
float: left
|
float: left
|
||||||
}
|
}
|
||||||
.item div:first-child {
|
.item div:first-child {
|
||||||
width: calc(100% - 250px);
|
width: calc(100% - 250px);
|
||||||
}
|
}
|
||||||
.item div:last-child {
|
.item div:last-child {
|
||||||
width: 250px;
|
width: 250px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
#no-posts {
|
#no-posts {
|
||||||
margin: 60px auto;
|
margin: 60px auto;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #7A5F2A;
|
color: #7A5F2A;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
let main =
|
let main =
|
||||||
<main>
|
<main>
|
||||||
|
|
||||||
\if len(posts) == 0:
|
\if len(posts) == 0:
|
||||||
<div id="no-posts">There are no posts yet!</div>
|
<div id="no-posts">There are no posts yet!</div>
|
||||||
|
|
||||||
\for post in posts: {
|
\for post in posts: {
|
||||||
|
|
||||||
let link
|
let link
|
||||||
if post.is_link != 0:
|
if post.is_link != 0:
|
||||||
link = post.content
|
link = post.content
|
||||||
else
|
else
|
||||||
link = ["/post?id=", post.id]
|
link = ["/post?id=", post.id]
|
||||||
|
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<div>
|
<div>
|
||||||
<a href=\'"'\link\'"'>\escape(post.title)</a>
|
<a href=\'"'\link\'"'>\escape(post.title)</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span>\escape(post.date)</span> | <span>\escape(post.num_comments) comments</span>
|
<span>\escape(post.date)</span> | <span>\escape(post.num_comments) comments</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
page("Index", $login_user_id, style, main)
|
page("Index", $login_user_id, style, main)
|
||||||
+22
-22
@@ -1,22 +1,22 @@
|
|||||||
include "page.wl"
|
include "page.wl"
|
||||||
include "login_and_signup_style.wl"
|
include "login_and_signup_style.wl"
|
||||||
|
|
||||||
let main =
|
let main =
|
||||||
<main>
|
<main>
|
||||||
<span>Welcome back!</span>
|
<span>Welcome back!</span>
|
||||||
|
|
||||||
<div id="response"></div>
|
<div id="response"></div>
|
||||||
|
|
||||||
<form action="/api/login" method="POST">
|
<form action="/api/login" method="POST">
|
||||||
<input type="text" name="username" placeholder="username" />
|
<input type="text" name="username" placeholder="username" />
|
||||||
<input type="password" name="password" placeholder="password" />
|
<input type="password" name="password" placeholder="password" />
|
||||||
<input type="submit" value="Log-In" />
|
<input type="submit" value="Log-In" />
|
||||||
<div class="form-links">
|
<div class="form-links">
|
||||||
<a href="">forgot password?</a>
|
<a href="">forgot password?</a>
|
||||||
|
|
|
|
||||||
<a href="">create account</a>
|
<a href="">create account</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
page("Log-In", none, style, main)
|
page("Log-In", none, style, main)
|
||||||
|
|||||||
@@ -1,74 +1,74 @@
|
|||||||
let style =
|
let style =
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
span {
|
span {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #1D2B42;
|
color: #1D2B42;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
form {
|
form {
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
margin: 30px auto;
|
margin: 30px auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
form input {
|
form input {
|
||||||
border: 0;
|
border: 0;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
form input[type=text],
|
form input[type=text],
|
||||||
form input[type=email],
|
form input[type=email],
|
||||||
form input[type=password] {
|
form input[type=password] {
|
||||||
background: #E8D4A9;
|
background: #E8D4A9;
|
||||||
border: 1px solid #D4C298;
|
border: 1px solid #D4C298;
|
||||||
}
|
}
|
||||||
|
|
||||||
form input[type=text]:focus,
|
form input[type=text]:focus,
|
||||||
form input[type=email]:focus,
|
form input[type=email]:focus,
|
||||||
form input[type=password]:focus {
|
form input[type=password]:focus {
|
||||||
border-color: #5780C9;
|
border-color: #5780C9;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
form input[type=submit] {
|
form input[type=submit] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: #5780C9;
|
background: #5780C9;
|
||||||
color: #F7E6C0;
|
color: #F7E6C0;
|
||||||
}
|
}
|
||||||
|
|
||||||
form input[type=submit]:hover {
|
form input[type=submit]:hover {
|
||||||
background: #1D2B42;
|
background: #1D2B42;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-links {
|
.form-links {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
.form-links a {
|
.form-links a {
|
||||||
color: #7A5F2A;
|
color: #7A5F2A;
|
||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
}
|
}
|
||||||
.form-links a:hover {
|
.form-links a:hover {
|
||||||
color: #1D2B42;
|
color: #1D2B42;
|
||||||
}
|
}
|
||||||
|
|
||||||
#response {
|
#response {
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
#response .error {
|
#response .error {
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
border: 1px solid #E44C82;
|
border: 1px solid #E44C82;
|
||||||
background: #F295B5;
|
background: #F295B5;
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
+60
-60
@@ -1,60 +1,60 @@
|
|||||||
include "page.wl"
|
include "page.wl"
|
||||||
|
|
||||||
let style =
|
let style =
|
||||||
<style>
|
<style>
|
||||||
.not-found-container {
|
.not-found-container {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 60px 20px;
|
padding: 60px 20px;
|
||||||
}
|
}
|
||||||
.error-code {
|
.error-code {
|
||||||
font-size: 72px;
|
font-size: 72px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #7A5F2A;
|
color: #7A5F2A;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
line-height: 100%;
|
line-height: 100%;
|
||||||
}
|
}
|
||||||
.error-message {
|
.error-message {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
color: #1D2B42;
|
color: #1D2B42;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
.error-description {
|
.error-description {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #7A5F2A;
|
color: #7A5F2A;
|
||||||
margin-bottom: 40px;
|
margin-bottom: 40px;
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
line-height: 160%;
|
line-height: 160%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-button {
|
.home-button {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background: #5780C9;
|
background: #5780C9;
|
||||||
color: #F7E6C0;
|
color: #F7E6C0;
|
||||||
padding: 12px 24px;
|
padding: 12px 24px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
border: none;
|
border: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.home-button:hover {
|
.home-button:hover {
|
||||||
background: #1D2B42;
|
background: #1D2B42;
|
||||||
color: #F7E6C0;
|
color: #F7E6C0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
let main =
|
let main =
|
||||||
<main>
|
<main>
|
||||||
<div class="not-found-container">
|
<div class="not-found-container">
|
||||||
<div class="error-code">404</div>
|
<div class="error-code">404</div>
|
||||||
<div class="error-message">Page Not Found</div>
|
<div class="error-message">Page Not Found</div>
|
||||||
<div class="error-description">
|
<div class="error-description">
|
||||||
Looks like this page wandered off somewhere.
|
Looks like this page wandered off somewhere.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
page("Not Found", $login_user_id, style, main)
|
page("Not Found", $login_user_id, style, main)
|
||||||
|
|||||||
+75
-75
@@ -1,75 +1,75 @@
|
|||||||
|
|
||||||
procedure page(title, login_user_id, style, main)
|
procedure page(title, login_user_id, style, main)
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<title>CN - \escape(title)</title>
|
<title>CN - \escape(title)</title>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
line-height: 200%;
|
line-height: 200%;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
margin: 20px auto;
|
margin: 20px auto;
|
||||||
}
|
}
|
||||||
nav {
|
nav {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
background: #5780C9;
|
background: #5780C9;
|
||||||
color: #6E93D4;
|
color: #6E93D4;
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
border-top-left-radius: 3px;
|
border-top-left-radius: 3px;
|
||||||
border-top-right-radius: 3px;
|
border-top-right-radius: 3px;
|
||||||
}
|
}
|
||||||
nav div {
|
nav div {
|
||||||
float: left
|
float: left
|
||||||
}
|
}
|
||||||
nav div:last-child {
|
nav div:last-child {
|
||||||
float: right
|
float: right
|
||||||
}
|
}
|
||||||
nav a {
|
nav a {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #1D2B42;
|
color: #1D2B42;
|
||||||
}
|
}
|
||||||
nav a.current {
|
nav a.current {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
main {
|
main {
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
background: #F7E6C0;
|
background: #F7E6C0;
|
||||||
border-bottom-left-radius: 3px;
|
border-bottom-left-radius: 3px;
|
||||||
border-bottom-right-radius: 3px;
|
border-bottom-right-radius: 3px;
|
||||||
}
|
}
|
||||||
footer {
|
footer {
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
\(style)
|
\(style)
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/htmx/1.9.2/htmx.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/htmx/1.9.2/htmx.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav>
|
<nav>
|
||||||
<div>
|
<div>
|
||||||
<a href="/index">index</a>
|
<a href="/index">index</a>
|
||||||
\if login_user_id != none: {
|
\if login_user_id != none: {
|
||||||
"|\n"
|
"|\n"
|
||||||
<a href="/write">write</a>
|
<a href="/write">write</a>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
\if login_user_id == none:
|
\if login_user_id == none:
|
||||||
<div>
|
<div>
|
||||||
<a href="/login">log-in</a>
|
<a href="/login">log-in</a>
|
||||||
|
|
|
|
||||||
<a href="/signup">sign-up</a>
|
<a href="/signup">sign-up</a>
|
||||||
</div>
|
</div>
|
||||||
else
|
else
|
||||||
<div>
|
<div>
|
||||||
<a href="">settings</a>
|
<a href="">settings</a>
|
||||||
|
|
|
|
||||||
<a href="/api/logout">log-out</a>
|
<a href="/api/logout">log-out</a>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
\main
|
\main
|
||||||
<footer>
|
<footer>
|
||||||
Made with love by cozis
|
Made with love by cozis
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+248
-245
@@ -1,246 +1,249 @@
|
|||||||
include "page.wl"
|
include "page.wl"
|
||||||
|
|
||||||
let posts = $query("SELECT U.username, P.title, P.content FROM Posts as P, Users as U WHERE P.id=? AND U.id=P.author", $resource_id)
|
let post_id = $args(0)
|
||||||
let comments = $query("SELECT C.id, U.username, C.content, C.parent_post, C.parent_comment FROM Comments as C, Users as U WHERE C.parent_post=? AND U.id=C.author", $resource_id)
|
let posts = $query("SELECT U.username, P.title, P.content FROM Posts as P, Users as U WHERE P.id=? AND U.id=P.author", post_id)
|
||||||
|
let comments = $query("SELECT C.id, U.username, C.content, C.parent_post, C.parent_comment FROM Comments as C, Users as U WHERE C.parent_post=? AND U.id=C.author", post_id)
|
||||||
let lookup = {}
|
|
||||||
|
let lookup = {}
|
||||||
for comment in comments: {
|
|
||||||
comment.child = []
|
for comment in comments: {
|
||||||
lookup[comment.id] = comment
|
comment.child = []
|
||||||
}
|
lookup[comment.id] = comment
|
||||||
|
}
|
||||||
let root_comments = []
|
|
||||||
|
let root_comments = []
|
||||||
for comment in comments: {
|
|
||||||
if comment.parent_comment == none:
|
for comment in comments: {
|
||||||
root_comments << comment
|
if comment.parent_comment == none:
|
||||||
else
|
root_comments << comment
|
||||||
lookup[comment.parent_comment].child << comment
|
else
|
||||||
}
|
lookup[comment.parent_comment].child << comment
|
||||||
|
}
|
||||||
let post = posts[0]
|
|
||||||
|
let post = posts[0]
|
||||||
let style =
|
|
||||||
<style>
|
let style =
|
||||||
.thread-header {
|
<style>
|
||||||
padding: 15px 0;
|
.thread-header {
|
||||||
border-bottom: 2px solid #E8D4A9;
|
padding: 15px 0;
|
||||||
margin-bottom: 20px;
|
border-bottom: 2px solid #E8D4A9;
|
||||||
}
|
margin-bottom: 20px;
|
||||||
.thread-title {
|
}
|
||||||
font-size: 16px;
|
.thread-title {
|
||||||
font-weight: bold;
|
font-size: 16px;
|
||||||
margin-bottom: 8px;
|
font-weight: bold;
|
||||||
}
|
margin-bottom: 8px;
|
||||||
.thread-title a {
|
}
|
||||||
color: #1D2B42;
|
.thread-title a {
|
||||||
text-decoration: none;
|
color: #1D2B42;
|
||||||
}
|
text-decoration: none;
|
||||||
.thread-title a:hover {
|
}
|
||||||
text-decoration: underline;
|
.thread-title a:hover {
|
||||||
}
|
text-decoration: underline;
|
||||||
.thread-meta {
|
}
|
||||||
font-size: 12px;
|
.thread-meta {
|
||||||
color: #7A5F2A;
|
font-size: 12px;
|
||||||
margin-bottom: 10px;
|
color: #7A5F2A;
|
||||||
}
|
margin-bottom: 10px;
|
||||||
.thread-meta a {
|
}
|
||||||
color: #7A5F2A;
|
.thread-meta a {
|
||||||
}
|
color: #7A5F2A;
|
||||||
.thread-text {
|
}
|
||||||
font-size: 14px;
|
.thread-text {
|
||||||
color: #1D2B42;
|
font-size: 14px;
|
||||||
line-height: 160%;
|
color: #1D2B42;
|
||||||
margin-bottom: 10px;
|
line-height: 160%;
|
||||||
}
|
margin-bottom: 10px;
|
||||||
.thread-actions {
|
}
|
||||||
font-size: 12px;
|
.thread-actions {
|
||||||
}
|
font-size: 12px;
|
||||||
.thread-actions a {
|
}
|
||||||
color: #7A5F2A;
|
.thread-actions a {
|
||||||
margin-right: 10px;
|
color: #7A5F2A;
|
||||||
}
|
margin-right: 10px;
|
||||||
|
}
|
||||||
/* Comment styles */
|
|
||||||
.comment {
|
/* Comment styles */
|
||||||
margin-bottom: 15px;
|
.comment {
|
||||||
border-left: 1px solid #E8D4A9;
|
margin-bottom: 15px;
|
||||||
padding-left: 10px;
|
border-left: 1px solid #E8D4A9;
|
||||||
}
|
padding-left: 10px;
|
||||||
|
}
|
||||||
.comment-meta {
|
|
||||||
font-size: 11px;
|
.comment-meta {
|
||||||
color: #7A5F2A;
|
font-size: 11px;
|
||||||
margin-bottom: 5px;
|
color: #7A5F2A;
|
||||||
}
|
margin-bottom: 5px;
|
||||||
.comment-meta a {
|
}
|
||||||
color: #7A5F2A;
|
.comment-meta a {
|
||||||
}
|
color: #7A5F2A;
|
||||||
.comment-text {
|
}
|
||||||
font-size: 13px;
|
.comment-text {
|
||||||
color: #1D2B42;
|
font-size: 13px;
|
||||||
line-height: 150%;
|
color: #1D2B42;
|
||||||
margin-bottom: 5px;
|
line-height: 150%;
|
||||||
}
|
margin-bottom: 5px;
|
||||||
.comment-actions {
|
}
|
||||||
font-size: 11px;
|
.comment-actions {
|
||||||
}
|
font-size: 11px;
|
||||||
.comment-actions a {
|
}
|
||||||
color: #7A5F2A;
|
.comment-actions a {
|
||||||
margin-right: 8px;
|
color: #7A5F2A;
|
||||||
}
|
margin-right: 8px;
|
||||||
.comment-actions a:hover {
|
}
|
||||||
color: #1D2B42;
|
.comment-actions a:hover {
|
||||||
}
|
color: #1D2B42;
|
||||||
|
}
|
||||||
.vote-buttons {
|
|
||||||
float: left;
|
.vote-buttons {
|
||||||
width: 15px;
|
float: left;
|
||||||
margin-right: 8px;
|
width: 15px;
|
||||||
font-size: 10px;
|
margin-right: 8px;
|
||||||
text-align: center;
|
font-size: 10px;
|
||||||
}
|
text-align: center;
|
||||||
.vote-buttons a {
|
}
|
||||||
display: block;
|
.vote-buttons a {
|
||||||
color: #7A5F2A;
|
display: block;
|
||||||
text-decoration: none;
|
color: #7A5F2A;
|
||||||
line-height: 100%;
|
text-decoration: none;
|
||||||
}
|
line-height: 100%;
|
||||||
.vote-buttons a:hover {
|
}
|
||||||
color: #1D2B42;
|
.vote-buttons a:hover {
|
||||||
}
|
color: #1D2B42;
|
||||||
.comment-content {
|
}
|
||||||
margin-left: 23px;
|
.comment-content {
|
||||||
}
|
margin-left: 23px;
|
||||||
.comment-child {
|
}
|
||||||
margin-top: 10px;
|
.comment-child {
|
||||||
margin-left: 10px;
|
margin-top: 10px;
|
||||||
}
|
margin-left: 10px;
|
||||||
.add-comment {
|
}
|
||||||
}
|
.add-comment {
|
||||||
.add-comment form {
|
}
|
||||||
margin: 0;
|
.add-comment form {
|
||||||
overflow: auto;
|
margin: 0;
|
||||||
}
|
overflow: auto;
|
||||||
.add-comment form textarea {
|
}
|
||||||
width: 100%;
|
.add-comment form textarea {
|
||||||
height: 80px;
|
width: 100%;
|
||||||
font-family: monospace;
|
height: 80px;
|
||||||
font-size: 12px;
|
font-family: monospace;
|
||||||
background: white;
|
font-size: 12px;
|
||||||
border: 1px solid #D4C298;
|
background: white;
|
||||||
border-radius: 3px;
|
border: 1px solid #D4C298;
|
||||||
padding: 8px;
|
border-radius: 3px;
|
||||||
box-sizing: border-box;
|
padding: 8px;
|
||||||
resize: vertical;
|
box-sizing: border-box;
|
||||||
}
|
resize: vertical;
|
||||||
.add-comment form input[type=submit] {
|
}
|
||||||
background: #5780C9;
|
.add-comment form input[type=submit] {
|
||||||
color: white;
|
background: #5780C9;
|
||||||
border: none;
|
color: white;
|
||||||
border-radius: 3px;
|
border: none;
|
||||||
padding: 6px 12px;
|
border-radius: 3px;
|
||||||
font-family: monospace;
|
padding: 6px 12px;
|
||||||
font-size: 12px;
|
font-family: monospace;
|
||||||
cursor: pointer;
|
font-size: 12px;
|
||||||
margin-top: 8px;
|
cursor: pointer;
|
||||||
float: right;
|
margin-top: 8px;
|
||||||
}
|
float: right;
|
||||||
.add-comment input[type=submit]:hover {
|
}
|
||||||
background: #1D2B42;
|
.add-comment input[type=submit]:hover {
|
||||||
}
|
background: #1D2B42;
|
||||||
summary {
|
}
|
||||||
list-style: none;
|
summary {
|
||||||
text-decoration: underline;
|
list-style: none;
|
||||||
color: #7A5F2A;
|
text-decoration: underline;
|
||||||
cursor: pointer;
|
color: #7A5F2A;
|
||||||
}
|
cursor: pointer;
|
||||||
::-webkit-details-marker {
|
}
|
||||||
display: none;
|
::-webkit-details-marker {
|
||||||
}
|
display: none;
|
||||||
|
}
|
||||||
#no-comments {
|
|
||||||
margin: 30px 0;
|
#no-comments {
|
||||||
width: 100%;
|
margin: 30px 0;
|
||||||
text-align: center;
|
width: 100%;
|
||||||
color: #7A5F2A;
|
text-align: center;
|
||||||
}
|
color: #7A5F2A;
|
||||||
pre {
|
}
|
||||||
white-space: pre-wrap; /* Since CSS 2.1 */
|
pre {
|
||||||
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
white-space: pre-wrap; /* Since CSS 2.1 */
|
||||||
white-space: -pre-wrap; /* Opera 4-6 */
|
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
||||||
white-space: -o-pre-wrap; /* Opera 7 */
|
white-space: -pre-wrap; /* Opera 4-6 */
|
||||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
white-space: -o-pre-wrap; /* Opera 7 */
|
||||||
}
|
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||||
</style>
|
}
|
||||||
|
</style>
|
||||||
let main =
|
|
||||||
<main>
|
let main =
|
||||||
<div class="thread-header">
|
<main>
|
||||||
<div class="thread-title">
|
<div class="thread-header">
|
||||||
<span>\escape(post.title)</span>
|
<div class="thread-title">
|
||||||
</div>
|
<span>\escape(post.title)</span>
|
||||||
<div class="thread-meta">
|
</div>
|
||||||
submitted 3 hours ago by <a href="">\escape(post.username)</a> | <a href="">\len(comments)</a>
|
<div class="thread-meta">
|
||||||
</div>
|
submitted 3 hours ago by <a href="">\escape(post.username)</a> | <a href="">\len(comments)</a>
|
||||||
<div class="thread-text">
|
</div>
|
||||||
<pre>\escape(post.content)</pre>
|
<div class="thread-text">
|
||||||
</div>
|
<pre>\escape(post.content)</pre>
|
||||||
<details>
|
</div>
|
||||||
<summary>
|
<details>
|
||||||
reply
|
<summary>
|
||||||
</summary>
|
reply
|
||||||
<div class="add-comment">
|
</summary>
|
||||||
<form action="/api/comment" method="POST">
|
<div class="add-comment">
|
||||||
<input type="hidden" name="parent_post" value=\'"'\$resource_id\'"' />
|
<form action="/api/comment" method="POST">
|
||||||
<textarea name="content" placeholder="Add a comment..."></textarea>
|
<input type="hidden" name="csrf" value=\'"'\$csrf\'"' />
|
||||||
<input type="submit" vaue="Publish" />
|
<input type="hidden" name="parent_post" value=\'"'\post_id\'"' />
|
||||||
</form>
|
<textarea name="content" placeholder="Add a comment..."></textarea>
|
||||||
</div>
|
<input type="submit" vaue="Publish" />
|
||||||
</details>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
</details>
|
||||||
\procedure render_comment(comment)
|
</div>
|
||||||
<div class="comment">
|
|
||||||
<div class="vote-buttons">
|
\procedure render_comment(post_id, comment)
|
||||||
<a href="">▲</a>
|
<div class="comment">
|
||||||
<a href="">▼</a>
|
<div class="vote-buttons">
|
||||||
</div>
|
<a href="">▲</a>
|
||||||
<div class="comment-content">
|
<a href="">▼</a>
|
||||||
<div class="comment-meta">
|
</div>
|
||||||
<a href="">\escape(comment.username)</a> 2 hours ago
|
<div class="comment-content">
|
||||||
</div>
|
<div class="comment-meta">
|
||||||
<div class="comment-text">
|
<a href="">\escape(comment.username)</a> 2 hours ago
|
||||||
<pre>\escape(comment.content)</pre>
|
</div>
|
||||||
</div>
|
<div class="comment-text">
|
||||||
\if $login_user_id != none:
|
<pre>\escape(comment.content)</pre>
|
||||||
<details>
|
</div>
|
||||||
<summary>
|
\if $login_user_id != none:
|
||||||
reply
|
<details>
|
||||||
</summary>
|
<summary>
|
||||||
<div class="add-comment">
|
reply
|
||||||
<form action="/api/comment" method="POST">
|
</summary>
|
||||||
<input type="hidden" name="parent_post" value=\'"'\$resource_id\'"' />
|
<div class="add-comment">
|
||||||
<input type="hidden" name="parent_comment" value=\'"'\comment.id\'"' />
|
<form action="/api/comment" method="POST">
|
||||||
<textarea name="content" placeholder="Add a comment..."></textarea>
|
<input type="hidden" name="csrf" value=\'"'\$csrf\'"' />
|
||||||
<input type="submit" vaue="Publish" />
|
<input type="hidden" name="parent_post" value=\'"'\post_id\'"' />
|
||||||
</form>
|
<input type="hidden" name="parent_comment" value=\'"'\comment.id\'"' />
|
||||||
</div>
|
<textarea name="content" placeholder="Add a comment..."></textarea>
|
||||||
</details>
|
<input type="submit" vaue="Publish" />
|
||||||
</div>
|
</form>
|
||||||
<div class="comment-child">
|
</div>
|
||||||
\for child in comment.child:
|
</details>
|
||||||
render_comment(child)
|
</div>
|
||||||
</div>
|
<div class="comment-child">
|
||||||
</div>
|
\for child in comment.child:
|
||||||
|
render_comment(post_id, child)
|
||||||
\if len(root_comments) == 0:
|
</div>
|
||||||
<div id="no-comments">
|
</div>
|
||||||
No comments
|
|
||||||
</div>
|
\if len(root_comments) == 0:
|
||||||
else for comment in root_comments:
|
<div id="no-comments">
|
||||||
render_comment(comment)
|
No comments
|
||||||
</main>
|
</div>
|
||||||
|
else for comment in root_comments:
|
||||||
|
render_comment(post_id, comment)
|
||||||
|
</main>
|
||||||
|
|
||||||
page(post.title, $login_user_id, style, main)
|
page(post.title, $login_user_id, style, main)
|
||||||
+72
-72
@@ -1,73 +1,73 @@
|
|||||||
include "page.wl"
|
include "page.wl"
|
||||||
|
|
||||||
let posts = $query("SELECT title, content FROM Posts WHERE id=?", $post_id)
|
let posts = $query("SELECT title, content FROM Posts WHERE id=?", $post_id)
|
||||||
let comments = $query("SELECT C.id, U.username, C.content, C.parent_post, C.parent_comment FROM Comments as C, Users as U WHERE C.parent_post=? AND U.id == C.author", $post_id)
|
let comments = $query("SELECT C.id, U.username, C.content, C.parent_post, C.parent_comment FROM Comments as C, Users as U WHERE C.parent_post=? AND U.id == C.author", $post_id)
|
||||||
|
|
||||||
let lookup = {}
|
let lookup = {}
|
||||||
|
|
||||||
for comment in comments: {
|
for comment in comments: {
|
||||||
comment.child = []
|
comment.child = []
|
||||||
lookup[comment.id] = comment
|
lookup[comment.id] = comment
|
||||||
}
|
}
|
||||||
|
|
||||||
let roots = []
|
let roots = []
|
||||||
|
|
||||||
for comment in comments: {
|
for comment in comments: {
|
||||||
if comment.parent_comment == none:
|
if comment.parent_comment == none:
|
||||||
roots << comment
|
roots << comment
|
||||||
else
|
else
|
||||||
lookup[comment.parent_comment].child << comment
|
lookup[comment.parent_comment].child << comment
|
||||||
}
|
}
|
||||||
|
|
||||||
comments = roots
|
comments = roots
|
||||||
|
|
||||||
let post = posts[0]
|
let post = posts[0]
|
||||||
|
|
||||||
let style =
|
let style =
|
||||||
<style>
|
<style>
|
||||||
.child {
|
.child {
|
||||||
border-left: 3px solid #ccc;
|
border-left: 3px solid #ccc;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
form textarea {
|
form textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
procedure render_comment(parent)
|
procedure render_comment(parent)
|
||||||
<div>
|
<div>
|
||||||
<a href="">\parent.username</a>
|
<a href="">\parent.username</a>
|
||||||
<p>
|
<p>
|
||||||
\parent.content
|
\parent.content
|
||||||
</p>
|
</p>
|
||||||
<div class="child">
|
<div class="child">
|
||||||
\if $login_user_id != none:
|
\if $login_user_id != none:
|
||||||
<form action="/api/comment" method="POST">
|
<form action="/api/comment" method="POST">
|
||||||
<input type="hidden" name="parent_post" value=\'"'\$post_id\'"' />
|
<input type="hidden" name="parent_post" value=\'"'\$post_id\'"' />
|
||||||
<input type="hidden" name="parent_comment" value=\'"'\parent.id\'"' />
|
<input type="hidden" name="parent_comment" value=\'"'\parent.id\'"' />
|
||||||
<textarea name="content"></textarea>
|
<textarea name="content"></textarea>
|
||||||
<input type="submit" vaue="Publish" />
|
<input type="submit" vaue="Publish" />
|
||||||
</form>
|
</form>
|
||||||
\for child in parent.child:
|
\for child in parent.child:
|
||||||
render_comment(child)
|
render_comment(child)
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
let main =
|
let main =
|
||||||
<main>
|
<main>
|
||||||
<h3>\post.title</h3>
|
<h3>\post.title</h3>
|
||||||
<p>\post.content</p>
|
<p>\post.content</p>
|
||||||
<div>
|
<div>
|
||||||
<form action="/api/comment" method="POST">
|
<form action="/api/comment" method="POST">
|
||||||
<input type="hidden" name="parent_post" value=\'"'\$post_id\'"' />
|
<input type="hidden" name="parent_post" value=\'"'\$post_id\'"' />
|
||||||
<textarea name="content"></textarea>
|
<textarea name="content"></textarea>
|
||||||
<input type="submit" vaue="Publish" />
|
<input type="submit" vaue="Publish" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
\if len comments == 0:
|
\if len comments == 0:
|
||||||
<span>No comments yet!</span>
|
<span>No comments yet!</span>
|
||||||
else for comment in comments:
|
else for comment in comments:
|
||||||
render_comment(comment)
|
render_comment(comment)
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
page(post.title, $login_user_id, style, main)
|
page(post.title, $login_user_id, style, main)
|
||||||
+24
-24
@@ -1,24 +1,24 @@
|
|||||||
include "page.wl"
|
include "page.wl"
|
||||||
include "login_and_signup_style.wl"
|
include "login_and_signup_style.wl"
|
||||||
|
|
||||||
let main =
|
let main =
|
||||||
<main>
|
<main>
|
||||||
<span>Welcome!</span>
|
<span>Welcome!</span>
|
||||||
|
|
||||||
<div id="response"></div>
|
<div id="response"></div>
|
||||||
|
|
||||||
<form action="/api/signup" method="POST">
|
<form action="/api/signup" method="POST">
|
||||||
<input type="text" name="username" placeholder="username" />
|
<input type="text" name="username" placeholder="username" />
|
||||||
<input type="email" name="email" placeholder="email" />
|
<input type="email" name="email" placeholder="email" />
|
||||||
<input type="password" name="password1" placeholder="password" />
|
<input type="password" name="password1" placeholder="password" />
|
||||||
<input type="password" name="password2" placeholder="repeat password" />
|
<input type="password" name="password2" placeholder="repeat password" />
|
||||||
<input type="submit" value="Sign-Up" />
|
<input type="submit" value="Sign-Up" />
|
||||||
<div class="form-links">
|
<div class="form-links">
|
||||||
<a href="">forgot password?</a>
|
<a href="">forgot password?</a>
|
||||||
|
|
|
|
||||||
<a href="">already have an account?</a>
|
<a href="">already have an account?</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
page("Log-In", none, style, main)
|
page("Log-In", none, style, main)
|
||||||
|
|||||||
+94
-94
@@ -1,95 +1,95 @@
|
|||||||
include "page.wl"
|
include "page.wl"
|
||||||
|
|
||||||
let style =
|
let style =
|
||||||
<style>
|
<style>
|
||||||
form {
|
form {
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
margin: 30px auto;
|
margin: 30px auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
form input,
|
form input,
|
||||||
form textarea {
|
form textarea {
|
||||||
border: 0;
|
border: 0;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
background: #E8D4A9;
|
background: #E8D4A9;
|
||||||
border: 1px solid #D4C298;
|
border: 1px solid #D4C298;
|
||||||
}
|
}
|
||||||
|
|
||||||
form input:focus,
|
form input:focus,
|
||||||
form textarea:focus {
|
form textarea:focus {
|
||||||
border-color: #5780C9;
|
border-color: #5780C9;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
form textarea {
|
form textarea {
|
||||||
height: 120px;
|
height: 120px;
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
form input[type=submit] {
|
form input[type=submit] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: #5780C9;
|
background: #5780C9;
|
||||||
color: #F7E6C0;
|
color: #F7E6C0;
|
||||||
}
|
}
|
||||||
|
|
||||||
form input[type=submit]:hover {
|
form input[type=submit]:hover {
|
||||||
background: #1D2B42;
|
background: #1D2B42;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox-row {
|
.checkbox-row {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox-row input[type="checkbox"] {
|
.checkbox-row input[type="checkbox"] {
|
||||||
width: auto;
|
width: auto;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox-row label {
|
.checkbox-row label {
|
||||||
color: #1D2B42;
|
color: #1D2B42;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
let main =
|
let main =
|
||||||
<main>
|
<main>
|
||||||
<form action="/api/post" method="POST">
|
<form action="/api/post" method="POST">
|
||||||
|
|
||||||
<input type="hidden" name="csrf" value=\'"'\$csrf\'"' />
|
<input type="hidden" name="csrf" value=\'"'\$csrf\'"' />
|
||||||
<input type="text" id="title" name="title" placeholder="Title" required />
|
<input type="text" id="title" name="title" placeholder="Title" required />
|
||||||
|
|
||||||
<div class="checkbox-row">
|
<div class="checkbox-row">
|
||||||
<input type="checkbox" id="is_link" name="is_link" onchange="togglePostType()" />
|
<input type="checkbox" id="is_link" name="is_link" onchange="togglePostType()" />
|
||||||
<label>This is a link post</label>
|
<label>This is a link post</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="url" id="url" name="link" placeholder="URL" style="display: none;" />
|
<input type="url" id="url" name="link" placeholder="URL" style="display: none;" />
|
||||||
|
|
||||||
<textarea id="content" name="content" placeholder="Write your post here..."></textarea>
|
<textarea id="content" name="content" placeholder="Write your post here..."></textarea>
|
||||||
|
|
||||||
<input type="submit" value="Submit Post" />
|
<input type="submit" value="Submit Post" />
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function togglePostType() {
|
function togglePostType() {
|
||||||
const checkbox = document.getElementById('is_link');
|
const checkbox = document.getElementById('is_link');
|
||||||
const urlInput = document.getElementById('url');
|
const urlInput = document.getElementById('url');
|
||||||
const contentTextarea = document.getElementById('content');
|
const contentTextarea = document.getElementById('content');
|
||||||
|
|
||||||
if (checkbox.checked) {
|
if (checkbox.checked) {
|
||||||
urlInput.style.display = 'block';
|
urlInput.style.display = 'block';
|
||||||
contentTextarea.style.display = 'none';
|
contentTextarea.style.display = 'none';
|
||||||
} else {
|
} else {
|
||||||
urlInput.style.display = 'none';
|
urlInput.style.display = 'none';
|
||||||
contentTextarea.style.display = 'block';
|
contentTextarea.style.display = 'block';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
page("Write Post", $login_user_id, style, main)
|
page("Write Post", $login_user_id, style, main)
|
||||||
+29
-29
@@ -1,29 +1,29 @@
|
|||||||
CREATE TABLE IF NOT EXISTS Users (
|
CREATE TABLE IF NOT EXISTS Users (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
username TEXT NOT NULL UNIQUE,
|
username TEXT NOT NULL UNIQUE,
|
||||||
hash TEXT NOT NULL,
|
hash TEXT NOT NULL,
|
||||||
email TEXT NOT NULL UNIQUE,
|
email TEXT NOT NULL UNIQUE,
|
||||||
signup_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
signup_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS Posts (
|
CREATE TABLE IF NOT EXISTS Posts (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
author INTEGER NOT NULL,
|
author INTEGER NOT NULL,
|
||||||
title TEXT NOT NULL,
|
title TEXT NOT NULL,
|
||||||
is_link BOOLEAN NOT NULL,
|
is_link BOOLEAN NOT NULL,
|
||||||
content TEXT NOT NULL,
|
content TEXT NOT NULL,
|
||||||
submit_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
submit_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
FOREIGN KEY (author) REFERENCES Users(id)
|
FOREIGN KEY (author) REFERENCES Users(id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS Comments (
|
CREATE TABLE IF NOT EXISTS Comments (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
parent_post INTEGER NOT NULL,
|
parent_post INTEGER NOT NULL,
|
||||||
parent_comment INTEGER,
|
parent_comment INTEGER,
|
||||||
author INTEGER NOT NULL,
|
author INTEGER NOT NULL,
|
||||||
content TEXT NOT NULL,
|
content TEXT NOT NULL,
|
||||||
submit_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
submit_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
FOREIGN KEY (author) REFERENCES Users(id),
|
FOREIGN KEY (author) REFERENCES Users(id),
|
||||||
FOREIGN KEY (parent_post) REFERENCES Posts(id),
|
FOREIGN KEY (parent_post) REFERENCES Posts(id),
|
||||||
FOREIGN KEY (parent_comment) REFERENCES Comments(id)
|
FOREIGN KEY (parent_comment) REFERENCES Comments(id)
|
||||||
);
|
);
|
||||||
|
|||||||
+1630
-1630
File diff suppressed because it is too large
Load Diff
+315
-315
@@ -1,315 +1,315 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#define CWEB_ENABLE_DATABASE
|
#define CWEB_ENABLE_DATABASE
|
||||||
#define CWEB_ENABLE_TEMPLATE
|
#define CWEB_ENABLE_TEMPLATE
|
||||||
|
|
||||||
#define CWEB_STR(X) ((CWEB_String) { (X), (int) sizeof(X)-1 })
|
#define CWEB_STR(X) ((CWEB_String) { (X), (int) sizeof(X)-1 })
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int len;
|
int len;
|
||||||
} CWEB_String;
|
} CWEB_String;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char data[61];
|
char data[61];
|
||||||
} CWEB_PasswordHash;
|
} CWEB_PasswordHash;
|
||||||
|
|
||||||
CWEB_String cweb_trim(CWEB_String s);
|
CWEB_String cweb_trim(CWEB_String s);
|
||||||
bool cweb_streq(CWEB_String a, CWEB_String b);
|
bool cweb_streq(CWEB_String a, CWEB_String b);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CWEB_VARG_TYPE_C,
|
CWEB_VARG_TYPE_C,
|
||||||
CWEB_VARG_TYPE_S,
|
CWEB_VARG_TYPE_S,
|
||||||
CWEB_VARG_TYPE_I,
|
CWEB_VARG_TYPE_I,
|
||||||
CWEB_VARG_TYPE_L,
|
CWEB_VARG_TYPE_L,
|
||||||
CWEB_VARG_TYPE_LL,
|
CWEB_VARG_TYPE_LL,
|
||||||
CWEB_VARG_TYPE_SC,
|
CWEB_VARG_TYPE_SC,
|
||||||
CWEB_VARG_TYPE_SS,
|
CWEB_VARG_TYPE_SS,
|
||||||
CWEB_VARG_TYPE_SI,
|
CWEB_VARG_TYPE_SI,
|
||||||
CWEB_VARG_TYPE_SL,
|
CWEB_VARG_TYPE_SL,
|
||||||
CWEB_VARG_TYPE_SLL,
|
CWEB_VARG_TYPE_SLL,
|
||||||
CWEB_VARG_TYPE_UC,
|
CWEB_VARG_TYPE_UC,
|
||||||
CWEB_VARG_TYPE_US,
|
CWEB_VARG_TYPE_US,
|
||||||
CWEB_VARG_TYPE_UI,
|
CWEB_VARG_TYPE_UI,
|
||||||
CWEB_VARG_TYPE_UL,
|
CWEB_VARG_TYPE_UL,
|
||||||
CWEB_VARG_TYPE_ULL,
|
CWEB_VARG_TYPE_ULL,
|
||||||
CWEB_VARG_TYPE_F,
|
CWEB_VARG_TYPE_F,
|
||||||
CWEB_VARG_TYPE_D,
|
CWEB_VARG_TYPE_D,
|
||||||
CWEB_VARG_TYPE_B,
|
CWEB_VARG_TYPE_B,
|
||||||
CWEB_VARG_TYPE_STR,
|
CWEB_VARG_TYPE_STR,
|
||||||
CWEB_VARG_TYPE_HASH,
|
CWEB_VARG_TYPE_HASH,
|
||||||
CWEB_VARG_TYPE_PC,
|
CWEB_VARG_TYPE_PC,
|
||||||
CWEB_VARG_TYPE_PS,
|
CWEB_VARG_TYPE_PS,
|
||||||
CWEB_VARG_TYPE_PI,
|
CWEB_VARG_TYPE_PI,
|
||||||
CWEB_VARG_TYPE_PL,
|
CWEB_VARG_TYPE_PL,
|
||||||
CWEB_VARG_TYPE_PLL,
|
CWEB_VARG_TYPE_PLL,
|
||||||
CWEB_VARG_TYPE_PSC,
|
CWEB_VARG_TYPE_PSC,
|
||||||
CWEB_VARG_TYPE_PSS,
|
CWEB_VARG_TYPE_PSS,
|
||||||
CWEB_VARG_TYPE_PSI,
|
CWEB_VARG_TYPE_PSI,
|
||||||
CWEB_VARG_TYPE_PSL,
|
CWEB_VARG_TYPE_PSL,
|
||||||
CWEB_VARG_TYPE_PSLL,
|
CWEB_VARG_TYPE_PSLL,
|
||||||
CWEB_VARG_TYPE_PUC,
|
CWEB_VARG_TYPE_PUC,
|
||||||
CWEB_VARG_TYPE_PUS,
|
CWEB_VARG_TYPE_PUS,
|
||||||
CWEB_VARG_TYPE_PUI,
|
CWEB_VARG_TYPE_PUI,
|
||||||
CWEB_VARG_TYPE_PUL,
|
CWEB_VARG_TYPE_PUL,
|
||||||
CWEB_VARG_TYPE_PULL,
|
CWEB_VARG_TYPE_PULL,
|
||||||
CWEB_VARG_TYPE_PF,
|
CWEB_VARG_TYPE_PF,
|
||||||
CWEB_VARG_TYPE_PD,
|
CWEB_VARG_TYPE_PD,
|
||||||
CWEB_VARG_TYPE_PB,
|
CWEB_VARG_TYPE_PB,
|
||||||
CWEB_VARG_TYPE_PSTR,
|
CWEB_VARG_TYPE_PSTR,
|
||||||
CWEB_VARG_TYPE_PHASH,
|
CWEB_VARG_TYPE_PHASH,
|
||||||
} CWEB_VArgType;
|
} CWEB_VArgType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
CWEB_VArgType type;
|
CWEB_VArgType type;
|
||||||
union {
|
union {
|
||||||
char c;
|
char c;
|
||||||
short s;
|
short s;
|
||||||
int i;
|
int i;
|
||||||
long l;
|
long l;
|
||||||
long long ll;
|
long long ll;
|
||||||
signed char sc;
|
signed char sc;
|
||||||
signed short ss;
|
signed short ss;
|
||||||
signed int si;
|
signed int si;
|
||||||
signed long sl;
|
signed long sl;
|
||||||
signed long long sll;
|
signed long long sll;
|
||||||
unsigned char uc;
|
unsigned char uc;
|
||||||
unsigned short us;
|
unsigned short us;
|
||||||
unsigned int ui;
|
unsigned int ui;
|
||||||
unsigned long ul;
|
unsigned long ul;
|
||||||
unsigned long long ull;
|
unsigned long long ull;
|
||||||
float f;
|
float f;
|
||||||
double d;
|
double d;
|
||||||
bool b;
|
bool b;
|
||||||
CWEB_String str;
|
CWEB_String str;
|
||||||
CWEB_PasswordHash hash;
|
CWEB_PasswordHash hash;
|
||||||
char *pc;
|
char *pc;
|
||||||
short *ps;
|
short *ps;
|
||||||
int *pi;
|
int *pi;
|
||||||
long *pl;
|
long *pl;
|
||||||
long long *pll;
|
long long *pll;
|
||||||
signed char *psc;
|
signed char *psc;
|
||||||
signed short *pss;
|
signed short *pss;
|
||||||
signed int *psi;
|
signed int *psi;
|
||||||
signed long *psl;
|
signed long *psl;
|
||||||
signed long long *psll;
|
signed long long *psll;
|
||||||
unsigned char *puc;
|
unsigned char *puc;
|
||||||
unsigned short *pus;
|
unsigned short *pus;
|
||||||
unsigned int *pui;
|
unsigned int *pui;
|
||||||
unsigned long *pul;
|
unsigned long *pul;
|
||||||
unsigned long long *pull;
|
unsigned long long *pull;
|
||||||
float *pf;
|
float *pf;
|
||||||
double *pd;
|
double *pd;
|
||||||
bool *pb;
|
bool *pb;
|
||||||
CWEB_String *pstr;
|
CWEB_String *pstr;
|
||||||
CWEB_PasswordHash *phash;
|
CWEB_PasswordHash *phash;
|
||||||
};
|
};
|
||||||
} CWEB_VArg;
|
} CWEB_VArg;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int len;
|
int len;
|
||||||
CWEB_VArg *ptr;
|
CWEB_VArg *ptr;
|
||||||
} CWEB_VArgs;
|
} CWEB_VArgs;
|
||||||
|
|
||||||
CWEB_VArg cweb_varg_from_c (char c);
|
CWEB_VArg cweb_varg_from_c (char c);
|
||||||
CWEB_VArg cweb_varg_from_s (short s);
|
CWEB_VArg cweb_varg_from_s (short s);
|
||||||
CWEB_VArg cweb_varg_from_i (int i);
|
CWEB_VArg cweb_varg_from_i (int i);
|
||||||
CWEB_VArg cweb_varg_from_l (long l);
|
CWEB_VArg cweb_varg_from_l (long l);
|
||||||
CWEB_VArg cweb_varg_from_ll (long long ll);
|
CWEB_VArg cweb_varg_from_ll (long long ll);
|
||||||
CWEB_VArg cweb_varg_from_sc (char sc);
|
CWEB_VArg cweb_varg_from_sc (char sc);
|
||||||
CWEB_VArg cweb_varg_from_ss (short ss);
|
CWEB_VArg cweb_varg_from_ss (short ss);
|
||||||
CWEB_VArg cweb_varg_from_si (int si);
|
CWEB_VArg cweb_varg_from_si (int si);
|
||||||
CWEB_VArg cweb_varg_from_sl (long sl);
|
CWEB_VArg cweb_varg_from_sl (long sl);
|
||||||
CWEB_VArg cweb_varg_from_sll (long long sll);
|
CWEB_VArg cweb_varg_from_sll (long long sll);
|
||||||
CWEB_VArg cweb_varg_from_uc (char uc);
|
CWEB_VArg cweb_varg_from_uc (char uc);
|
||||||
CWEB_VArg cweb_varg_from_us (short us);
|
CWEB_VArg cweb_varg_from_us (short us);
|
||||||
CWEB_VArg cweb_varg_from_ui (int ui);
|
CWEB_VArg cweb_varg_from_ui (int ui);
|
||||||
CWEB_VArg cweb_varg_from_ul (long ul);
|
CWEB_VArg cweb_varg_from_ul (long ul);
|
||||||
CWEB_VArg cweb_varg_from_ull (long long ull);
|
CWEB_VArg cweb_varg_from_ull (long long ull);
|
||||||
CWEB_VArg cweb_varg_from_f (float f);
|
CWEB_VArg cweb_varg_from_f (float f);
|
||||||
CWEB_VArg cweb_varg_from_d (double d);
|
CWEB_VArg cweb_varg_from_d (double d);
|
||||||
CWEB_VArg cweb_varg_from_b (bool b);
|
CWEB_VArg cweb_varg_from_b (bool b);
|
||||||
CWEB_VArg cweb_varg_from_str (CWEB_String str);
|
CWEB_VArg cweb_varg_from_str (CWEB_String str);
|
||||||
CWEB_VArg cweb_varg_from_hash (CWEB_PasswordHash hash);
|
CWEB_VArg cweb_varg_from_hash (CWEB_PasswordHash hash);
|
||||||
CWEB_VArg cweb_varg_from_pc (char *pc);
|
CWEB_VArg cweb_varg_from_pc (char *pc);
|
||||||
CWEB_VArg cweb_varg_from_ps (short *ps);
|
CWEB_VArg cweb_varg_from_ps (short *ps);
|
||||||
CWEB_VArg cweb_varg_from_pi (int *pi);
|
CWEB_VArg cweb_varg_from_pi (int *pi);
|
||||||
CWEB_VArg cweb_varg_from_pl (long *pl);
|
CWEB_VArg cweb_varg_from_pl (long *pl);
|
||||||
CWEB_VArg cweb_varg_from_pll (long long *pll);
|
CWEB_VArg cweb_varg_from_pll (long long *pll);
|
||||||
CWEB_VArg cweb_varg_from_psc (signed char *psc);
|
CWEB_VArg cweb_varg_from_psc (signed char *psc);
|
||||||
CWEB_VArg cweb_varg_from_pss (signed short *pss);
|
CWEB_VArg cweb_varg_from_pss (signed short *pss);
|
||||||
CWEB_VArg cweb_varg_from_psi (signed int *psi);
|
CWEB_VArg cweb_varg_from_psi (signed int *psi);
|
||||||
CWEB_VArg cweb_varg_from_psl (signed long *psl);
|
CWEB_VArg cweb_varg_from_psl (signed long *psl);
|
||||||
CWEB_VArg cweb_varg_from_psll (signed long long *psll);
|
CWEB_VArg cweb_varg_from_psll (signed long long *psll);
|
||||||
CWEB_VArg cweb_varg_from_puc (unsigned char *puc);
|
CWEB_VArg cweb_varg_from_puc (unsigned char *puc);
|
||||||
CWEB_VArg cweb_varg_from_pus (unsigned short *pus);
|
CWEB_VArg cweb_varg_from_pus (unsigned short *pus);
|
||||||
CWEB_VArg cweb_varg_from_pui (unsigned int *pui);
|
CWEB_VArg cweb_varg_from_pui (unsigned int *pui);
|
||||||
CWEB_VArg cweb_varg_from_pul (unsigned long *pul);
|
CWEB_VArg cweb_varg_from_pul (unsigned long *pul);
|
||||||
CWEB_VArg cweb_varg_from_pull (unsigned long long *pull);
|
CWEB_VArg cweb_varg_from_pull (unsigned long long *pull);
|
||||||
CWEB_VArg cweb_varg_from_pf (float *pf);
|
CWEB_VArg cweb_varg_from_pf (float *pf);
|
||||||
CWEB_VArg cweb_varg_from_pd (double *pd);
|
CWEB_VArg cweb_varg_from_pd (double *pd);
|
||||||
CWEB_VArg cweb_varg_from_pb (bool *pb);
|
CWEB_VArg cweb_varg_from_pb (bool *pb);
|
||||||
CWEB_VArg cweb_varg_from_pstr (CWEB_String *pstr);
|
CWEB_VArg cweb_varg_from_pstr (CWEB_String *pstr);
|
||||||
CWEB_VArg cweb_varg_from_phash(CWEB_PasswordHash *phash);
|
CWEB_VArg cweb_varg_from_phash(CWEB_PasswordHash *phash);
|
||||||
|
|
||||||
#define __CWEB_HELPER_ARG(X) (_Generic((X), \
|
#define __CWEB_HELPER_ARG(X) (_Generic((X), \
|
||||||
char : cweb_varg_from_c, \
|
char : cweb_varg_from_c, \
|
||||||
short : cweb_varg_from_s, \
|
short : cweb_varg_from_s, \
|
||||||
int : cweb_varg_from_i, \
|
int : cweb_varg_from_i, \
|
||||||
long : cweb_varg_from_l, \
|
long : cweb_varg_from_l, \
|
||||||
long long : cweb_varg_from_ll, \
|
long long : cweb_varg_from_ll, \
|
||||||
signed char : cweb_varg_from_sc, \
|
signed char : cweb_varg_from_sc, \
|
||||||
/*signed short : cweb_varg_from_ss,*/ \
|
/*signed short : cweb_varg_from_ss,*/ \
|
||||||
/*signed int : cweb_varg_from_si,*/ \
|
/*signed int : cweb_varg_from_si,*/ \
|
||||||
/*signed long : cweb_varg_from_sl,*/ \
|
/*signed long : cweb_varg_from_sl,*/ \
|
||||||
/*signed long long : cweb_varg_from_sll,*/ \
|
/*signed long long : cweb_varg_from_sll,*/ \
|
||||||
unsigned char : cweb_varg_from_uc, \
|
unsigned char : cweb_varg_from_uc, \
|
||||||
unsigned short : cweb_varg_from_us, \
|
unsigned short : cweb_varg_from_us, \
|
||||||
unsigned int : cweb_varg_from_ui, \
|
unsigned int : cweb_varg_from_ui, \
|
||||||
unsigned long : cweb_varg_from_ul, \
|
unsigned long : cweb_varg_from_ul, \
|
||||||
unsigned long long: cweb_varg_from_ull, \
|
unsigned long long: cweb_varg_from_ull, \
|
||||||
float : cweb_varg_from_f, \
|
float : cweb_varg_from_f, \
|
||||||
double : cweb_varg_from_d, \
|
double : cweb_varg_from_d, \
|
||||||
bool : cweb_varg_from_b, \
|
bool : cweb_varg_from_b, \
|
||||||
CWEB_String : cweb_varg_from_str, \
|
CWEB_String : cweb_varg_from_str, \
|
||||||
CWEB_PasswordHash : cweb_varg_from_hash, \
|
CWEB_PasswordHash : cweb_varg_from_hash, \
|
||||||
char* : cweb_varg_from_pc, \
|
char* : cweb_varg_from_pc, \
|
||||||
short* : cweb_varg_from_ps, \
|
short* : cweb_varg_from_ps, \
|
||||||
int* : cweb_varg_from_pi, \
|
int* : cweb_varg_from_pi, \
|
||||||
long* : cweb_varg_from_pl, \
|
long* : cweb_varg_from_pl, \
|
||||||
long long* : cweb_varg_from_pll, \
|
long long* : cweb_varg_from_pll, \
|
||||||
signed char* : cweb_varg_from_psc, \
|
signed char* : cweb_varg_from_psc, \
|
||||||
/*signed short* : cweb_varg_from_pss,*/ \
|
/*signed short* : cweb_varg_from_pss,*/ \
|
||||||
/*signed int* : cweb_varg_from_psi,*/ \
|
/*signed int* : cweb_varg_from_psi,*/ \
|
||||||
/*signed long* : cweb_varg_from_psl,*/ \
|
/*signed long* : cweb_varg_from_psl,*/ \
|
||||||
/*signed long long* : cweb_varg_from_psll,*/ \
|
/*signed long long* : cweb_varg_from_psll,*/ \
|
||||||
unsigned char* : cweb_varg_from_puc, \
|
unsigned char* : cweb_varg_from_puc, \
|
||||||
unsigned short* : cweb_varg_from_pus, \
|
unsigned short* : cweb_varg_from_pus, \
|
||||||
unsigned int* : cweb_varg_from_pui, \
|
unsigned int* : cweb_varg_from_pui, \
|
||||||
unsigned long* : cweb_varg_from_pul, \
|
unsigned long* : cweb_varg_from_pul, \
|
||||||
unsigned long long*: cweb_varg_from_pull, \
|
unsigned long long*: cweb_varg_from_pull, \
|
||||||
float* : cweb_varg_from_pf, \
|
float* : cweb_varg_from_pf, \
|
||||||
double* : cweb_varg_from_pd, \
|
double* : cweb_varg_from_pd, \
|
||||||
bool* : cweb_varg_from_pb, \
|
bool* : cweb_varg_from_pb, \
|
||||||
CWEB_String* : cweb_varg_from_pstr, \
|
CWEB_String* : cweb_varg_from_pstr, \
|
||||||
CWEB_PasswordHash* : cweb_varg_from_phash \
|
CWEB_PasswordHash* : cweb_varg_from_phash \
|
||||||
))(X)
|
))(X)
|
||||||
|
|
||||||
// Helper macros
|
// Helper macros
|
||||||
#define __CWEB_HELPER_DISPATCH_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N
|
#define __CWEB_HELPER_DISPATCH_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N
|
||||||
#define __CWEB_HELPER_CONCAT_0(A, B) A ## B
|
#define __CWEB_HELPER_CONCAT_0(A, B) A ## B
|
||||||
#define __CWEB_HELPER_CONCAT_1(A, B) __CWEB_HELPER_CONCAT_0(A, B)
|
#define __CWEB_HELPER_CONCAT_1(A, B) __CWEB_HELPER_CONCAT_0(A, B)
|
||||||
#define __CWEB_HELPER_ARGS_0() (CWEB_VArgs) { 0, (CWEB_VArg[]) {}}
|
#define __CWEB_HELPER_ARGS_0() (CWEB_VArgs) { 0, (CWEB_VArg[]) {}}
|
||||||
#define __CWEB_HELPER_ARGS_1(a) (CWEB_VArgs) { 1, (CWEB_VArg[]) { __CWEB_HELPER_ARG(a) }}
|
#define __CWEB_HELPER_ARGS_1(a) (CWEB_VArgs) { 1, (CWEB_VArg[]) { __CWEB_HELPER_ARG(a) }}
|
||||||
#define __CWEB_HELPER_ARGS_2(a, b) (CWEB_VArgs) { 2, (CWEB_VArg[]) { __CWEB_HELPER_ARG(a), __CWEB_HELPER_ARG(b) }}
|
#define __CWEB_HELPER_ARGS_2(a, b) (CWEB_VArgs) { 2, (CWEB_VArg[]) { __CWEB_HELPER_ARG(a), __CWEB_HELPER_ARG(b) }}
|
||||||
#define __CWEB_HELPER_ARGS_3(a, b, c) (CWEB_VArgs) { 3, (CWEB_VArg[]) { __CWEB_HELPER_ARG(a), __CWEB_HELPER_ARG(b), __CWEB_HELPER_ARG(c) }}
|
#define __CWEB_HELPER_ARGS_3(a, b, c) (CWEB_VArgs) { 3, (CWEB_VArg[]) { __CWEB_HELPER_ARG(a), __CWEB_HELPER_ARG(b), __CWEB_HELPER_ARG(c) }}
|
||||||
#define __CWEB_HELPER_ARGS_4(a, b, c, d) (CWEB_VArgs) { 4, (CWEB_VArg[]) { __CWEB_HELPER_ARG(a), __CWEB_HELPER_ARG(b), __CWEB_HELPER_ARG(c), __CWEB_HELPER_ARG(d) }}
|
#define __CWEB_HELPER_ARGS_4(a, b, c, d) (CWEB_VArgs) { 4, (CWEB_VArg[]) { __CWEB_HELPER_ARG(a), __CWEB_HELPER_ARG(b), __CWEB_HELPER_ARG(c), __CWEB_HELPER_ARG(d) }}
|
||||||
#define __CWEB_HELPER_ARGS_5(a, b, c, d, e) (CWEB_VArgs) { 5, (CWEB_VArg[]) { __CWEB_HELPER_ARG(a), __CWEB_HELPER_ARG(b), __CWEB_HELPER_ARG(c), __CWEB_HELPER_ARG(d), __CWEB_HELPER_ARG(e) }}
|
#define __CWEB_HELPER_ARGS_5(a, b, c, d, e) (CWEB_VArgs) { 5, (CWEB_VArg[]) { __CWEB_HELPER_ARG(a), __CWEB_HELPER_ARG(b), __CWEB_HELPER_ARG(c), __CWEB_HELPER_ARG(d), __CWEB_HELPER_ARG(e) }}
|
||||||
#define __CWEB_HELPER_ARGS_6(a, b, c, d, e, f) (CWEB_VArgs) { 6, (CWEB_VArg[]) { __CWEB_HELPER_ARG(a), __CWEB_HELPER_ARG(b), __CWEB_HELPER_ARG(c), __CWEB_HELPER_ARG(d), __CWEB_HELPER_ARG(e), __CWEB_HELPER_ARG(f) }}
|
#define __CWEB_HELPER_ARGS_6(a, b, c, d, e, f) (CWEB_VArgs) { 6, (CWEB_VArg[]) { __CWEB_HELPER_ARG(a), __CWEB_HELPER_ARG(b), __CWEB_HELPER_ARG(c), __CWEB_HELPER_ARG(d), __CWEB_HELPER_ARG(e), __CWEB_HELPER_ARG(f) }}
|
||||||
#define __CWEB_HELPER_ARGS_7(a, b, c, d, e, f, g) (CWEB_VArgs) { 7, (CWEB_VArg[]) { __CWEB_HELPER_ARG(a), __CWEB_HELPER_ARG(b), __CWEB_HELPER_ARG(c), __CWEB_HELPER_ARG(d), __CWEB_HELPER_ARG(e), __CWEB_HELPER_ARG(f), __CWEB_HELPER_ARG(g) }}
|
#define __CWEB_HELPER_ARGS_7(a, b, c, d, e, f, g) (CWEB_VArgs) { 7, (CWEB_VArg[]) { __CWEB_HELPER_ARG(a), __CWEB_HELPER_ARG(b), __CWEB_HELPER_ARG(c), __CWEB_HELPER_ARG(d), __CWEB_HELPER_ARG(e), __CWEB_HELPER_ARG(f), __CWEB_HELPER_ARG(g) }}
|
||||||
#define __CWEB_HELPER_ARGS_8(a, b, c, d, e, f, g, h) (CWEB_VArgs) { 8, (CWEB_VArg[]) { __CWEB_HELPER_ARG(a), __CWEB_HELPER_ARG(b), __CWEB_HELPER_ARG(c), __CWEB_HELPER_ARG(d), __CWEB_HELPER_ARG(e), __CWEB_HELPER_ARG(f), __CWEB_HELPER_ARG(g), __CWEB_HELPER_ARG(h) }}
|
#define __CWEB_HELPER_ARGS_8(a, b, c, d, e, f, g, h) (CWEB_VArgs) { 8, (CWEB_VArg[]) { __CWEB_HELPER_ARG(a), __CWEB_HELPER_ARG(b), __CWEB_HELPER_ARG(c), __CWEB_HELPER_ARG(d), __CWEB_HELPER_ARG(e), __CWEB_HELPER_ARG(f), __CWEB_HELPER_ARG(g), __CWEB_HELPER_ARG(h) }}
|
||||||
#define __CWEB_COUNT_ARGS(...) __CWEB_HELPER_DISPATCH_N(DUMMY, ##__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
#define __CWEB_COUNT_ARGS(...) __CWEB_HELPER_DISPATCH_N(DUMMY, ##__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||||
|
|
||||||
#define CWEB_VARGS(...) __CWEB_HELPER_CONCAT_1(__CWEB_HELPER_ARGS_, __CWEB_COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__)
|
#define CWEB_VARGS(...) __CWEB_HELPER_CONCAT_1(__CWEB_HELPER_ARGS_, __CWEB_COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__)
|
||||||
|
|
||||||
typedef struct CWEB CWEB;
|
typedef struct CWEB CWEB;
|
||||||
typedef struct CWEB_Request CWEB_Request;
|
typedef struct CWEB_Request CWEB_Request;
|
||||||
|
|
||||||
int cweb_global_init(void);
|
int cweb_global_init(void);
|
||||||
void cweb_global_free(void);
|
void cweb_global_free(void);
|
||||||
|
|
||||||
CWEB *cweb_init(CWEB_String addr, uint16_t port);
|
CWEB *cweb_init(CWEB_String addr, uint16_t port);
|
||||||
void cweb_free(CWEB *cweb);
|
void cweb_free(CWEB *cweb);
|
||||||
|
|
||||||
// Open an SQLite instance in file "database_file" and run the DDL script at "schema_file".
|
// Open an SQLite instance in file "database_file" and run the DDL script at "schema_file".
|
||||||
// Note that "database_file" may be ":memory:".
|
// Note that "database_file" may be ":memory:".
|
||||||
int cweb_enable_database(CWEB *cweb, CWEB_String database_file, CWEB_String schema_file);
|
int cweb_enable_database(CWEB *cweb, CWEB_String database_file, CWEB_String schema_file);
|
||||||
|
|
||||||
// Log all evaluated SQL statements to stdout
|
// Log all evaluated SQL statements to stdout
|
||||||
void cweb_trace_sql(CWEB *cweb, bool enable);
|
void cweb_trace_sql(CWEB *cweb, bool enable);
|
||||||
|
|
||||||
// TODO: comment
|
// TODO: comment
|
||||||
void cweb_enable_template_cache(CWEB *cweb, bool enable);
|
void cweb_enable_template_cache(CWEB *cweb, bool enable);
|
||||||
|
|
||||||
// Pause execution until a request is available.
|
// Pause execution until a request is available.
|
||||||
// TODO: When does this function return NULL?
|
// TODO: When does this function return NULL?
|
||||||
CWEB_Request *cweb_wait(CWEB *cweb);
|
CWEB_Request *cweb_wait(CWEB *cweb);
|
||||||
|
|
||||||
// Returns true iff the request matches the specified endpoint
|
// Returns true iff the request matches the specified endpoint
|
||||||
bool cweb_match_endpoint(CWEB_Request *req, CWEB_String str);
|
bool cweb_match_endpoint(CWEB_Request *req, CWEB_String str);
|
||||||
|
|
||||||
// Returns the CSRF token associated to the current session
|
// Returns the CSRF token associated to the current session
|
||||||
CWEB_String cweb_get_csrf(CWEB_Request *req);
|
CWEB_String cweb_get_csrf(CWEB_Request *req);
|
||||||
|
|
||||||
// Returns the user ID for the current session, or -1 if there is no session
|
// Returns the user ID for the current session, or -1 if there is no session
|
||||||
int cweb_get_user_id(CWEB_Request *req);
|
int cweb_get_user_id(CWEB_Request *req);
|
||||||
|
|
||||||
// Sets the user ID for the current session (it must be a positive integer).
|
// Sets the user ID for the current session (it must be a positive integer).
|
||||||
// If the ID is -1, the session is deleted.
|
// If the ID is -1, the session is deleted.
|
||||||
int cweb_set_user_id(CWEB_Request *req, int user_id);
|
int cweb_set_user_id(CWEB_Request *req, int user_id);
|
||||||
|
|
||||||
// TODO: comment
|
// TODO: comment
|
||||||
CWEB_String cweb_get_path(CWEB_Request *req);
|
CWEB_String cweb_get_path(CWEB_Request *req);
|
||||||
|
|
||||||
// Returns the request parameter with the specified name
|
// Returns the request parameter with the specified name
|
||||||
// If the request uses POST, the parameter is taken from the body,
|
// If the request uses POST, the parameter is taken from the body,
|
||||||
// else it's taken from the URL. If the parameter is not present,
|
// else it's taken from the URL. If the parameter is not present,
|
||||||
// an empty string is returned.
|
// an empty string is returned.
|
||||||
CWEB_String cweb_get_param_s(CWEB_Request *req, CWEB_String name);
|
CWEB_String cweb_get_param_s(CWEB_Request *req, CWEB_String name);
|
||||||
|
|
||||||
// Like cweb_get_param_s, but also parser the argument as an integer.
|
// Like cweb_get_param_s, but also parser the argument as an integer.
|
||||||
// If parsing fails or the parameter is missing, -1 is returned.
|
// If parsing fails or the parameter is missing, -1 is returned.
|
||||||
int cweb_get_param_i(CWEB_Request *req, CWEB_String name);
|
int cweb_get_param_i(CWEB_Request *req, CWEB_String name);
|
||||||
|
|
||||||
// Create a string by evaluating a format. Memory is allocated from the arena of the request.
|
// Create a string by evaluating a format. Memory is allocated from the arena of the request.
|
||||||
// If the arena is full, an empty string is returned.
|
// If the arena is full, an empty string is returned.
|
||||||
CWEB_String cweb_format_impl(CWEB_Request *req, char *fmt, CWEB_VArgs args);
|
CWEB_String cweb_format_impl(CWEB_Request *req, char *fmt, CWEB_VArgs args);
|
||||||
|
|
||||||
// Helper
|
// Helper
|
||||||
#define cweb_format(req, fmt, ...) cweb_format_impl((req), (fmt), CWEB_VARGS(__VA_ARGS__))
|
#define cweb_format(req, fmt, ...) cweb_format_impl((req), (fmt), CWEB_VARGS(__VA_ARGS__))
|
||||||
|
|
||||||
// Responds to the specified request with the given status code and content
|
// Responds to the specified request with the given status code and content
|
||||||
void cweb_respond_basic(CWEB_Request *req, int status, CWEB_String content);
|
void cweb_respond_basic(CWEB_Request *req, int status, CWEB_String content);
|
||||||
|
|
||||||
// Responds to the request by redirecting the client to the given target
|
// Responds to the request by redirecting the client to the given target
|
||||||
void cweb_respond_redirect(CWEB_Request *req, CWEB_String target);
|
void cweb_respond_redirect(CWEB_Request *req, CWEB_String target);
|
||||||
|
|
||||||
// Responds to the request by evaluating a WL template file
|
// Responds to the request by evaluating a WL template file
|
||||||
void cweb_respond_template_impl(CWEB_Request *req, int status, CWEB_String template_file, CWEB_VArgs args);
|
void cweb_respond_template_impl(CWEB_Request *req, int status, CWEB_String template_file, CWEB_VArgs args);
|
||||||
|
|
||||||
// Helper
|
// Helper
|
||||||
#define cweb_respond_template(req, status, template_file, ...) \
|
#define cweb_respond_template(req, status, template_file, ...) \
|
||||||
cweb_respond_template_impl((req), (status), (template_file), CWEB_VARGS(__VA_ARGS__))
|
cweb_respond_template_impl((req), (status), (template_file), CWEB_VARGS(__VA_ARGS__))
|
||||||
|
|
||||||
// Evaluates an SQL INSERT statement and returns the ID of the last inserted row. On error -1 is returned
|
// Evaluates an SQL INSERT statement and returns the ID of the last inserted row. On error -1 is returned
|
||||||
int64_t cweb_database_insert_impl(CWEB *cweb, char *fmt, CWEB_VArgs args);
|
int64_t cweb_database_insert_impl(CWEB *cweb, char *fmt, CWEB_VArgs args);
|
||||||
|
|
||||||
// Helper
|
// Helper
|
||||||
#define cweb_database_insert(cweb, fmt, ...) \
|
#define cweb_database_insert(cweb, fmt, ...) \
|
||||||
cweb_database_insert_impl((cweb), (fmt), CWEB_VARGS(__VA_ARGS__))
|
cweb_database_insert_impl((cweb), (fmt), CWEB_VARGS(__VA_ARGS__))
|
||||||
|
|
||||||
// Iterator over database rows
|
// Iterator over database rows
|
||||||
typedef struct { void *handle; } CWEB_QueryResult;
|
typedef struct { void *handle; } CWEB_QueryResult;
|
||||||
|
|
||||||
// Evaluates an SQL SELECT statement, returning a scanner over the returned rows.
|
// Evaluates an SQL SELECT statement, returning a scanner over the returned rows.
|
||||||
// You don't have to check for errors with this function
|
// You don't have to check for errors with this function
|
||||||
CWEB_QueryResult cweb_database_select_impl(CWEB *cweb, char *fmt, CWEB_VArgs args);
|
CWEB_QueryResult cweb_database_select_impl(CWEB *cweb, char *fmt, CWEB_VArgs args);
|
||||||
|
|
||||||
// Helper
|
// Helper
|
||||||
#define cweb_database_select(cweb, fmt, ...) cweb_database_select_impl((cweb), (fmt), CWEB_VARGS(__VA_ARGS__))
|
#define cweb_database_select(cweb, fmt, ...) cweb_database_select_impl((cweb), (fmt), CWEB_VARGS(__VA_ARGS__))
|
||||||
|
|
||||||
// Returns the next row from the query result iterator.
|
// Returns the next row from the query result iterator.
|
||||||
int cweb_next_query_row_impl(CWEB_QueryResult *res, CWEB_VArgs args);
|
int cweb_next_query_row_impl(CWEB_QueryResult *res, CWEB_VArgs args);
|
||||||
|
|
||||||
// Helper
|
// Helper
|
||||||
#define cweb_next_query_row(res, ...) cweb_next_query_row_impl((res), CWEB_VARGS(__VA_ARGS__))
|
#define cweb_next_query_row(res, ...) cweb_next_query_row_impl((res), CWEB_VARGS(__VA_ARGS__))
|
||||||
|
|
||||||
// Frees the result of a database query
|
// Frees the result of a database query
|
||||||
void cweb_free_query_result(CWEB_QueryResult *res);
|
void cweb_free_query_result(CWEB_QueryResult *res);
|
||||||
|
|
||||||
// Calculates the bcrypt hash of the specified password
|
// Calculates the bcrypt hash of the specified password
|
||||||
int cweb_hash_password(CWEB_String pass, int cost, CWEB_PasswordHash *hash);
|
int cweb_hash_password(CWEB_String pass, int cost, CWEB_PasswordHash *hash);
|
||||||
|
|
||||||
// Checks whether the password matches the given hash
|
// Checks whether the password matches the given hash
|
||||||
int cweb_check_password(CWEB_String pass, CWEB_PasswordHash hash);
|
int cweb_check_password(CWEB_String pass, CWEB_PasswordHash hash);
|
||||||
|
|||||||
Reference in New Issue
Block a user