diff options
author | Vincent Douillet <vincent@vdouillet.fr> | 2024-09-11 11:20:31 +0200 |
---|---|---|
committer | Vincent Douillet <vincent@vdouillet.fr> | 2024-09-11 11:20:31 +0200 |
commit | 19e47daa9c1fb55f2cb9e639d5a6ef16b5bc4e88 (patch) | |
tree | 2b98ac0700a11cb142625d8355019c44b49c1850 /url.c | |
parent | 4e921ffa31fdca2425d326efda1c6d9ad190359a (diff) |
url: fix encoding for use in http context
Diffstat (limited to 'url.c')
-rw-r--r-- | url.c | 80 |
1 files changed, 69 insertions, 11 deletions
@@ -28,13 +28,18 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include <sys/types.h> + #include <assert.h> #include <limits.h> #include <stdarg.h> +#include <stdint.h> #include <stdlib.h> +#include <kcgi.h> #include <string.h> #include "config.h" +#include "str.h" #include "url.h" bool @@ -74,20 +79,35 @@ check_request_path(const char *path, const char *suffix) return true; } +char * +url_encode(const char *str) +{ + char *result; + + if ((result = khttp_urlencode(str)) == NULL) + return NULL; + + str_replace(result, '+', ' '); + return result; +} + size_t -url_build(char *dst, size_t dst_size,...) +url_build(char *dst, size_t dst_sz,...) { va_list path_list; - const char *path; - size_t w_size; + char p [PATH_MAX]; + char *encoded, *path, *slash; + size_t c_len, p_len, w_len; dst[0] = '\0'; - w_size = 0; - va_start(path_list, dst_size); + w_len = 0; + va_start(path_list, dst_sz); while ((path = va_arg(path_list, char *)) != NULL) { /* no more space in dst buffer */ - if (w_size >= dst_size) - break; + if (w_len >= dst_sz) { + w_len = 0; + goto end; + } if (path[0] == '\0') continue; @@ -95,12 +115,50 @@ url_build(char *dst, size_t dst_size,...) if (path[0] == '.' && path[1] == '\0') continue; - if (path[0] != '/' && w_size > 0 && dst[w_size - 1] != '/') - strlcat(dst, "/", dst_size); + while (path[0] != '\0') { + /* no more space in dst buffer */ + if (w_len >= dst_sz) { + w_len = 0; + goto end; + } + + /* skip heading slashes */ + slash = strchr(path, '/'); + if (slash == path) { + path++; + continue; + } + + /* copy string to encode into buffer + * if no slash found, copy everything, otherwise stop + * before the slash */ + c_len = slash == NULL ? strlen(path) : + (size_t) (slash - path); + if (c_len >= PATH_MAX) { + w_len = 0; + goto end; + } + p_len = strlcpy(p, path, c_len + 1); + if (p_len < c_len) { + w_len = 0; + goto end; + } + + /* encode string */ + if ((encoded = url_encode(p)) == NULL) { + w_len = 0; + goto end; + } - w_size = strlcat(dst, path, dst_size); + /* append it to the path */ + strlcat(dst, "/", dst_sz); + w_len = strlcat(dst, encoded, dst_sz); + free(encoded); + path += c_len; + } } +end: va_end(path_list); - return w_size; + return w_len; } |