diff -r 000000000000 -r 7442b30ecaae librazor/path.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/librazor/path.c Sat Jun 11 17:56:48 2016 +0100 @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2014 J. Ali Harlow + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include +#include +#include "razor.h" +#include "razor-internal.h" + +/** + * razor_path_add_root: + * + * Adds a root to a path. path must be an absolute pathname. In POSIX + * environments this is equivalent to the concationation of root and path. + * In Microsoft Windows an adjustment may need to be made for a drive letter + * in path (which will be dropped). + * + * Returns: The new pathname. + **/ +RAZOR_EXPORT char *razor_path_add_root(const char *path, const char *root) +{ + if (root && *root) + return razor_concat(root, SKIP_DRIVE_LETTER(path), NULL); + else + return strdup(path); +} + +#if 0 + +/* + * This should work, but for some reason PathCreateFromUrlW() + * treats the percent-encoded bytes as being in CP 850 rather + * than UTF-8 as expected even if we set the codepage. + */ +RAZOR_EXPORT char *razor_path_from_url(const char *url) +{ + UINT saved_cp; + HRESULT result; + DWORD len = MAX_PATH; + wchar_t *url16; + wchar_t path16[MAX_PATH]; + char *path; + + url16 = razor_utf8_to_utf16(url, -1); + + saved_cp = GetConsoleCP(); + SetConsoleCP(CP_UTF8); + + result = PathCreateFromUrlW(url16, path16, &len, NULL); + + SetConsoleCP(saved_cp); + + if (result == S_OK) + path = razor_utf16_to_utf8(path16, len); + else + path = NULL; + + free(url16); + + return path; +} + +#else + +#ifdef MSWIN_API +static int is_ascii_letter(char c) +{ + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); +} +#endif + +static int xdigit_value(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + else + return (c | 0x20) - 'a' + 10; +} + +static int valid_unicode(unsigned unicode) +{ + /* + * Within the U+0000..U+10FFFF range defined by RFC3629 + * but not in the U+D800..U+DFFF range prohibited in UTF-8. + */ + return unicode < 0xD800 || (unicode >= 0xE000 && unicode < 0x110000); +} + +RAZOR_EXPORT char *razor_path_from_url(const char *url) +{ + int continuation_bytes = 0; + char *path, *p; + unsigned char c; + unsigned unicode; + + if (strncmp(url, "file://", 7) == 0) + url += 7; + else + return NULL; + + if (strncmp(url, "localhost/", 10) == 0) + url += 9; + else if (strncmp(url, "/", 1) != 0) + return NULL; + +#ifdef MSWIN_API + /* + * Under MS-Windows, file:///c:/xxx maps to c:/xxx + * Note that PathCreateFromUrl converts / to \ as well. + */ + if (is_ascii_letter(url[1]) && url[2] == ':' && url[3] == '/') + url++; +#endif + + p = path = malloc(strlen(url) + 1); + + while(*url) { + if (*url >= 0x7F || *url < 0x20) { + free(path); + return NULL; + } else if (*url != '%') { + if (continuation_bytes) { + free(path); + return NULL; + } else + *p++ = *url++; + } else if (isxdigit(url[1]) && isxdigit(url[2])) { + c = xdigit_value(url[1]) * 16 + xdigit_value(url[2]); + if (c == '/') { + free(path); + return NULL; + } else if (!continuation_bytes) { + if (c >= 0xF5 || c == 0xC0 || c == 0xC1) { + free(path); + return NULL; + } else if (c >= 0xF0) { + unicode = c & 7; + continuation_bytes = 3; + } else if (c >= 0xE0) { + unicode = c & 3; + continuation_bytes = 2; + } else if (c >= 0xC0) { + unicode = c & 1; + continuation_bytes = 1; + } + } else if ((c & 0xC0) != 0x80) { + free(path); + return NULL; + } else { + unicode <<= 6; + unicode |= (c & 0x3F); + + if (!--continuation_bytes && + !valid_unicode(unicode)) { + free(path); + return NULL; + } + } + + *p++ = c; + url += 3; + } else { + free(path); + return NULL; + } + } + + if (continuation_bytes) { + free(path); + return NULL; + } + + *p++ = '\0'; + + return realloc(path, p - path); +} + +#endif /* 0 */