From 10ddc97d221989e107c5283e3d5df8c48a23dc26 Mon Sep 17 00:00:00 2001 From: ame Date: Fri, 1 Aug 2025 14:20:08 -0500 Subject: write file, and code should be an int --- src/lua.c | 2 +- src/net.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lua.c b/src/lua.c index 4fe9962..3d35858 100644 --- a/src/lua.c +++ b/src/lua.c @@ -73,7 +73,7 @@ int _stream_file(lua_State* L){ const char* filename = lua_tostring(L, 2); FILE *f; - f = fopen(filename, "a"); + f = fopen(filename, "w"); if(f == NULL){ luaI_error(L, -1, "unable to open file"); } diff --git a/src/net.c b/src/net.c index a6f3bf4..70400a2 100644 --- a/src/net.c +++ b/src/net.c @@ -590,6 +590,11 @@ int l_srequest(lua_State* L){ luaI_treplk(L, idx, "Path", "code"); luaI_treplk(L, idx, "Request", "version"); luaI_treplk(L, idx, "Version", "code-name"); + + lua_pushstring(L, "code"); + lua_gettable(L, idx); + int code = atoi(lua_tostring(L, -1)); + luaI_tseti(L, idx, "code", code); void* encoding = parray_get(owo, "Transfer-Encoding"); -- cgit v1.2.3 From 19afaa2feedaa6ec1e1774174ce752e7f2583484 Mon Sep 17 00:00:00 2001 From: ame Date: Fri, 1 Aug 2025 14:25:07 -0500 Subject: change stream modes --- src/lua.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lua.c b/src/lua.c index 3d35858..ef3c032 100644 --- a/src/lua.c +++ b/src/lua.c @@ -59,10 +59,15 @@ int _stream_file(lua_State* L){ const int CHUNK_SIZE = 4096; uint64_t maxlen = 0; uint64_t totallen = 0; + const char* mode = "w"; if(lua_gettop(L) > 2){ maxlen = lua_tointeger(L, 3); } + if(lua_gettop(L) > 3){ + mode = lua_tostring(L, 4); + } + lua_pushstring(L, "_read"); lua_gettable(L, 1); stream_read_function rf = lua_touserdata(L, -1); @@ -73,7 +78,7 @@ int _stream_file(lua_State* L){ const char* filename = lua_tostring(L, 2); FILE *f; - f = fopen(filename, "w"); + f = fopen(filename, mode); if(f == NULL){ luaI_error(L, -1, "unable to open file"); } -- cgit v1.2.3 From 9ee19b1e0af44f48f39bd6ce57a0cb85eb1147ad Mon Sep 17 00:00:00 2001 From: ame Date: Fri, 1 Aug 2025 18:00:47 -0500 Subject: length should include host --- src/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/net.c b/src/net.c index 70400a2..9af82f7 100644 --- a/src/net.c +++ b/src/net.c @@ -545,7 +545,7 @@ int l_srequest(lua_State* L){ //char* req = "GET / HTTP/1.1\nHost: amyy.cc\nConnection: Close\n\n"; - char* request = calloc(cont_len + header->len + 512, sizeof * request); + char* request = calloc(cont_len + header->len + strlen(host) + strlen(path) + 512, sizeof * request); sprintf(request, "%s %s HTTP/1.1\r\nHost: %s\r\nConnection: Close%s\r\n\r\n%s", action, path, host, header->c, cont); //printf("%s\n", request); str_free(header); -- cgit v1.2.3 From 6b0cda77a3e04e4fb3024b21bb648b6bf9f62568 Mon Sep 17 00:00:00 2001 From: ame Date: Fri, 1 Aug 2025 19:27:34 -0500 Subject: send user-agent --- src/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/net.c b/src/net.c index 9af82f7..b5b75bf 100644 --- a/src/net.c +++ b/src/net.c @@ -546,7 +546,7 @@ int l_srequest(lua_State* L){ //char* req = "GET / HTTP/1.1\nHost: amyy.cc\nConnection: Close\n\n"; char* request = calloc(cont_len + header->len + strlen(host) + strlen(path) + 512, sizeof * request); - sprintf(request, "%s %s HTTP/1.1\r\nHost: %s\r\nConnection: Close%s\r\n\r\n%s", action, path, host, header->c, cont); + sprintf(request, "%s %s HTTP/1.1\r\nUser-Agent: lullaby/"MAJOR_VERSION"\r\nHost: %s\r\nConnection: Close%s\r\n\r\n%s", action, path, host, header->c, cont); //printf("%s\n", request); str_free(header); -- cgit v1.2.3 From cd1c124e2def659dd2919e4387047de733afcc59 Mon Sep 17 00:00:00 2001 From: ame Date: Fri, 1 Aug 2025 21:27:11 -0500 Subject: make user-agent editable with default header values --- src/lua.c | 12 +++++++----- src/lua.h | 2 ++ src/net.c | 46 ++++++++++++++++++++++++---------------------- 3 files changed, 33 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/lua.c b/src/lua.c index ef3c032..e138f77 100644 --- a/src/lua.c +++ b/src/lua.c @@ -374,19 +374,21 @@ int env_table(lua_State* L, int provide_table){ return 1; } -//top table is prioritized -void luaI_jointable(lua_State* L){ - int idx = lua_gettop(L) - 1; +//main is the default values, merge is the new and overridden ones +void luaI_jointable(lua_State* L, int main, int merge){ + int idx = lua_gettop(L); + + lua_pushvalue(L, merge); lua_pushnil(L); for(;lua_next(L, -2) != 0;){ lua_pushvalue(L, -2); lua_pushvalue(L, -2); - lua_settable(L, idx); + lua_settable(L, main); lua_pop(L, 1); } - lua_pushvalue(L, idx); + lua_settop(L, idx); } //copys all variables from state A to B, including locals (stored in _locals) diff --git a/src/lua.h b/src/lua.h index 2e7aa5e..db58862 100644 --- a/src/lua.h +++ b/src/lua.h @@ -38,6 +38,8 @@ typedef int (*stream_free_function)(void**); void luaI_newstream(lua_State* L, stream_read_function, stream_free_function, void*); int luaI_nothing(lua_State*); +void luaI_jointable(lua_State* L, int main, int merge); + //generic macro that takes other macros (see below) #define _tset_b(L, Tidx, K, V, F)\ diff --git a/src/net.c b/src/net.c index b5b75bf..34e20c0 100644 --- a/src/net.c +++ b/src/net.c @@ -484,7 +484,6 @@ int _srequest_chunked_encoding(char* input, int length, struct chunked_encoding_ int l_srequest(lua_State* L){ int params = lua_gettop(L); - int check = 1; uint64_t ilen = 0; char* request_url = (char*)lua_tolstring(L, 1, &ilen); struct url awa = parse_url(request_url, ilen); @@ -510,12 +509,11 @@ int l_srequest(lua_State* L){ char* cont = ""; size_t cont_len = 0; - if(params >= check + 1){ - check++; - switch(lua_type(L, check)){ + if(params >= 2){ + switch(lua_type(L, 2)){ case LUA_TNUMBER: case LUA_TSTRING: - cont = (char*)luaL_tolstring(L, check, &cont_len); + cont = (char*)luaL_tolstring(L, 2, &cont_len); break; default: p_fatal("cant send type"); @@ -523,31 +521,35 @@ int l_srequest(lua_State* L){ } } - str* header = str_init(""); - if(params >= check + 1){ - check++; - lua_pushnil(L); - - for(;lua_next(L, check) != 0;){ - str_push(header, "\r\n"); - str_push(header, lua_tostring(L, -2)); - str_push(header, ": "); - str_push(header, lua_tostring(L, -1)); - lua_pop(L, 1); - } + lua_newtable(L); + int header_idx = lua_gettop(L); + luaI_tsets(L, header_idx, "User-Agent", "lullaby/"MAJOR_VERSION); + + if(params >= 3){ + luaI_jointable(L, header_idx, 3); } + + str* header = str_init(""); + lua_pushnil(L); + + for(;lua_next(L, header_idx) != 0;){ + str_push(header, "\r\n"); + str_push(header, lua_tostring(L, -2)); + str_push(header, ": "); + str_push(header, lua_tostring(L, -1)); + lua_pop(L, 1); + } char* action = "GET"; - if(params >= check + 1){ - check++; - action = (char*)lua_tostring(L, check); + if(params >= 4){ + action = (char*)lua_tostring(L, 4); } //char* req = "GET / HTTP/1.1\nHost: amyy.cc\nConnection: Close\n\n"; char* request = calloc(cont_len + header->len + strlen(host) + strlen(path) + 512, sizeof * request); - sprintf(request, "%s %s HTTP/1.1\r\nUser-Agent: lullaby/"MAJOR_VERSION"\r\nHost: %s\r\nConnection: Close%s\r\n\r\n%s", action, path, host, header->c, cont); - //printf("%s\n", request); + sprintf(request, "%s %s HTTP/1.1\r\nHost: %s\r\nConnection: Close%s\r\n\r\n%s", action, path, host, header->c, cont); + str_free(header); int s = SSL_write(ssl, request, strlen(request)); -- cgit v1.2.3 From 0f2fb182199bf0c7e8d996400b82b2dd2b2463df Mon Sep 17 00:00:00 2001 From: ame Date: Sat, 2 Aug 2025 04:23:14 -0500 Subject: l_request, http support --- src/net.c | 143 ++++++++++++++++++++++++++++++++++---------------------------- src/net.h | 2 +- 2 files changed, 80 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/net.c b/src/net.c index 34e20c0..04fd5a1 100644 --- a/src/net.c +++ b/src/net.c @@ -389,20 +389,27 @@ int l_wss(lua_State* L){ return 1; } -struct _srequest_state { +struct request_state { SSL* ssl; SSL_CTX* ctx; int sock; + int secure; str* buffer; //anything pre-existing struct chunked_encoding_state* state; }; +ssize_t _request_read(struct request_state* state, void* buffer, size_t count); + int _srequest_free(void** _state){ - struct _srequest_state* state = *((struct _srequest_state**)_state); - SSL_set_shutdown(state->ssl, SSL_RECEIVED_SHUTDOWN | SSL_SENT_SHUTDOWN); - SSL_shutdown(state->ssl); - SSL_free(state->ssl); - SSL_CTX_free(state->ctx); + struct request_state* state = *((struct request_state**)_state); + + if(state->secure){ + SSL_set_shutdown(state->ssl, SSL_RECEIVED_SHUTDOWN | SSL_SENT_SHUTDOWN); + SSL_shutdown(state->ssl); + SSL_free(state->ssl); + SSL_CTX_free(state->ctx); + } + close(state->sock); if(state->state != NULL){ @@ -419,7 +426,7 @@ int _srequest_free(void** _state){ } int _srequest_read(uint64_t reqlen, str** _output, void** _state){ - struct _srequest_state* state = *((struct _srequest_state**)_state); + struct request_state* state = *((struct request_state**)_state); str* output = *_output; //states using chunked encoding should skip this if(state->buffer != NULL){ @@ -431,7 +438,7 @@ int _srequest_read(uint64_t reqlen, str** _output, void** _state){ char buffer[BUFFER_LEN]; memset(buffer, 0, BUFFER_LEN); uint64_t len; - for(; (len = SSL_read(state->ssl, buffer, BUFFER_LEN)) > 0;){ + for(; (len = _request_read(state, buffer, BUFFER_LEN)) > 0;){ if(state->state != NULL){ chunked_encoding_round(buffer, len, state->state); } else { @@ -481,31 +488,67 @@ int _srequest_chunked_encoding(char* input, int length, struct chunked_encoding_ return 0; } +int _request(lua_State* L, struct request_state* state); + int l_srequest(lua_State* L){ + struct request_state* state = calloc(sizeof * state, 1); + state->secure = 1; + + return _request(L, state); +} + +int l_request(lua_State* L){ + struct request_state* state = calloc(sizeof * state, 1); + state->secure = 0; + + return _request(L, state); +} + +ssize_t _request_read(struct request_state* state, void* buffer, size_t count){ + if(state->secure){ + return SSL_read(state->ssl, buffer, count); + } else { + return read(state->sock, buffer, count); + } +} + +ssize_t _request_write(struct request_state* state, const void* buffer, size_t count){ + if(state->secure){ + return SSL_write(state->ssl, buffer, count); + } else { + return write(state->sock, buffer, count); + } +} + +int _request(lua_State* L, struct request_state* state){ int params = lua_gettop(L); uint64_t ilen = 0; char* request_url = (char*)lua_tolstring(L, 1, &ilen); struct url awa = parse_url(request_url, ilen); if(awa.proto != NULL && strcmp(awa.proto->c, "http") == 0){ - //send to l_request, todo - abort(); + state->secure = 0; + } else if (awa.proto != NULL && strcmp(awa.proto->c, "https") == 0){ + state->secure = 1; } + const char* host = awa.domain == NULL ? request_url : awa.domain->c; - const char* port = awa.port == NULL ? "443" : awa.port->c; + const char* port = awa.port == NULL ? + (state->secure ? "443" : "80") + : awa.port->c; char* path = awa.path == NULL ? "/" : awa.path->c; - int sock = get_host((char*)host, (char*)port); - if(sock == -1){ - //p_fatal("could not resolve address"); - //abort(); + state->sock = get_host((char*)host, (char*)port); + if(state->sock == -1){ luaI_error(L, -1, "error resolving address"); } - ssl_init(); - SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method()); - SSL* ssl = ssl_connect(ctx, sock, host); - if(ssl == NULL) luaI_error(L, -1, "ssl_connect error"); + if(state->secure){ + ssl_init(); + state->ctx = SSL_CTX_new(SSLv23_client_method()); + state->ssl = ssl_connect(state->ctx, state->sock, host); + if(state->ssl == NULL) luaI_error(L, -1, "ssl_connect error"); + } char* cont = ""; size_t cont_len = 0; @@ -552,10 +595,10 @@ int l_srequest(lua_State* L){ str_free(header); - int s = SSL_write(ssl, request, strlen(request)); + int s = _request_write(state, request, strlen(request)); free(request); - if(s <= 0) luaI_error(L, s, "SSL_write error"); + if(s <= 0) luaI_error(L, s, "_request_write error"); str* a = str_init(""); char buffer[BUFFER_LEN]; @@ -563,7 +606,7 @@ int l_srequest(lua_State* L){ int extra_len = 0; char* header_eof = NULL; - for(; (len = SSL_read(ssl, buffer, BUFFER_LEN)) > 0;){ + for(; (len = _request_read(state, buffer, BUFFER_LEN)) > 0;){ int blen = a->len; str_pushl(a, buffer, len); int offset = blen >= 4 ? 4 : blen; @@ -574,7 +617,7 @@ int l_srequest(lua_State* L){ memset(buffer, 0, BUFFER_LEN); } - if(len < 0) luaI_error(L, len, "SSL_read error"); + if(len < 0) luaI_error(L, len, "read error"); if(header_eof != NULL){ lua_newtable(L); @@ -600,29 +643,29 @@ int l_srequest(lua_State* L){ void* encoding = parray_get(owo, "Transfer-Encoding"); - struct _srequest_state *read_state = calloc(sizeof * read_state, 1); - read_state->ctx = ctx; - read_state->ssl = ssl; - read_state->sock = sock; + //struct _srequest_state *read_state = calloc(sizeof * read_state, 1); + //read_state->ctx = state->ctx; + //read_state->ssl = state->ssl; + //read_state->sock = state->sock; if(encoding != NULL){ if(strcmp(((str*)encoding)->c, "chunked") == 0){ - struct chunked_encoding_state* state = calloc(sizeof * state, 1); - state->reading_length = 1; - state->buffer = str_init(""); - state->content = str_init(""); + struct chunked_encoding_state* chunk_state = calloc(sizeof * state, 1); + chunk_state->reading_length = 1; + chunk_state->buffer = str_init(""); + chunk_state->content = str_init(""); - chunked_encoding_round(header_eof + 4, extra_len - 4, state); + chunked_encoding_round(header_eof + 4, extra_len - 4, chunk_state); memset(buffer, 0, BUFFER_LEN); - read_state->buffer = str_init(""); - read_state->state = state; + state->buffer = str_init(""); + state->state = chunk_state; } } else { - read_state->buffer = str_initl(header_eof + 4, extra_len - 4); + state->buffer = str_initl(header_eof + 4, extra_len - 4); } parray_clear(owo, STR); - luaI_newstream(L, _srequest_read, _srequest_free, read_state); + luaI_newstream(L, _srequest_read, _srequest_free, state); int v = lua_gettop(L); luaI_tsetv(L, idx, "content", v); lua_pushvalue(L, idx); @@ -640,34 +683,6 @@ int l_srequest(lua_State* L){ return 1; } -int l_request(lua_State* L){ - const char* host = luaL_checkstring(L, 1); - int sock = get_host((char*)host, (char*)lua_tostring(L, 2)); - - char* path = "/"; - if(lua_gettop(L) >= 3) - path = (char*)luaL_checkstring(L, 3); - - //char* req = "GET / HTTP/1.1\nHost: amyy.cc\nConnection: Close\n\n"; - - char request[2000]; - sprintf(request, "GET %s HTTP/1.1\nHost: %s\nConnection: Close\n\n", path, host); - write(sock, request, strlen(request)); - - str* a = str_init(""); - char buffer[512]; - int len = 0; - - for(; (len = read(sock, buffer, 511)) != 0;){ - str_pushl(a, buffer, len); - memset(buffer, 0, 512); - } - - lua_pushstring(L, a->c); - - return 1; -} - #define max_uri_size 2048 _Atomic size_t threads = 0; diff --git a/src/net.h b/src/net.h index f7e5d64..cfc2009 100644 --- a/src/net.h +++ b/src/net.h @@ -45,7 +45,7 @@ int clean_lullaby_net(lua_State* L); static const luaL_Reg net_function_list [] = { {"listen",l_listen}, - //{"request",l_request}, + {"request",l_request}, {"srequest",l_srequest}, {"wss",l_wss}, -- cgit v1.2.3 From 05cd214e8d4a4a3f560327f414a82d388cfe6755 Mon Sep 17 00:00:00 2001 From: ame Date: Tue, 5 Aug 2025 03:45:01 -0500 Subject: skip empty chunks --- src/net.c | 35 ++--------------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/net.c b/src/net.c index 04fd5a1..a21579c 100644 --- a/src/net.c +++ b/src/net.c @@ -97,7 +97,8 @@ int chunked_encoding_round(char* input, int length, struct chunked_encoding_stat str_popb(state->buffer, 2); state->chunk_length = strtoll(state->buffer->c, NULL, 16); str_clear(state->buffer); - state->reading_length = 0; + if(state->chunk_length != 0) + state->reading_length = 0; } } else { int len = lesser(state->chunk_length - state->buffer->len, length - i); @@ -456,38 +457,6 @@ int _srequest_read(uint64_t reqlen, str** _output, void** _state){ return 1; } -int _srequest_chunked_encoding(char* input, int length, struct chunked_encoding_state* state){ - //printf("'%s'\n", input); - for(int i = 0; i < length; i++){ - //printf("%i/%i\n", i, length); - if(state->reading_length){ - str_pushl(state->buffer, input + i, 1); - - if(state->buffer->len >= 2 && memmem(state->buffer->c + state->buffer->len - 2, 2, "\r\n", 2)){ - - str_popb(state->buffer, 2); - state->chunk_length = strtoll(state->buffer->c, NULL, 16); - str_clear(state->buffer); - state->reading_length = 0; - } - } else { - int len = lesser(state->chunk_length - state->buffer->len, length - i); - str_pushl(state->buffer, input + i, len); - i += len; - - if(state->buffer->len >= state->chunk_length){ - state->reading_length = 1; - str_pushl(state->content, state->buffer->c, state->buffer->len); - str_clear(state->buffer); - } - } - } - - //printf("buffer '%s'\n", state->buffer->c); - - return 0; -} - int _request(lua_State* L, struct request_state* state); int l_srequest(lua_State* L){ -- cgit v1.2.3 From ce33e309ad9dd3321e42ae623ac12fd739957259 Mon Sep 17 00:00:00 2001 From: ame Date: Tue, 5 Aug 2025 15:07:31 -0500 Subject: add length after check, duh --- src/net/util.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/net/util.c b/src/net/util.c index 3e91c7c..b41f0ed 100644 --- a/src/net/util.c +++ b/src/net/util.c @@ -16,16 +16,16 @@ int64_t recv_header(int client_fd, char** _buffer, char** header_eof){ return -1; } - if((len += n) >= MAX_HEADER_SIZE){ - return -2; - } - // search the last 4 characters too if they exist // this could probably be changed to 3 - int64_t start_len = len - 4 > 0 ? len - 4 : 0; + int64_t start_len = len - 4 > 0 ? len - 4 : len; int64_t search_end = len - 4 > 0 ? n + 4 : n; if((*header_eof = memmem(buffer + start_len, search_end, "\r\n\r\n", 4)) != NULL){ - return len; + return len + n; + } + + if((len += n) >= MAX_HEADER_SIZE){ + return -2; } buffer = realloc(buffer, sizeof* buffer * (len + BUFFER_SIZE + 1)); -- cgit v1.2.3 From 7cc8cade712506c7eeaf3a8e0002cf2313218885 Mon Sep 17 00:00:00 2001 From: ame Date: Fri, 8 Aug 2025 20:36:01 -0500 Subject: free cookie from header table --- src/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/net.c b/src/net.c index a21579c..6944805 100644 --- a/src/net.c +++ b/src/net.c @@ -721,7 +721,7 @@ void* handle_client(void *_arg){ luaI_tsetv(L, req_idx, "cookies", lcookie); parray_clear(cookie, STR); - parray_remove(table, "Cookie", NONE); + parray_remove(table, "Cookie", STR); } lua_pushlightuserdata(L, file_cont); -- cgit v1.2.3 From 71995aa7bab0198b3977f33d16ca34e4f628ec3d Mon Sep 17 00:00:00 2001 From: ame Date: Sat, 9 Aug 2025 04:26:08 -0500 Subject: dont override Content-Type --- src/net/lua.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/net/lua.c b/src/net/lua.c index d6bba65..2e46943 100644 --- a/src/net/lua.c +++ b/src/net/lua.c @@ -228,8 +228,11 @@ int l_sendfile(lua_State* L){ p_fatal("missing permissions"); } + lua_pushstring(L, "Content-Type"); + lua_gettable(L, header); + char* ext = strrchr(path, '.'); - if(ext && mime_type != NULL){ + if(lua_isnil(L, -1) && ext && mime_type != NULL){ char* content_type = map_get(mime_type, ext + 1); if(content_type) -- cgit v1.2.3 From 5666cbf8830c8b26337eb92f4da434d0d2242dc2 Mon Sep 17 00:00:00 2001 From: ame Date: Sat, 9 Aug 2025 15:17:04 -0500 Subject: dont auto-set content-type (yet) --- src/net.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/net.c b/src/net.c index 6944805..713e56a 100644 --- a/src/net.c +++ b/src/net.c @@ -762,7 +762,6 @@ void* handle_client(void *_arg){ lua_newtable(L); int header_idx = lua_gettop(L); luaI_tseti(L, header_idx, "Code", 200); - luaI_tsets(L, header_idx, "Content-Type", "text/html"); luaI_tsetv(L, res_idx, "header", header_idx); -- cgit v1.2.3 From 432f7792d12dadc3adb605c018176bbc7359b503 Mon Sep 17 00:00:00 2001 From: ame Date: Tue, 12 Aug 2025 21:54:57 -0500 Subject: support percent encoding --- src/net.c | 23 ++++++++++++++++------- src/net/util.c | 26 ++++++++++++++++++++++++++ src/net/util.h | 3 +++ src/types/str.c | 13 +++++++++++++ src/types/str.h | 5 ++++- 5 files changed, 62 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/net.c b/src/net.c index 713e56a..2766781 100644 --- a/src/net.c +++ b/src/net.c @@ -678,7 +678,7 @@ void* handle_client(void *_arg){ if(val == -2) net_error(client_fd, 414); if(val >= 0){ - str* sk = (str*)parray_get(table, "Path"); + str* path = (str*)parray_get(table, "Path"); str* sR = (str*)parray_get(table, "Request"); str* sT = (str*)parray_get(table, "Content-Type"); str* sC = (str*)parray_get(table, "Cookie"); @@ -693,13 +693,22 @@ void* handle_client(void *_arg){ sprintf(portc, "%i", args->port); str* aa = str_init(portc); - str_push(aa, sk->c); + str* decoded_path; + int decoded_err = percent_decode(path, &decoded_path); + larray_t* params = NULL; + parray_t* v = NULL; - larray_t* params = larray_init(); - parray_t* v = route_match(paths, aa->c, ¶ms); - - if(sT != NULL) - rolling_file_parse(L, &files_idx, &body_idx, header + 4, sT, bite - header_eof - 4, file_cont); + if(decoded_err == 1){ + net_error(client_fd, 400); + } else { + str_push(aa, decoded_path->c); + + params = larray_init(); + v = route_match(paths, aa->c, ¶ms); + + if(sT != NULL) + rolling_file_parse(L, &files_idx, &body_idx, header + 4, sT, bite - header_eof - 4, file_cont); + } str_free(aa); if(v != NULL){ diff --git a/src/net/util.c b/src/net/util.c index b41f0ed..92e538b 100644 --- a/src/net/util.c +++ b/src/net/util.c @@ -522,3 +522,29 @@ int net_error(int fd, int code){ send(fd, out, strlen(out), MSG_NOSIGNAL); return 0; } + +int percent_decode(str* input, str** _output){ + str* output = str_init(""); + + //could maybe make this better by using memmem to find occurrences of % + for(int i = 0; i <= input->len; i++){ + if(input->c[i] == '%' && input->len - i >= 3){ + str* hex = str_initfl(input->c + i + 1, 2); + + //casting a long to a char pointer is a horrible idea + long c = strtol(hex->c, NULL, 16); + if(c == 0){ + *_output = output; + return 1; + } + + str_pushl(output, ((char*)&c), 1); + str_free(hex); + i += 2; + } else { + str_pushl(output, input->c + i, 1); + } + } + *_output = output; + return 0; +} diff --git a/src/net/util.h b/src/net/util.h index cfac065..b8bc824 100644 --- a/src/net/util.h +++ b/src/net/util.h @@ -56,3 +56,6 @@ int match_param(char* path, char* match, parray_t* arr); void parse_mimetypes(); int net_error(int fd, int code); + +int percent_decode(str* input, str** _output); + diff --git a/src/types/str.c b/src/types/str.c index 0c8d63a..e1818a2 100644 --- a/src/types/str.c +++ b/src/types/str.c @@ -16,6 +16,19 @@ str* str_initl(const char* init, size_t len){ return s; } +str* str_initfl(const char* init, size_t len){ + + str* s = malloc(sizeof * s); + s->_bytes = len + 1 + alloc_buffer; + s->c = malloc(s->_bytes); + if(s->c == NULL) p_fatal("failed to allocate string\n"); + s->len = len ; + + memcpy(s->c, init, (len) * sizeof * init); + s->c[len] = '\0'; + return s; +} + str* str_init(const char* init){ return str_initl(init, strlen(init)); } diff --git a/src/types/str.h b/src/types/str.h index 86490cc..e650542 100644 --- a/src/types/str.h +++ b/src/types/str.h @@ -12,6 +12,9 @@ typedef struct { } str; str* str_initl(const char*, size_t len); +//str_initfl has the 'correct' behaviour where it forces the len and doesnt read extra bytes +//plan to switch everything to str_initfl, when everything will work with it +str* str_initfl(const char*, size_t len); str* str_init(const char*); void str_free(str*); void str_push(str*, const char*); @@ -19,4 +22,4 @@ void str_pushl(str*, const char*, size_t); void str_clear(str*); void str_popf(str*, int); void str_popb(str*, int); -#endif //__STR_H \ No newline at end of file +#endif //__STR_H -- cgit v1.2.3 From 70dcbc67382084d924d353f9c741cd8c0e46cb0f Mon Sep 17 00:00:00 2001 From: ame Date: Tue, 12 Aug 2025 22:02:18 -0500 Subject: mem leak oops --- src/net.c | 1 + src/net/util.c | 1 + 2 files changed, 2 insertions(+) (limited to 'src') diff --git a/src/net.c b/src/net.c index 2766781..d68da2c 100644 --- a/src/net.c +++ b/src/net.c @@ -710,6 +710,7 @@ void* handle_client(void *_arg){ rolling_file_parse(L, &files_idx, &body_idx, header + 4, sT, bite - header_eof - 4, file_cont); } + str_free(decoded_path); str_free(aa); if(v != NULL){ lua_newtable(L); diff --git a/src/net/util.c b/src/net/util.c index 92e538b..78e3043 100644 --- a/src/net/util.c +++ b/src/net/util.c @@ -534,6 +534,7 @@ int percent_decode(str* input, str** _output){ //casting a long to a char pointer is a horrible idea long c = strtol(hex->c, NULL, 16); if(c == 0){ + str_free(hex); *_output = output; return 1; } -- cgit v1.2.3 From 6e6e948a553cc062b439f349c0b545df0223d9a1 Mon Sep 17 00:00:00 2001 From: ame Date: Tue, 2 Sep 2025 00:07:22 -0500 Subject: parse net path and query --- src/net.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/net.c b/src/net.c index d68da2c..49eabd7 100644 --- a/src/net.c +++ b/src/net.c @@ -2,6 +2,7 @@ #include "net/util.h" #include "net/lua.h" #include "net/luai.h" +#include "types/str.h" #include @@ -652,6 +653,50 @@ int _request(lua_State* L, struct request_state* state){ return 1; } +struct net_path_t { + str* path; + parray_t* query; +}; + +void path_parse(struct net_path_t* path, str* raw){ + path->path = str_init(""); + path->query = parray_init(); + + str* query_key = str_init(""); + str* query_value = str_init(""); + + str** reading = &path->path; + + for(int i = 0; i <= raw->len; i++){ + if(raw->len - i > 1){ + switch(raw->c[i]){ + case '&': + parray_set(path->query, query_key->c, query_value); + str_clear(query_key); + query_value = str_init(""); + //dont want to break here + case '?': + reading = &query_key; + i++; + break; + case '=': + reading = &query_value; + i++; + break; + } + } + + str_pushl(*reading, raw->c + i, 1); + } + + if(*reading == query_value){ + parray_set(path->query, query_key->c, query_value); + } else { + str_free(query_value); + } + str_free(query_key); +} + #define max_uri_size 2048 _Atomic size_t threads = 0; @@ -693,12 +738,15 @@ void* handle_client(void *_arg){ sprintf(portc, "%i", args->port); str* aa = str_init(portc); + struct net_path_t parsed_path; + path_parse(&parsed_path, path); + str* decoded_path; - int decoded_err = percent_decode(path, &decoded_path); + int decoded_err = percent_decode(parsed_path.path, &decoded_path); larray_t* params = NULL; parray_t* v = NULL; - if(decoded_err == 1){ + if(decoded_err == 1 || paths == NULL){ net_error(client_fd, 400); } else { str_push(aa, decoded_path->c); @@ -734,6 +782,16 @@ void* handle_client(void *_arg){ parray_remove(table, "Cookie", STR); } + if(parsed_path.query->len != 0){ + lua_newtable(L); + int lquery = lua_gettop(L); + for(int i = 0; i != parsed_path.query->len; i++){ + luaI_tsetsl(L, lquery, parsed_path.query->P[i].key->c, ((str*)parsed_path.query->P[i].value)->c, ((str*)parsed_path.query->P[i].value)->len); + } + + luaI_tsetv(L, req_idx, "query", lquery); + } + lua_pushlightuserdata(L, file_cont); int ld = lua_gettop(L); @@ -747,6 +805,8 @@ void* handle_client(void *_arg){ } luaI_tsets(L, req_idx, "ip", inet_ntoa(args->cli.sin_addr)); + luaI_tsets(L, req_idx, "path", parsed_path.path->c); + luaI_tsets(L, req_idx, "rawpath", path->c); if(bite == -1){ client_fd = -2; @@ -837,6 +897,9 @@ net_end: } + str_free(parsed_path.path); + parray_clear(parsed_path.query, STR); + if(file_cont->boundary != NULL) str_free(file_cont->current); if(file_cont->boundary != NULL) str_free(file_cont->boundary); if(file_cont->boundary_id != NULL) str_free(file_cont->boundary_id); -- cgit v1.2.3