librazor/path.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Jun 11 17:56:48 2016 +0100 (2016-06-11)
changeset 474 7442b30ecaae
child 475 008c75a5e08d
permissions -rw-r--r--
Added tag 0.6.3 for changeset 2e8a0b26d579
ali@459
     1
/*
ali@459
     2
 * Copyright (C) 2014  J. Ali Harlow <ali@juiblex.co.uk>
ali@459
     3
 *
ali@459
     4
 * This program is free software; you can redistribute it and/or modify
ali@459
     5
 * it under the terms of the GNU General Public License as published by
ali@459
     6
 * the Free Software Foundation; either version 2 of the License, or
ali@459
     7
 * (at your option) any later version.
ali@459
     8
 *
ali@459
     9
 * This program is distributed in the hope that it will be useful,
ali@459
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ali@459
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ali@459
    12
 * GNU General Public License for more details.
ali@459
    13
 *
ali@459
    14
 * You should have received a copy of the GNU General Public License along
ali@459
    15
 * with this program; if not, write to the Free Software Foundation, Inc.,
ali@459
    16
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ali@459
    17
 */
ali@459
    18
ali@459
    19
#include "config.h"
ali@459
    20
#include <stdlib.h>
ali@459
    21
#include <string.h>
ali@459
    22
#include "razor.h"
ali@459
    23
#include "razor-internal.h"
ali@459
    24
ali@459
    25
/**
ali@459
    26
 * razor_path_add_root:
ali@459
    27
 *
ali@459
    28
 * Adds a root to a path. path must be an absolute pathname. In POSIX
ali@459
    29
 * environments this is equivalent to the concationation of root and path.
ali@459
    30
 * In Microsoft Windows an adjustment may need to be made for a drive letter
ali@459
    31
 * in path (which will be dropped).
ali@459
    32
 *
ali@459
    33
 * Returns: The new pathname.
ali@459
    34
 **/
ali@459
    35
RAZOR_EXPORT char *razor_path_add_root(const char *path, const char *root)
ali@459
    36
{
ali@459
    37
	if (root && *root)
ali@459
    38
		return razor_concat(root, SKIP_DRIVE_LETTER(path), NULL);
ali@459
    39
	else
ali@459
    40
		return strdup(path);
ali@459
    41
}
ali@459
    42
ali@459
    43
#if 0
ali@459
    44
ali@459
    45
/*
ali@459
    46
 * This should work, but for some reason PathCreateFromUrlW()
ali@459
    47
 * treats the percent-encoded bytes as being in CP 850 rather
ali@459
    48
 * than UTF-8 as expected even if we set the codepage.
ali@459
    49
 */
ali@459
    50
RAZOR_EXPORT char *razor_path_from_url(const char *url)
ali@459
    51
{
ali@459
    52
	UINT saved_cp;
ali@459
    53
	HRESULT result;
ali@459
    54
	DWORD len = MAX_PATH;
ali@459
    55
	wchar_t *url16;
ali@459
    56
	wchar_t path16[MAX_PATH];
ali@459
    57
	char *path;
ali@459
    58
ali@459
    59
	url16 = razor_utf8_to_utf16(url, -1);
ali@459
    60
ali@459
    61
	saved_cp = GetConsoleCP();
ali@459
    62
	SetConsoleCP(CP_UTF8);
ali@459
    63
ali@459
    64
	result = PathCreateFromUrlW(url16, path16, &len, NULL);
ali@459
    65
ali@459
    66
	SetConsoleCP(saved_cp);
ali@459
    67
ali@459
    68
	if (result == S_OK)
ali@459
    69
		path = razor_utf16_to_utf8(path16, len);
ali@459
    70
	else
ali@459
    71
		path = NULL;
ali@459
    72
ali@459
    73
	free(url16);
ali@459
    74
ali@459
    75
	return path;
ali@459
    76
}
ali@459
    77
ali@459
    78
#else
ali@459
    79
ali@459
    80
#ifdef MSWIN_API
ali@459
    81
static int is_ascii_letter(char c)
ali@459
    82
{
ali@459
    83
	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
ali@459
    84
}
ali@459
    85
#endif
ali@459
    86
ali@459
    87
static int xdigit_value(char c)
ali@459
    88
{
ali@459
    89
	if (c >= '0' && c <= '9')
ali@459
    90
		return c - '0';
ali@459
    91
	else
ali@459
    92
		return (c | 0x20) - 'a' + 10;
ali@459
    93
}
ali@459
    94
ali@459
    95
static int valid_unicode(unsigned unicode)
ali@459
    96
{
ali@459
    97
	/*
ali@459
    98
	 * Within the U+0000..U+10FFFF range defined by RFC3629
ali@459
    99
	 * but not in the U+D800..U+DFFF range prohibited in UTF-8.
ali@459
   100
	 */
ali@459
   101
	return unicode < 0xD800 || (unicode >= 0xE000 && unicode < 0x110000);
ali@459
   102
}
ali@459
   103
ali@459
   104
RAZOR_EXPORT char *razor_path_from_url(const char *url)
ali@459
   105
{
ali@459
   106
	int continuation_bytes = 0;
ali@459
   107
	char *path, *p;
ali@459
   108
	unsigned char c;
ali@459
   109
	unsigned unicode;
ali@459
   110
ali@459
   111
	if (strncmp(url, "file://", 7) == 0)
ali@459
   112
		url += 7;
ali@459
   113
	else
ali@459
   114
		return NULL;
ali@459
   115
ali@459
   116
	if (strncmp(url, "localhost/", 10) == 0)
ali@459
   117
		url += 9;
ali@459
   118
	else if (strncmp(url, "/", 1) != 0)
ali@459
   119
		return NULL;
ali@459
   120
ali@459
   121
#ifdef MSWIN_API
ali@459
   122
	/*
ali@459
   123
	 * Under MS-Windows, file:///c:/xxx maps to c:/xxx
ali@459
   124
	 * Note that PathCreateFromUrl converts / to \ as well.
ali@459
   125
	 */
ali@459
   126
	if (is_ascii_letter(url[1]) && url[2] == ':' && url[3] == '/')
ali@459
   127
		url++;
ali@459
   128
#endif
ali@459
   129
ali@459
   130
	p = path = malloc(strlen(url) + 1);
ali@459
   131
ali@459
   132
	while(*url) {
ali@459
   133
		if (*url >= 0x7F || *url < 0x20) {
ali@459
   134
			free(path);
ali@459
   135
			return NULL;
ali@459
   136
		} else if (*url != '%') {
ali@459
   137
			if (continuation_bytes) {
ali@459
   138
				free(path);
ali@459
   139
				return NULL;
ali@459
   140
			} else
ali@459
   141
				*p++ = *url++;
ali@459
   142
		} else if (isxdigit(url[1]) && isxdigit(url[2])) {
ali@459
   143
			c = xdigit_value(url[1]) * 16 + xdigit_value(url[2]);
ali@459
   144
			if (c == '/') {
ali@459
   145
				free(path);
ali@459
   146
				return NULL;
ali@459
   147
			} else if (!continuation_bytes) {
ali@459
   148
				if (c >= 0xF5 || c == 0xC0 || c == 0xC1) {
ali@459
   149
					free(path);
ali@459
   150
					return NULL;
ali@459
   151
				} else if (c >= 0xF0) {
ali@459
   152
					unicode = c & 7;
ali@459
   153
					continuation_bytes = 3;
ali@459
   154
				} else if (c >= 0xE0) {
ali@459
   155
					unicode = c & 3;
ali@459
   156
					continuation_bytes = 2;
ali@459
   157
				} else if (c >= 0xC0) {
ali@459
   158
					unicode = c & 1;
ali@459
   159
					continuation_bytes = 1;
ali@459
   160
				}
ali@459
   161
			} else if ((c & 0xC0) != 0x80) {
ali@459
   162
				free(path);
ali@459
   163
				return NULL;
ali@459
   164
			} else {
ali@459
   165
				unicode <<= 6;
ali@459
   166
				unicode |= (c & 0x3F);
ali@459
   167
ali@459
   168
				if (!--continuation_bytes &&
ali@459
   169
				    !valid_unicode(unicode)) {
ali@459
   170
					free(path);
ali@459
   171
					return NULL;
ali@459
   172
				}
ali@459
   173
			}
ali@459
   174
ali@459
   175
			*p++ = c;
ali@459
   176
			url += 3;
ali@459
   177
		} else {
ali@459
   178
			free(path);
ali@459
   179
			return NULL;
ali@459
   180
		}
ali@459
   181
	}
ali@459
   182
ali@459
   183
	if (continuation_bytes) {
ali@459
   184
		free(path);
ali@459
   185
		return NULL;
ali@459
   186
	}
ali@459
   187
ali@459
   188
	*p++ = '\0';
ali@459
   189
ali@459
   190
	return realloc(path, p - path);
ali@459
   191
}
ali@459
   192
ali@459
   193
#endif	/* 0 */