1.1 --- a/librazor/path.c Fri Oct 17 10:13:48 2014 +0100
1.2 +++ b/librazor/path.c Mon Jul 04 13:04:19 2016 +0100
1.3 @@ -1,5 +1,5 @@
1.4 /*
1.5 - * Copyright (C) 2014 J. Ali Harlow <ali@juiblex.co.uk>
1.6 + * Copyright (C) 2014, 2016 J. Ali Harlow <ali@juiblex.co.uk>
1.7 *
1.8 * This program is free software; you can redistribute it and/or modify
1.9 * it under the terms of the GNU General Public License as published by
1.10 @@ -19,78 +19,10 @@
1.11 #include "config.h"
1.12 #include <stdlib.h>
1.13 #include <string.h>
1.14 +#include <ctype.h>
1.15 #include "razor.h"
1.16 #include "razor-internal.h"
1.17 -
1.18 -/**
1.19 - * razor_path_add_root:
1.20 - *
1.21 - * Adds a root to a path. path must be an absolute pathname. In POSIX
1.22 - * environments this is equivalent to the concationation of root and path.
1.23 - * In Microsoft Windows an adjustment may need to be made for a drive letter
1.24 - * in path (which will be dropped).
1.25 - *
1.26 - * Returns: The new pathname.
1.27 - **/
1.28 -RAZOR_EXPORT char *razor_path_add_root(const char *path, const char *root)
1.29 -{
1.30 - if (root && *root)
1.31 - return razor_concat(root, SKIP_DRIVE_LETTER(path), NULL);
1.32 - else
1.33 - return strdup(path);
1.34 -}
1.35 -
1.36 -#if 0
1.37 -
1.38 -/*
1.39 - * This should work, but for some reason PathCreateFromUrlW()
1.40 - * treats the percent-encoded bytes as being in CP 850 rather
1.41 - * than UTF-8 as expected even if we set the codepage.
1.42 - */
1.43 -RAZOR_EXPORT char *razor_path_from_url(const char *url)
1.44 -{
1.45 - UINT saved_cp;
1.46 - HRESULT result;
1.47 - DWORD len = MAX_PATH;
1.48 - wchar_t *url16;
1.49 - wchar_t path16[MAX_PATH];
1.50 - char *path;
1.51 -
1.52 - url16 = razor_utf8_to_utf16(url, -1);
1.53 -
1.54 - saved_cp = GetConsoleCP();
1.55 - SetConsoleCP(CP_UTF8);
1.56 -
1.57 - result = PathCreateFromUrlW(url16, path16, &len, NULL);
1.58 -
1.59 - SetConsoleCP(saved_cp);
1.60 -
1.61 - if (result == S_OK)
1.62 - path = razor_utf16_to_utf8(path16, len);
1.63 - else
1.64 - path = NULL;
1.65 -
1.66 - free(url16);
1.67 -
1.68 - return path;
1.69 -}
1.70 -
1.71 -#else
1.72 -
1.73 -#ifdef MSWIN_API
1.74 -static int is_ascii_letter(char c)
1.75 -{
1.76 - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
1.77 -}
1.78 -#endif
1.79 -
1.80 -static int xdigit_value(char c)
1.81 -{
1.82 - if (c >= '0' && c <= '9')
1.83 - return c - '0';
1.84 - else
1.85 - return (c | 0x20) - 'a' + 10;
1.86 -}
1.87 +#include "uri.h"
1.88
1.89 static int valid_unicode(unsigned unicode)
1.90 {
1.91 @@ -101,54 +33,74 @@
1.92 return unicode < 0xD800 || (unicode >= 0xE000 && unicode < 0x110000);
1.93 }
1.94
1.95 -RAZOR_EXPORT char *razor_path_from_url(const char *url)
1.96 +char *razor_path_from_parsed_uri(const struct razor_uri *ru,
1.97 + struct razor_error **error)
1.98 {
1.99 int continuation_bytes = 0;
1.100 - char *path, *p;
1.101 + char *path, *p, *s, *uri;
1.102 unsigned char c;
1.103 unsigned unicode;
1.104
1.105 - if (strncmp(url, "file://", 7) == 0)
1.106 - url += 7;
1.107 - else
1.108 + if (!ru->scheme) {
1.109 + uri = razor_uri_recompose(ru);
1.110 + razor_set_error(error, RAZOR_GENERAL_ERROR,
1.111 + RAZOR_GENERAL_ERROR_BAD_URI, uri,
1.112 + "URI does not include a scheme");
1.113 + free(uri);
1.114 return NULL;
1.115 + }
1.116
1.117 - if (strncmp(url, "localhost/", 10) == 0)
1.118 - url += 9;
1.119 - else if (strncmp(url, "/", 1) != 0)
1.120 + if (strcmp(ru->scheme, "file")) {
1.121 + uri = razor_uri_recompose(ru);
1.122 + razor_set_error(error, RAZOR_GENERAL_ERROR,
1.123 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI, uri,
1.124 + "Not a file URI");
1.125 + free(uri);
1.126 return NULL;
1.127 + }
1.128
1.129 + if (ru->host && *ru->host && strcmp(ru->host, "localhost") ||
1.130 + ru->userinfo || ru->port) {
1.131 + uri = razor_uri_recompose(ru);
1.132 + razor_set_error(error, RAZOR_GENERAL_ERROR,
1.133 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI, uri,
1.134 + "URI refers to a non-local file");
1.135 + free(uri);
1.136 + return NULL;
1.137 + }
1.138 +
1.139 + s = ru->path;
1.140 #ifdef MSWIN_API
1.141 /*
1.142 - * Under MS-Windows, file:///c:/xxx maps to c:/xxx
1.143 + * Under MS-Windows, a path of /c:/xxx maps to c:/xxx
1.144 * Note that PathCreateFromUrl converts / to \ as well.
1.145 */
1.146 - if (is_ascii_letter(url[1]) && url[2] == ':' && url[3] == '/')
1.147 - url++;
1.148 + if (s[0] == '/' && is_alpha(s[1]) && s[2] == ':' && s[3] == '/')
1.149 + s++;
1.150 #endif
1.151
1.152 - p = path = malloc(strlen(url) + 1);
1.153 + p = path = malloc(strlen(s) + 1);
1.154
1.155 - while(*url) {
1.156 - if (*url >= 0x7F || *url < 0x20) {
1.157 - free(path);
1.158 - return NULL;
1.159 - } else if (*url != '%') {
1.160 - if (continuation_bytes) {
1.161 - free(path);
1.162 - return NULL;
1.163 - } else
1.164 - *p++ = *url++;
1.165 - } else if (isxdigit(url[1]) && isxdigit(url[2])) {
1.166 - c = xdigit_value(url[1]) * 16 + xdigit_value(url[2]);
1.167 - if (c == '/') {
1.168 - free(path);
1.169 - return NULL;
1.170 - } else if (!continuation_bytes) {
1.171 - if (c >= 0xF5 || c == 0xC0 || c == 0xC1) {
1.172 - free(path);
1.173 - return NULL;
1.174 - } else if (c >= 0xF0) {
1.175 + while (*s) {
1.176 + if (*s >= 0x7F || *s < 0x20)
1.177 + break;
1.178 + else if (*s != '%') {
1.179 + if (continuation_bytes)
1.180 + break;
1.181 + else
1.182 + *p++ = *s++;
1.183 + } else {
1.184 + c = pchar_get_char(s);
1.185 +#ifdef MSWIN_API
1.186 + if (c == '/' || c == '\\')
1.187 +#else
1.188 + if (c == '/')
1.189 +#endif
1.190 + break;
1.191 + else if (!continuation_bytes) {
1.192 + if (c >= 0xF5 || c == 0xC0 || c == 0xC1)
1.193 + break;
1.194 + else if (c >= 0xF0) {
1.195 unicode = c & 7;
1.196 continuation_bytes = 3;
1.197 } else if (c >= 0xE0) {
1.198 @@ -158,29 +110,28 @@
1.199 unicode = c & 1;
1.200 continuation_bytes = 1;
1.201 }
1.202 - } else if ((c & 0xC0) != 0x80) {
1.203 - free(path);
1.204 - return NULL;
1.205 - } else {
1.206 + } else if ((c & 0xC0) != 0x80)
1.207 + break;
1.208 + else {
1.209 unicode <<= 6;
1.210 unicode |= (c & 0x3F);
1.211
1.212 if (!--continuation_bytes &&
1.213 - !valid_unicode(unicode)) {
1.214 - free(path);
1.215 - return NULL;
1.216 - }
1.217 + !valid_unicode(unicode))
1.218 + break;
1.219 }
1.220
1.221 *p++ = c;
1.222 - url += 3;
1.223 - } else {
1.224 - free(path);
1.225 - return NULL;
1.226 + s += 3;
1.227 }
1.228 }
1.229
1.230 - if (continuation_bytes) {
1.231 + if (*s || continuation_bytes) {
1.232 + uri = razor_uri_recompose(ru);
1.233 + razor_set_error(error, RAZOR_GENERAL_ERROR,
1.234 + RAZOR_GENERAL_ERROR_BAD_URI,
1.235 + uri, "Illegal character in file URI path");
1.236 + free(uri);
1.237 free(path);
1.238 return NULL;
1.239 }
1.240 @@ -190,4 +141,72 @@
1.241 return realloc(path, p - path);
1.242 }
1.243
1.244 -#endif /* 0 */
1.245 +RAZOR_EXPORT char *razor_path_from_uri(const char *uri,
1.246 + struct razor_error **error)
1.247 +{
1.248 + struct razor_uri ru;
1.249 + char *path;
1.250 +
1.251 + if (razor_uri_parse(&ru, uri, error))
1.252 + return NULL;
1.253 +
1.254 + path = razor_path_from_parsed_uri(&ru, error);
1.255 +
1.256 + razor_uri_destroy(&ru);
1.257 +
1.258 + return path;
1.259 +}
1.260 +
1.261 +RAZOR_EXPORT char *razor_path_to_uri(const char *path)
1.262 +{
1.263 + char *uri, *p;
1.264 +
1.265 + uri = malloc(6 + 3 * strlen(path) + 1);
1.266 +
1.267 + strcpy(uri, "file:");
1.268 +
1.269 + p = uri + 5;
1.270 +
1.271 +#ifdef MSWIN_API
1.272 + /*
1.273 + * Under MS-Windows, c:/xxx maps to a path of /c:/xxx
1.274 + */
1.275 + if (is_alpha(path[0]) && path[1] == ':' && path[2] == '/')
1.276 + *p++ = '/';
1.277 +#endif
1.278 +
1.279 + while(*path) {
1.280 + if (*path == '/' || is_unreserved(*path) ||
1.281 + is_sub_delim(*path) || *path == ':' || *path == '@')
1.282 + *p++ = *path;
1.283 +#ifdef MSWIN_API
1.284 + else if (*path == '\\')
1.285 + *p++ = '/';
1.286 +#endif
1.287 + else {
1.288 + *p++ = '%';
1.289 + *p++ = "0123456789ABCDEF"[(*(unsigned char *)path)/16];
1.290 + *p++ = "0123456789ABCDEF"[(*(unsigned char *)path)%16];
1.291 + }
1.292 + path++;
1.293 + }
1.294 + *p++ = '\0';
1.295 +
1.296 + return realloc(uri, p - uri);
1.297 +}
1.298 +
1.299 +RAZOR_EXPORT char *
1.300 +razor_path_relative_to_uri(const char *uri, const char *path,
1.301 + struct razor_error **error)
1.302 +{
1.303 + char *rel_uri, *result;
1.304 +
1.305 + /* Strictly wrong if uri isn't a file URI, but probably okay */
1.306 + rel_uri = razor_path_to_uri(path);
1.307 +
1.308 + result = razor_resolve_uri_root(uri, rel_uri + 5, 1, error);
1.309 +
1.310 + free(rel_uri);
1.311 +
1.312 + return result;
1.313 +}