diff --git a/CMakeLists.txt b/CMakeLists.txt index 0032825..43b39d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10) -project(fun VERSION 0.40.8 LANGUAGES C) +project(fun VERSION 0.41.0 LANGUAGES C) set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED ON) diff --git a/lib/net/cgi.fun b/lib/net/cgi.fun index 3624c6a..b65cfcf 100644 --- a/lib/net/cgi.fun +++ b/lib/net/cgi.fun @@ -256,39 +256,38 @@ class CGI() return resp fun url_decode(this, s) - source_str = to_string(s) - decoded_result = "" - number current_pos = 0 - number source_len = len(source_str) - while (current_pos < source_len) - current_char = substr(source_str, current_pos, 1) - if (current_char == "+") - decoded_result = decoded_result + " " - current_pos = current_pos + 1 - else if (current_char == "%" && current_pos + 2 < source_len) - hex_digit1 = substr(source_str, current_pos + 1, 1) - hex_digit2 = substr(source_str, current_pos + 2, 1) - hex_table = "0123456789ABCDEF" - val1 = find(hex_table, str_to_upper(hex_digit1)) - val2 = find(hex_table, str_to_upper(hex_digit2)) - if (val1 >= 0 && val2 >= 0) - number char_code = val1 * 16 + val2 - // Using a more robust table with explicit characters - ascii_table = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" - if (char_code >= 32 && char_code <= 126) - decoded_result = decoded_result + substr(ascii_table, char_code - 32, 1) + src = to_string(s) + out = [] + i = 0 + n = len(src) + while (i < n) + ch = substr(src, i, 1) + if (ch == "+") + push(out, " ") + i = i + 1 + else if (ch == "%" && i + 2 < n) + h1 = substr(src, i + 1, 1) + h2 = substr(src, i + 2, 1) + hexdigits = "0123456789ABCDEF" + v1 = find(hexdigits, str_to_upper(h1)) + v2 = find(hexdigits, str_to_upper(h2)) + if (v1 >= 0 && v2 >= 0) + code = v1 * 16 + v2 + ascii = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" + if (code >= 32 && code <= 126) + push(out, substr(ascii, code - 32, 1)) else - decoded_result = decoded_result + "%" - decoded_result = decoded_result + hex_digit1 - decoded_result = decoded_result + hex_digit2 - current_pos = current_pos + 3 + push(out, "%") + push(out, h1) + push(out, h2) + i = i + 3 else - decoded_result = decoded_result + current_char - current_pos = current_pos + 1 + push(out, ch) + i = i + 1 else - decoded_result = decoded_result + current_char - current_pos = current_pos + 1 - return decoded_result + push(out, ch) + i = i + 1 + return join(out, "") fun _merge_params(this, pairs) // pairs: array of [key, value] entries diff --git a/src/parser.c b/src/parser.c index af40c75..2bedf2c 100644 --- a/src/parser.c +++ b/src/parser.c @@ -201,10 +201,16 @@ static struct { int count; } G = {{0}, {0}, {0}, 0}; -static int sym_index(const char *name) { +static int sym_find(const char *name) { for (int i = 0; i < G.count; ++i) { if (strcmp(G.names[i], name) == 0) return i; } + return -1; +} + +static int sym_index(const char *name) { + int existing = sym_find(name); + if (existing >= 0) return existing; if (G.count >= MAX_GLOBALS) { parser_fail(0, "Too many globals (max %d)", MAX_GLOBALS); return 0; @@ -5580,7 +5586,17 @@ static void parse_simple_statement(Bytecode *bc, const char *src, size_t len, si /* assignment or simple call */ int lidx = local_find(name); - int gi = (lidx < 0) ? sym_index(name) : -1; + int gi = (lidx < 0) ? sym_find(name) : -1; + if (lidx < 0 && gi < 0 && g_locals) { + /* Auto-declare as local if we're in a function and it's not known as local or global */ + lidx = local_add(name); + } + if (lidx < 0 && gi < 0) { + /* Not local, not existing global -> it's a new global (or a new local if we were in a function but lidx still < 0?) + Actually if g_locals was non-null we already added it to lidx. + If g_locals is NULL, we create it as global. */ + gi = sym_index(name); + } skip_spaces(src, len, &local_pos); /* object field assignment: supports