From da94a304bcb9645600901a692409680ac627e7d7 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sat, 23 Apr 2011 13:35:51 -0700 Subject: [PATCH] pxe: Add a much more general URL-parsing framework Add a URL-parsing framework that we can use for multiple protocols. Signed-off-by: H. Peter Anvin --- core/fs/pxe/url.h | 28 ++++++++ core/fs/pxe/urlparse.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 220 insertions(+) create mode 100644 core/fs/pxe/url.h create mode 100644 core/fs/pxe/urlparse.c diff --git a/core/fs/pxe/url.h b/core/fs/pxe/url.h new file mode 100644 index 0000000..baea2b7 --- /dev/null +++ b/core/fs/pxe/url.h @@ -0,0 +1,28 @@ +/* + * url.h + */ + +#ifndef CORE_PXE_URL_H +#define CORE_PXE_URL_H + +enum url_type { + URL_NORMAL, + URL_OLD_TFTP, + URL_PREFIX +}; + +struct url_info { + char *scheme; + char *user; + char *passwd; + char *host; + unsigned int port; + char *path; /* Includes query */ + enum url_type type; +}; + +void parse_url(struct url_info *ui, char *url); +char *url_escape_unsafe(const char *input); +char *url_unescape(char *buffer, char terminator); + +#endif /* CORE_PXE_URL_H */ diff --git a/core/fs/pxe/urlparse.c b/core/fs/pxe/urlparse.c new file mode 100644 index 0000000..77865b5 --- /dev/null +++ b/core/fs/pxe/urlparse.c @@ -0,0 +1,192 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009-2011 Intel Corporation; author: H. Peter Anvin + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * urlparse.c + * + * Decompose a URL into its components. + */ + +#include +#include +#include +#include "url.h" + +void parse_url(struct url_info *ui, char *url) +{ + char *p = url; + char *q, *r, *s; + + memset(ui, 0, sizeof *ui); + + q = strstr(p, "://"); + if (!q) { + q = strstr(p, "::"); + if (q) { + *q = '\0'; + ui->scheme = "tftp"; + ui->host = p; + ui->path = q+2; + ui->type = URL_OLD_TFTP; + return; + } else { + ui->path = p; + ui->type = URL_PREFIX; + return; + } + } + + ui->type = URL_NORMAL; + + ui->scheme = p; + *q = '\0'; + p = q+3; + + q = strchr(p, '/'); + if (q) { + *q = '\0'; + ui->path = q+1; + q = strchr(q+1, '#'); + if (q) + *q = '\0'; + } else { + ui->path = ""; + } + + r = strchr(p, '@'); + if (r) { + ui->user = p; + *r = '\0'; + s = strchr(p, ':'); + if (s) { + *s = '\0'; + ui->passwd = s+1; + } + p = r+1; + } + + ui->host = p; + r = strchr(p, ':'); + if (r) { + *r = '\0'; + ui->port = atoi(r+1); + } +} + +char *url_escape_unsafe(const char *input) +{ + const char *p = input; + unsigned char c; + char *out, *q; + size_t n = 0; + + while ((c = *p++)) { + if (c < ' ' || c > '~') { + n += 3; /* Need escaping */ + } else { + n++; + } + } + + q = out = malloc(n+1); + while ((c = *p++)) { + if (c < ' ' || c > '~') { + q += snprintf(q, 3, "%%%02X", c); + } else { + *q++ = c; + } + } + + *q = '\0'; + + return out; +} + +static int hexdigit(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + c |= 0x20; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + return -1; +} + +char *url_unescape(char *buffer, char terminator) +{ + char *p = buffer; + char *q = buffer; + unsigned char c; + int x, y; + + while ((c = *p++)) { + if (c == terminator) { + *q = '\0'; + return p; + } + p++; + if (c == '%') { + x = hexdigit(p[0]); + if (x >= 0) { + y = hexdigit(p[1]); + if (y >= 0) { + *q++ = (x << 4) + y; + p += 2; + continue; + } + } + } + *q++ = c; + } + *q = '\0'; + return NULL; +} + +#ifdef URL_TEST + +int main(int argc, char *argv[]) +{ + int i; + struct url_info url; + + for (i = 1; i < argc; i++) { + parse_url(&url, argv[i]); + printf("scheme: %s\n" + "user: %s\n" + "passwd: %s\n" + "host: %s\n" + "port: %d\n" + "path: %s\n" + "type: %d\n", + url.scheme, url.user, url.passwd, url.host, url.port, + url.path, url.type); + } + + return 0; +} + +#endif -- 2.7.4