librazor/path.c
changeset 469 4aaa4b4b29e5
child 475 008c75a5e08d
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/librazor/path.c	Fri Apr 15 16:58:07 2016 +0100
     1.3 @@ -0,0 +1,193 @@
     1.4 +/*
     1.5 + * Copyright (C) 2014  J. Ali Harlow <ali@juiblex.co.uk>
     1.6 + *
     1.7 + * This program is free software; you can redistribute it and/or modify
     1.8 + * it under the terms of the GNU General Public License as published by
     1.9 + * the Free Software Foundation; either version 2 of the License, or
    1.10 + * (at your option) any later version.
    1.11 + *
    1.12 + * This program is distributed in the hope that it will be useful,
    1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.15 + * GNU General Public License for more details.
    1.16 + *
    1.17 + * You should have received a copy of the GNU General Public License along
    1.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
    1.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    1.20 + */
    1.21 +
    1.22 +#include "config.h"
    1.23 +#include <stdlib.h>
    1.24 +#include <string.h>
    1.25 +#include "razor.h"
    1.26 +#include "razor-internal.h"
    1.27 +
    1.28 +/**
    1.29 + * razor_path_add_root:
    1.30 + *
    1.31 + * Adds a root to a path. path must be an absolute pathname. In POSIX
    1.32 + * environments this is equivalent to the concationation of root and path.
    1.33 + * In Microsoft Windows an adjustment may need to be made for a drive letter
    1.34 + * in path (which will be dropped).
    1.35 + *
    1.36 + * Returns: The new pathname.
    1.37 + **/
    1.38 +RAZOR_EXPORT char *razor_path_add_root(const char *path, const char *root)
    1.39 +{
    1.40 +	if (root && *root)
    1.41 +		return razor_concat(root, SKIP_DRIVE_LETTER(path), NULL);
    1.42 +	else
    1.43 +		return strdup(path);
    1.44 +}
    1.45 +
    1.46 +#if 0
    1.47 +
    1.48 +/*
    1.49 + * This should work, but for some reason PathCreateFromUrlW()
    1.50 + * treats the percent-encoded bytes as being in CP 850 rather
    1.51 + * than UTF-8 as expected even if we set the codepage.
    1.52 + */
    1.53 +RAZOR_EXPORT char *razor_path_from_url(const char *url)
    1.54 +{
    1.55 +	UINT saved_cp;
    1.56 +	HRESULT result;
    1.57 +	DWORD len = MAX_PATH;
    1.58 +	wchar_t *url16;
    1.59 +	wchar_t path16[MAX_PATH];
    1.60 +	char *path;
    1.61 +
    1.62 +	url16 = razor_utf8_to_utf16(url, -1);
    1.63 +
    1.64 +	saved_cp = GetConsoleCP();
    1.65 +	SetConsoleCP(CP_UTF8);
    1.66 +
    1.67 +	result = PathCreateFromUrlW(url16, path16, &len, NULL);
    1.68 +
    1.69 +	SetConsoleCP(saved_cp);
    1.70 +
    1.71 +	if (result == S_OK)
    1.72 +		path = razor_utf16_to_utf8(path16, len);
    1.73 +	else
    1.74 +		path = NULL;
    1.75 +
    1.76 +	free(url16);
    1.77 +
    1.78 +	return path;
    1.79 +}
    1.80 +
    1.81 +#else
    1.82 +
    1.83 +#ifdef MSWIN_API
    1.84 +static int is_ascii_letter(char c)
    1.85 +{
    1.86 +	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
    1.87 +}
    1.88 +#endif
    1.89 +
    1.90 +static int xdigit_value(char c)
    1.91 +{
    1.92 +	if (c >= '0' && c <= '9')
    1.93 +		return c - '0';
    1.94 +	else
    1.95 +		return (c | 0x20) - 'a' + 10;
    1.96 +}
    1.97 +
    1.98 +static int valid_unicode(unsigned unicode)
    1.99 +{
   1.100 +	/*
   1.101 +	 * Within the U+0000..U+10FFFF range defined by RFC3629
   1.102 +	 * but not in the U+D800..U+DFFF range prohibited in UTF-8.
   1.103 +	 */
   1.104 +	return unicode < 0xD800 || (unicode >= 0xE000 && unicode < 0x110000);
   1.105 +}
   1.106 +
   1.107 +RAZOR_EXPORT char *razor_path_from_url(const char *url)
   1.108 +{
   1.109 +	int continuation_bytes = 0;
   1.110 +	char *path, *p;
   1.111 +	unsigned char c;
   1.112 +	unsigned unicode;
   1.113 +
   1.114 +	if (strncmp(url, "file://", 7) == 0)
   1.115 +		url += 7;
   1.116 +	else
   1.117 +		return NULL;
   1.118 +
   1.119 +	if (strncmp(url, "localhost/", 10) == 0)
   1.120 +		url += 9;
   1.121 +	else if (strncmp(url, "/", 1) != 0)
   1.122 +		return NULL;
   1.123 +
   1.124 +#ifdef MSWIN_API
   1.125 +	/*
   1.126 +	 * Under MS-Windows, file:///c:/xxx maps to c:/xxx
   1.127 +	 * Note that PathCreateFromUrl converts / to \ as well.
   1.128 +	 */
   1.129 +	if (is_ascii_letter(url[1]) && url[2] == ':' && url[3] == '/')
   1.130 +		url++;
   1.131 +#endif
   1.132 +
   1.133 +	p = path = malloc(strlen(url) + 1);
   1.134 +
   1.135 +	while(*url) {
   1.136 +		if (*url >= 0x7F || *url < 0x20) {
   1.137 +			free(path);
   1.138 +			return NULL;
   1.139 +		} else if (*url != '%') {
   1.140 +			if (continuation_bytes) {
   1.141 +				free(path);
   1.142 +				return NULL;
   1.143 +			} else
   1.144 +				*p++ = *url++;
   1.145 +		} else if (isxdigit(url[1]) && isxdigit(url[2])) {
   1.146 +			c = xdigit_value(url[1]) * 16 + xdigit_value(url[2]);
   1.147 +			if (c == '/') {
   1.148 +				free(path);
   1.149 +				return NULL;
   1.150 +			} else if (!continuation_bytes) {
   1.151 +				if (c >= 0xF5 || c == 0xC0 || c == 0xC1) {
   1.152 +					free(path);
   1.153 +					return NULL;
   1.154 +				} else if (c >= 0xF0) {
   1.155 +					unicode = c & 7;
   1.156 +					continuation_bytes = 3;
   1.157 +				} else if (c >= 0xE0) {
   1.158 +					unicode = c & 3;
   1.159 +					continuation_bytes = 2;
   1.160 +				} else if (c >= 0xC0) {
   1.161 +					unicode = c & 1;
   1.162 +					continuation_bytes = 1;
   1.163 +				}
   1.164 +			} else if ((c & 0xC0) != 0x80) {
   1.165 +				free(path);
   1.166 +				return NULL;
   1.167 +			} else {
   1.168 +				unicode <<= 6;
   1.169 +				unicode |= (c & 0x3F);
   1.170 +
   1.171 +				if (!--continuation_bytes &&
   1.172 +				    !valid_unicode(unicode)) {
   1.173 +					free(path);
   1.174 +					return NULL;
   1.175 +				}
   1.176 +			}
   1.177 +
   1.178 +			*p++ = c;
   1.179 +			url += 3;
   1.180 +		} else {
   1.181 +			free(path);
   1.182 +			return NULL;
   1.183 +		}
   1.184 +	}
   1.185 +
   1.186 +	if (continuation_bytes) {
   1.187 +		free(path);
   1.188 +		return NULL;
   1.189 +	}
   1.190 +
   1.191 +	*p++ = '\0';
   1.192 +
   1.193 +	return realloc(path, p - path);
   1.194 +}
   1.195 +
   1.196 +#endif	/* 0 */