Implement url en/decoding
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
static enum MHD_Result handle_get(struct MHD_Connection *connection, SV url, Settings settings, SV username) {
|
||||
noh_arena_save(&temp);
|
||||
Noh_String fs_path = build_path(false, false, &settings.base_path, &username, &url);
|
||||
noh_string_replace(&fs_path, '+', ' ');
|
||||
url_decode(&fs_path);
|
||||
|
||||
noh_log(NOH_INFO, "Physical path: "Nsv_Fmt, Nsv_Arg(fs_path));
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ static Noh_String create_feed_response(Library_Entry self_path, SV url, Library_
|
||||
static enum MHD_Result handle_opds(struct MHD_Connection *connection, SV url, Settings settings, SV username) {
|
||||
noh_arena_save(&temp);
|
||||
Noh_String fs_path = build_path(false, false, &settings.base_path, &username, &url);
|
||||
noh_string_replace(&fs_path, '+', ' ');
|
||||
url_decode(&fs_path);
|
||||
Noh_String fs_path_cstr = fs_path;
|
||||
noh_string_append_null(&fs_path_cstr);
|
||||
|
||||
|
||||
102
src/path.c
102
src/path.c
@@ -1,3 +1,103 @@
|
||||
static inline bool byte_is_url_safe(char c) {
|
||||
return (c >= 'A' && c <= 'Z')
|
||||
|| (c >= 'a' && c <= 'z')
|
||||
|| (c >= '0' && c <+ '9')
|
||||
|| (c >= '(' && c <= '*')
|
||||
|| c == '!' || c == '-'
|
||||
|| c == '.' || c == '_';
|
||||
}
|
||||
|
||||
// Determines if a string needs to be URL encoded.
|
||||
// Sets the number of unsafe characters that need to be replaced by a hexadecimal format.
|
||||
static bool needs_encoding(Noh_String string, int *unsafe_count) {
|
||||
*unsafe_count = 0;
|
||||
bool safe = true ;
|
||||
for (size_t i = 0; i < string.count; i++) {
|
||||
bool needs_encode = byte_is_url_safe(string.elems[i]);
|
||||
if (needs_encode || string.elems[i] == ' ') safe = false;
|
||||
if (needs_encode) (*unsafe_count)++;
|
||||
}
|
||||
|
||||
return safe;
|
||||
}
|
||||
|
||||
static inline char to_char_lower(int value) {
|
||||
value &= 0XF;
|
||||
value += '0';
|
||||
if (value > '9') value += ('a' - ('9' + 1));
|
||||
|
||||
return (char)value;
|
||||
}
|
||||
|
||||
static inline int from_char(char c) {
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
if (c >= 'a' && c <= 'z') return c - 'a';
|
||||
if (c >= 'A' && c <= 'Z') return c - 'A';
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void url_encode(Noh_String *string) {
|
||||
int unsafe_count = 0;
|
||||
if (!needs_encoding(*string, &unsafe_count)) return;
|
||||
|
||||
// TODO: Use the calculated size to allocate exactly enough memory?
|
||||
// size_t new_string_size = string->count + unsafe_count * 2 + 1;
|
||||
Noh_String result = {0};
|
||||
|
||||
for (size_t i = 0; i < string->count; i++) {
|
||||
char cur = string->elems[i];
|
||||
if (cur == ' ') noh_da_append(&result, '+');
|
||||
|
||||
if (!byte_is_url_safe(cur)) {
|
||||
noh_da_append(&result, '%');
|
||||
noh_da_append(&result, to_char_lower(cur >> 4));
|
||||
noh_da_append(&result, to_char_lower(cur));
|
||||
}
|
||||
}
|
||||
|
||||
noh_string_free(string);
|
||||
string->elems = result.elems;
|
||||
string->count = result.count;
|
||||
string->capacity = result.capacity;
|
||||
}
|
||||
|
||||
void url_decode(Noh_String *string) {
|
||||
size_t read = 0;
|
||||
size_t write = 0;
|
||||
|
||||
while (read < string->count) {
|
||||
char c = string->elems[read++];
|
||||
if (c == '+') {
|
||||
string->elems[write++] = ' ';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '%') {
|
||||
int h1 = string->elems[read];
|
||||
int h2 = string->elems[read + 1];
|
||||
|
||||
// If valid hex chars, add it.
|
||||
if ((h1 | h2) != 0xFF) {
|
||||
string->elems[write] = (char)((h1 << 4) | h2);
|
||||
read += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fallback to just adding the '%'.
|
||||
}
|
||||
|
||||
// Just copy the character.
|
||||
string->elems[write++] = c;
|
||||
}
|
||||
|
||||
// Zero-out the rest.
|
||||
string->count = read;
|
||||
for (size_t i = read; i < string->count; i++) {
|
||||
string->elems[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#define build_path(url, first, ...) build_path_((url), (first), __VA_ARGS__, NULL)
|
||||
static Noh_String build_path_(bool url, bool go_up, Noh_String_View *first, ...) {
|
||||
va_list args;
|
||||
@@ -23,7 +123,7 @@ static Noh_String build_path_(bool url, bool go_up, Noh_String_View *first, ...)
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
if (url) noh_string_replace(&result, ' ', '+');
|
||||
if (url) url_encode(&result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user