/* * 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 */