Changeset: e33753ba0353 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=e33753ba0353
Modified Files:
monetdb5/modules/atoms/url.c
sql/test/BugTracker-2012/Tests/url_script_test.Bug-2972.stable.out
Branch: Jan2014
Log Message:
Reimplemented URL parsing, and cleaned up code and mistakes.
diffs (truncated from 1243 to 300 lines):
diff --git a/monetdb5/modules/atoms/url.c b/monetdb5/modules/atoms/url.c
--- a/monetdb5/modules/atoms/url.c
+++ b/monetdb5/modules/atoms/url.c
@@ -57,519 +57,133 @@
#include "mal.h"
#include "mal_exception.h"
-#if 0
-static void getword(char *word, char *line, char stop);
-static void plustospace(char *str);
-#endif
static char x2c(char *what);
-/* COMMAND "getAnchor": Extract an anchor (reference) from the URL
- * SIGNATURE: getAnchor(url) : str; */
-static str
-url_getAnchor(str *retval, /* put string: pointer to char here. */
- url Str1) /* string: pointer to char. */
+/* SCHEME "://" AUTHORITY [ PATH ] [ "?" SEARCH ] [ "#" FRAGMENT ]
+ * AUTHORITY is: [ USER [ ":" PASSWORD ] "@" ] HOST [ ":" PORT ] */
+
+/* return pointer to string after the scheme and colon; input: pointer
+ * to start of URI */
+static const char *
+skip_scheme(const char *uri)
{
- str s, d;
-
- if (Str1 == 0)
- throw(ILLARG, "url.getAnchor", "url missing");
- s = strchr(Str1, '#');
- if (s == 0)
- s= (str) str_nil;
- d = GDKstrdup(s);
- if (d == NULL)
- throw(MAL, "url.getAnchor", "Allocation failed");
- *retval = d;
- return MAL_SUCCEED;
+ if (('a' <= *uri && *uri <= 'z') || ('A' <= *uri && *uri <= 'Z')) {
+ uri++;
+ while (('a' <= *uri && *uri <= 'z') ||
+ ('A' <= *uri && *uri <= 'Z') ||
+ ('0' <= *uri && *uri <= '9') ||
+ *uri == '+' || *uri == '-' || *uri == '.')
+ uri++;
+ if (*uri == ':')
+ return uri + 1;
+ }
+ return NULL;
}
-/* COMMAND "getBasename": Extract the base of the last file name of the URL,
- * thus, excluding the file extension.
- * SIGNATURE: getBasename(str) : str; */
-static str
-url_getBasename(str *retval, url t)
+#define ishex(c) (('0' <= (c) && (c) <= '9') || \
+ ('a' <= (c) && (c) <= 'f') || \
+ ('A' <= (c) && (c) <= 'F'))
+#define isreserved(c) ((c) == ';' || (c) == '/' || (c) == '?' || \
+ (c) == ':' || (c) == '@' ||
(c) == '&' || \
+ (c) == '=' || (c) == '+' ||
(c) == '$' || \
+ (c) == ',')
+#define isunreserved(c) (('a' <= (c) && (c) <= 'z') || \
+ ('A' <= (c) && (c) <= 'Z') || \
+ ('0' <= (c) && (c) <= '9') || \
+ (c) == '-' || (c) == '_' ||
(c) == '.' || \
+ (c) == '!' || (c) == '~' ||
(c) == '*' || \
+ (c) == '\'' || (c) == '(' ||
(c) == ')')
+
+/* return pointer to string after the authority, filling in pointers
+ * to start of user, password, host, and port, if provided; input:
+ * result of skip_scheme() */
+static const char *
+skip_authority(const char *uri, const char **userp, const char **passp, const
char **hostp, const char **portp)
{
- str d = 0, s;
+ const char *user = NULL, *pass = NULL, *host = NULL, *port = NULL;
- if (t == 0)
- throw(ILLARG, "url.getBasename", "url missing");
- s = strrchr(t, '/');
- if (s)
- s++;
- else
- s = (str) str_nil;
- d = GDKstrdup(s);
- if (d == NULL)
- throw(MAL, "url.getBasename", "Allocation failed");
- s = strchr(d, '.');
- if (s)
- *s = 0;
- *retval = d;
- return MAL_SUCCEED;
+ if (uri[0] == '/' && uri[1] == '/') {
+ uri += 2;
+ user = host = uri;
+ while (isunreserved(*uri) ||
+ (*uri == '%' && ishex(uri[1]) && ishex(uri[2])) ||
+ *uri == ';' || *uri == ':' || *uri == '=' || *uri ==
'+'|| *uri == '$' || *uri == ',' ||
+ *uri == '@') {
+ if (*uri == ':') {
+ if (user == host)
+ port = pass = uri + 1;
+ else
+ port = uri + 1;
+ } else if (*uri == '@')
+ host = uri + 1;
+ uri += *uri == '%' ? 3 : 1;
+ }
+ if (user == host) {
+ /* no "@", so no user info */
+ if (userp)
+ *userp = NULL;
+ if (passp)
+ *passp = NULL;
+ } else {
+ if (*userp)
+ *userp = user;
+ if (*passp)
+ *passp = pass;
+ }
+ if (portp)
+ *portp = port;
+ if (hostp)
+ *hostp = host;
+ return uri;
+ }
+ return NULL;
}
-#if 0
-/* COMMAND "getContent": Retrieve the file referenced
- * SIGNATURE: getContent(str) : str; */
-static str
-url_getContent(str *retval, /* put string: pointer to char here. */
- url Str1) /* string: pointer to char. */
+/* return pointer to string after the path, filling in pointer to
+ * start of last component and extension of that component; input:
+ * result of skip_authority() */
+static const char *
+skip_path(const char *uri, const char **basep, const char **extp)
{
- /* TODO: getContent should not return a string */
- if (!Str1)
- throw(ILLARG, "url.getContent", "url missing");
- strcpy(*retval, "functions not implemented");
- return MAL_SUCCEED;
-}
-#endif
+ const char *base = NULL, *ext = NULL;
-/* COMMAND "getContext": Extract the path context from the URL
- * SIGNATURE: getContext(str) : str; */
-static str
-url_getContext(str *retval, url Str1)
-{
- const char *s;
- str d;
-
- if (Str1 == 0)
- throw(ILLARG, "url.getContext", "url missing");
-
- s = strstr(Str1, "://");
- if (s)
- s += 3;
- else
- s = Str1;
-
- s = strchr(s, '/');
- if (s == 0)
- s = str_nil;
- d = GDKstrdup(s);
- if (d == NULL)
- throw(MAL, "url.getContext", "Allocation failed");
- *retval = d;
- return MAL_SUCCEED;
+ if (*uri == '/') {
+ uri++;
+ base = uri;
+ while (isunreserved(*uri) ||
+ (*uri == '%' && ishex(uri[1]) && ishex(uri[2])) ||
+ *uri == ':' || *uri == '@' || *uri == '&' || *uri ==
'=' || *uri == '+' || *uri == '$' || *uri == ',' ||
+ *uri == ';' ||
+ *uri == '/') {
+ if (*uri == '/') {
+ base = uri + 1;
+ ext = NULL;
+ } else if (*uri == '.' && ext == NULL && uri != base) {
+ ext = uri;
+ }
+ uri += *uri == '%' ? 3 : 1;
+ }
+ }
+ if (basep)
+ *basep = base;
+ if (extp)
+ *extp = ext;
+ return uri;
}
-#if 0
-/* COMMAND "getDirectory": Extract the directory names from the URL
- * SIGNATURE: getDirectory(str) : bat[int,str]; */
-static str
-url_getDirectory(BAT **retval, /* put pointer to BAT[int,str] record here. */
- url t)
+/* return pointer to string after the search string; input: result of
+ * skip_path() */
+static const char *
+skip_search(const char *uri)
{
- char buf[1024];
- char *s;
- int i = 0, k = 0;
- BAT *b = NULL;
-
- if (t == 0)
- throw(ILLARG, "url.getDirectory", "url missing");
-
- while (*t && *t != ':')
- t++;
- t++;
- if (*t != '/')
- goto getDir_done;
- t++;
- if (*t != '/')
- goto getDir_done;
- t++;
- while (*t && *t != '/')
- t++;
- b = BATnew(TYPE_int, TYPE_str, 40);
- if (b == 0)
- throw(MAL, "url.getDirectory", "could not create BAT");
-
- s = buf;
- for (t++; *t; t++) {
- if (*t == '/') {
- *s = 0;
- BUNins(b, &k, buf, FALSE);
- k++;
- s = buf;
- *s = 0;
- i = 0;
- continue;
+ if (*uri == '?') {
+ uri++;
+ while (isreserved(*uri) || isunreserved(*uri) ||
+ (*uri == '%' && ishex(uri[1]) && ishex(uri[2]))) {
+ uri += *uri == '%' ? 3 : 1;
}
- *s++ = *t;
- if (i++ == 1023)
- throw(PARSE, "url.getDirectory","server name too long");
}
-getDir_done:
- BATrename(b,"dir_name");
- BATroles(b,"dir","name");
- BATmode(b,TRANSIENT);
- *retval= b;
- return MAL_SUCCEED;
-}
-#endif
-
-/* COMMAND "getDomain": Extract the Internet domain from the URL
- * SIGNATURE: getDomain(str) : str; */
-str
-URLgetDomain(str *retval, str *u)
-{
- char buf[1024];
- char *b, *d, *s = buf;
- int i = 0;
- url t= *u;
-
- *retval = 0;
- s = (str)str_nil;
- if (t == 0)
- throw(ILLARG, "url.getDomain", "domain missing");
- while (*t && *t != ':')
- t++;
- t++;
- if (*t != '/')
- goto getDomain_done;
- t++;
- if (*t != '/')
- goto getDomain_done;
- t++;
- b = buf;
- d = 0;
- for (; *t && *t != '/' && *t != ':' && *t != '?' && *t != '#'; t++) {
- if (*t == '.')
- d = b;
- *b++ = *t;
- if (i++ == 1023)
- throw(PARSE, "url.getDomain", "server name too long\n");
- }
- *b = 0;
- if (d)
- s = d + 1;
-getDomain_done:
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list