From 2ca1648ee260877c2a619ee45449cbf5b4aaa3a1 Mon Sep 17 00:00:00 2001 From: Romain de Laage Date: Tue, 16 Feb 2021 19:38:50 +0100 Subject: [PATCH] Join url implemented --- lib/url.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 159 insertions(+), 8 deletions(-) diff --git a/lib/url.c b/lib/url.c index 5952c25..30055e7 100644 --- a/lib/url.c +++ b/lib/url.c @@ -16,6 +16,7 @@ Url *urllib_init (void); void urllib_free (Url *url); int urllib_parse (Url *url, const char *url_string); void urllib_tostring (Url *url, char *dest); +int urllib_join (Url *url, const char *path); int main (int argc, @@ -26,11 +27,19 @@ main (int argc, url = urllib_init (); - if (argc >= 2) + if (argc == 2) { if (urllib_parse (url, argv[1])) return 1; } + if (argc >= 3) + { + if (urllib_parse (url, argv[1])) + return 1; + + if (urllib_join (url, argv[2])) + return 1; + } else { printf ("Enter a url : "); @@ -38,6 +47,12 @@ main (int argc, if (urllib_parse (url, url_str)) return 1; + + printf ("Enter a path : "); + scanf ("%s", url_str); + + if (urllib_join (url, url_str)) + return 1; } urllib_tostring (url, url_str); @@ -74,7 +89,6 @@ urllib_free (Url *url) free (url); } -/* check this parser : http://draft.scyphus.co.jp/lang/c/url_parser.html not perfect but could give ideas */ int urllib_parse (Url *url, const char *url_string) @@ -189,12 +203,11 @@ urllib_parse (Url *url, } return 0; - - //is there a path ? (test \0) } void -urllib_tostring (Url *url, char *dest) +urllib_tostring (Url *url, + char *dest) { if (url->port == NULL) if (url->path == NULL) @@ -208,6 +221,144 @@ urllib_tostring (Url *url, char *dest) sprintf (dest, "%s://%s:%s%s\r\n", url->scheme, url->host, url->port, url->path); } -void -urllib_join (Url *url, const char *path) -{} +int +urllib_join (Url *url, + const char *path) +{// view RFC 3986, section 5.2.4 + int len = strlen (path); + char *base, *result, *inputcursor; + + if (len == 0)//nothing to merge + return 0; + + if (url->path == NULL)//no current path, path = '/' + { + url->path = malloc (sizeof (char) * 2); + if (url->path == NULL) + return 1; + + url->path[0] = '/'; + url->path[1] = '\0'; + } + + if (path[0] != '/') //relative path + { + int url_path_len = strlen (path); + + if (url->path[url_path_len - 1] != '/')//we are on a file + { + char *tmpcursor = strrchr (url->path, '/'); + if (tmpcursor == NULL) + return -1; + + tmpcursor[1] = '\0'; + } + + len += url_path_len; + base = malloc (sizeof (char) * (len + 1)); + if (base == NULL) + return 1; + result = malloc (sizeof (char) * (len + 1)); + if (result == NULL) + { + free (base); + return 1; + } + + sprintf (base, "%s%s", url->path, path); + result[0] = '\0'; + } + else //absolute path + { + base = malloc (sizeof (char) * (len + 1)); + if (base == NULL) + return 1; + result = malloc (sizeof (char) * (len + 1)); + if (result == NULL) + { + free (base); + return 1; + } + + strncpy (base, path, len); + base[len] = '\0'; + result[0] = '\0'; + } + + inputcursor = base; + len = strlen (inputcursor); + while (len > 0) //while input buffer is not empty + { + char *tmpcursor; + + if (len >= 3 && inputcursor[0] == '.' && inputcursor[1] == '.' && inputcursor[2] == '/') + { + inputcursor += 3; + len = strlen (inputcursor); + } + else if (len >= 2 && inputcursor[0] == '.' && inputcursor[1] == '/') + { + inputcursor += 2; + len = strlen (inputcursor); + } + else if (len >= 3 && inputcursor[0] == '/' && inputcursor[1] == '.' && inputcursor[2] == '/') + { + inputcursor += 2; + len = strlen (inputcursor); + } + else if (len == 2 && inputcursor[0] == '/' && inputcursor[1] == '.') + { + inputcursor += 1; + inputcursor[0] = '/'; + len = strlen (inputcursor); + } + else if (len >= 4 && inputcursor[0] == '/' && inputcursor[1] == '.' && inputcursor[2] == '.' && inputcursor[3] == '/') + { + inputcursor += 3; + len = strlen (inputcursor); + //remove result last segment + tmpcursor = strrchr (result, '/'); + if (tmpcursor != NULL) + *tmpcursor = '\0'; + } + else if (len == 3 && inputcursor[0] == '/' && inputcursor[1] == '.' && inputcursor[2] == '.') + { + inputcursor += 2; + inputcursor[0] = '/'; + len = strlen (inputcursor); + //remove result last segment + tmpcursor = strrchr (result, '/'); + if (tmpcursor != NULL) + *tmpcursor = '\0'; + } + else if ((len == 2 && inputcursor[0] == '.' && inputcursor[1] == '.') || (len == 1 && inputcursor[0] == '.')) + { + inputcursor[0] = '\0'; + len = strlen (inputcursor); + } + else + { + //get first segment of inputcursor then append it to result and delete it + tmpcursor = strchr (inputcursor + 1, '/'); + if (tmpcursor == NULL)//last segment in input buffer + { + sprintf (result, "%s%s", result, inputcursor); + *inputcursor = '\0'; + } + else + { + len = tmpcursor - inputcursor; + strncpy (result + strlen (result), inputcursor, len); + inputcursor = tmpcursor; + } + + len = strlen (inputcursor); + } + } + + free (url->path); + url->path = result; + free (base); + + return 0; +}