diff options
author | Shav Kinderlehrer <[email protected]> | 2024-07-23 17:48:28 -0400 |
---|---|---|
committer | Shav Kinderlehrer <[email protected]> | 2024-07-23 17:48:28 -0400 |
commit | dc0f2ce9ba97ebb47e05b80a511da6eb29818b63 (patch) | |
tree | dc83035069f5a015047be1ca3da6f65781eb4695 /src/molerat/url.c | |
parent | f638f4bd1e3a03bc2bdd5f9dcd57d4830fd3c553 (diff) | |
download | molehole-dc0f2ce9ba97ebb47e05b80a511da6eb29818b63.tar.gz molehole-dc0f2ce9ba97ebb47e05b80a511da6eb29818b63.zip |
Merge old-moleholencurses
Diffstat (limited to 'src/molerat/url.c')
-rwxr-xr-x | src/molerat/url.c | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/src/molerat/url.c b/src/molerat/url.c new file mode 100755 index 0000000..0fd99ea --- /dev/null +++ b/src/molerat/url.c @@ -0,0 +1,181 @@ +#include <stdlib.h> +#include <string.h> + +#include "url.h" + +#define SET_STR(segment) \ + (segment) = malloc(i - start + 1); \ + strncpy((segment), s + start, i - start); + +#define MOVE(amount) \ + i += (amount); \ + start = i; + +#define SET_AT_END(segment) \ + if (cur == '\0') { \ + state = END; \ + if (i - 1 > start) { \ + SET_STR(segment); \ + } \ + } + +enum state { SCHEME, HOST, PORT, PATH, QUERY, FRAGMENT, END }; + +int parse_url(struct url *url, char *s) { + int i = 0; // index into *s + int start = 0; // index of current mode start + enum state state = SCHEME; + char cur; + + while (i < MAX_URL_LENGTH) { + cur = s[i]; + + if (cur == ' ') + return INVALID_CHARACTER; + + switch (state) { + case SCHEME: + if (cur == ':') { + state = HOST; + SET_STR(url->scheme); + + MOVE(3); // skip the '://' + } + SET_AT_END(url->scheme); + break; + + case HOST: + if (cur == ':') { + state = PORT; + SET_STR(url->host); + + MOVE(1); + } + + if (cur == '/') { + state = PATH; + SET_STR(url->host); + + MOVE(0); + } + SET_AT_END(url->host); + break; + + case PORT: + if (cur == '/') { + state = PATH; + char *port; + SET_STR(port); + + url->port = atoi(port); + + MOVE(0); + } + if (cur == '\0') { + state = END; + + char *port; + SET_STR(port); + + url->port = atoi(port); + } + + break; + + case PATH: + if (cur == '?') { + state = QUERY; + SET_STR(url->path); + + MOVE(0); + } + + if (cur == '#') { + state = FRAGMENT; + SET_STR(url->path); + + MOVE(0); + } + SET_AT_END(url->path); + break; + + case QUERY: + if (cur == '#') { + state = FRAGMENT; + SET_STR(url->query); + + MOVE(0); + } + SET_AT_END(url->query); + break; + + case FRAGMENT: + if (cur == '\0') { + state = END; + SET_STR(url->fragment); + + MOVE(0); + } + break; + + case END: + break; + } + + i++; + + if (cur == '\0') + break; + if (state == END) + break; + } + + if (url->host == NULL) + return MISSING_HOST; + if (url->port == 0) + return MISSING_PORT; + + if (url->path == NULL) { + url->path = malloc(2); + strcpy(url->path, "/"); + } + + return 0; +} + +struct url *init_url(void) { + struct url *url = malloc(sizeof(struct url)); + + url->scheme = NULL; + url->host = NULL; + url->port = 2693; + + url->path = NULL; + + url->query = NULL; + url->fragment = NULL; + + return url; +} + +void free_url(struct url *url) { + free(url->scheme); + free(url->host); + free(url->path); + free(url->fragment); + free(url->query); + free(url); +} + +int len_url(struct url *url) { + int len = 0; + + len += url->scheme != NULL ? strlen(url->scheme) : 0; + len += url->host != NULL ? strlen(url->host) : 0; + len += sizeof(url->port); + len += url->path != NULL ? strlen(url->path) : 0; + len += url->query != NULL ? strlen(url->query) : 0; + len += url->fragment != NULL ? strlen(url->fragment) : 0; + + return len; +} |