2 * Copyright (C) 2014, 2016 J. Ali Harlow <ali@juiblex.co.uk>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include "razor-internal.h"
27 static int valid_unicode(unsigned unicode)
30 * Within the U+0000..U+10FFFF range defined by RFC3629
31 * but not in the U+D800..U+DFFF range prohibited in UTF-8.
33 return unicode < 0xD800 || (unicode >= 0xE000 && unicode < 0x110000);
36 char *razor_path_from_parsed_uri(const struct razor_uri *ru,
37 struct razor_error **error)
39 int continuation_bytes = 0;
40 char *path, *p, *s, *uri;
45 uri = razor_uri_recompose(ru);
46 razor_set_error(error, RAZOR_GENERAL_ERROR,
47 RAZOR_GENERAL_ERROR_BAD_URI, uri,
48 "URI does not include a scheme");
53 if (strcmp(ru->scheme, "file")) {
54 uri = razor_uri_recompose(ru);
55 razor_set_error(error, RAZOR_GENERAL_ERROR,
56 RAZOR_GENERAL_ERROR_UNSUPPORTED_URI, uri,
62 if (ru->host && *ru->host && strcmp(ru->host, "localhost") ||
63 ru->userinfo || ru->port) {
64 uri = razor_uri_recompose(ru);
65 razor_set_error(error, RAZOR_GENERAL_ERROR,
66 RAZOR_GENERAL_ERROR_UNSUPPORTED_URI, uri,
67 "URI refers to a non-local file");
75 * Under MS-Windows, a path of /c:/xxx maps to c:/xxx
76 * Note that PathCreateFromUrl converts / to \ as well.
78 if (s[0] == '/' && is_alpha(s[1]) && s[2] == ':' && s[3] == '/')
82 p = path = malloc(strlen(s) + 1);
85 if (*s >= 0x7F || *s < 0x20)
88 if (continuation_bytes)
93 c = pchar_get_char(s);
95 if (c == '/' || c == '\\')
100 else if (!continuation_bytes) {
101 if (c >= 0xF5 || c == 0xC0 || c == 0xC1)
103 else if (c >= 0xF0) {
105 continuation_bytes = 3;
106 } else if (c >= 0xE0) {
108 continuation_bytes = 2;
109 } else if (c >= 0xC0) {
111 continuation_bytes = 1;
113 } else if ((c & 0xC0) != 0x80)
117 unicode |= (c & 0x3F);
119 if (!--continuation_bytes &&
120 !valid_unicode(unicode))
129 if (*s || continuation_bytes) {
130 uri = razor_uri_recompose(ru);
131 razor_set_error(error, RAZOR_GENERAL_ERROR,
132 RAZOR_GENERAL_ERROR_BAD_URI,
133 uri, "Illegal character in file URI path");
141 return realloc(path, p - path);
144 RAZOR_EXPORT char *razor_path_from_uri(const char *uri,
145 struct razor_error **error)
150 if (razor_uri_parse(&ru, uri, error))
153 path = razor_path_from_parsed_uri(&ru, error);
155 razor_uri_destroy(&ru);
160 RAZOR_EXPORT char *razor_path_to_uri(const char *path)
164 uri = malloc(6 + 3 * strlen(path) + 1);
166 strcpy(uri, "file:");
172 * Under MS-Windows, c:/xxx maps to a path of /c:/xxx
174 if (is_alpha(path[0]) && path[1] == ':' &&
175 (path[2] == '/' || path[2] == '\\'))
180 if (*path == '/' || is_unreserved(*path) ||
181 is_sub_delim(*path) || *path == ':' || *path == '@')
184 else if (*path == '\\')
189 *p++ = "0123456789ABCDEF"[(*(unsigned char *)path)/16];
190 *p++ = "0123456789ABCDEF"[(*(unsigned char *)path)%16];
196 return realloc(uri, p - uri);
200 razor_path_relative_to_uri(const char *uri, const char *path,
201 struct razor_error **error)
203 char *rel_uri, *result;
205 /* Strictly wrong if uri isn't a file URI, but probably okay */
206 rel_uri = razor_path_to_uri(path);
208 result = razor_resolve_uri_root(uri, rel_uri + 5, 1, error);