summaryrefslogtreecommitdiffstats
path: root/plugins/uriparser/UriFile.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/uriparser/UriFile.c')
-rw-r--r--plugins/uriparser/UriFile.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/plugins/uriparser/UriFile.c b/plugins/uriparser/UriFile.c
new file mode 100644
index 0000000..9cf788f
--- /dev/null
+++ b/plugins/uriparser/UriFile.c
@@ -0,0 +1,226 @@
1/*
2 * uriparser - RFC 3986 URI parsing library
3 *
4 * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
5 * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.org>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer.
15 *
16 * * Redistributions in binary form must reproduce the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer in the documentation and/or other materials
19 * provided with the distribution.
20 *
21 * * Neither the name of the <ORGANIZATION> nor the names of its
22 * contributors may be used to endorse or promote products
23 * derived from this software without specific prior written
24 * permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
37 * OF THE POSSIBILITY OF SUCH DAMAGE.
38 */
39
40/* What encodings are enabled? */
41#include <uriparser/UriDefsConfig.h>
42#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
43/* Include SELF twice */
44# ifdef URI_ENABLE_ANSI
45# define URI_PASS_ANSI 1
46# include "UriFile.c"
47# undef URI_PASS_ANSI
48# endif
49# ifdef URI_ENABLE_UNICODE
50# define URI_PASS_UNICODE 1
51# include "UriFile.c"
52# undef URI_PASS_UNICODE
53# endif
54#else
55# ifdef URI_PASS_ANSI
56# include <uriparser/UriDefsAnsi.h>
57# else
58# include <uriparser/UriDefsUnicode.h>
59# include <wchar.h>
60# endif
61
62
63
64#ifndef URI_DOXYGEN
65# include <uriparser/Uri.h>
66#endif
67
68
69
70static URI_INLINE int URI_FUNC(FilenameToUriString)(const URI_CHAR * filename,
71 URI_CHAR * uriString, UriBool fromUnix) {
72 const URI_CHAR * input = filename;
73 const URI_CHAR * lastSep = input - 1;
74 UriBool firstSegment = URI_TRUE;
75 URI_CHAR * output = uriString;
76 UriBool absolute;
77 UriBool is_windows_network;
78
79 if ((filename == NULL) || (uriString == NULL)) {
80 return URI_ERROR_NULL;
81 }
82
83 is_windows_network = (filename[0] == _UT('\\')) && (filename[1] == _UT('\\'));
84 absolute = fromUnix
85 ? (filename[0] == _UT('/'))
86 : ((filename[0] != _UT('\0')) && (filename[1] == _UT(':'))
87 || is_windows_network);
88
89 if (absolute) {
90 const URI_CHAR * const prefix = fromUnix
91 ? _UT("file://")
92 : is_windows_network
93 ? _UT("file:")
94 : _UT("file:///");
95 const int prefixLen = URI_STRLEN(prefix);
96
97 /* Copy prefix */
98 memcpy(uriString, prefix, prefixLen * sizeof(URI_CHAR));
99 output += prefixLen;
100 }
101
102 /* Copy and escape on the fly */
103 for (;;) {
104 if ((input[0] == _UT('\0'))
105 || (fromUnix && input[0] == _UT('/'))
106 || (!fromUnix && input[0] == _UT('\\'))) {
107 /* Copy text after last seperator */
108 if (lastSep + 1 < input) {
109 if (!fromUnix && absolute && (firstSegment == URI_TRUE)) {
110 /* Quick hack to not convert "C:" to "C%3A" */
111 const int charsToCopy = (int)(input - (lastSep + 1));
112 memcpy(output, lastSep + 1, charsToCopy * sizeof(URI_CHAR));
113 output += charsToCopy;
114 } else {
115 output = URI_FUNC(EscapeEx)(lastSep + 1, input, output,
116 URI_FALSE, URI_FALSE);
117 }
118 }
119 firstSegment = URI_FALSE;
120 }
121
122 if (input[0] == _UT('\0')) {
123 output[0] = _UT('\0');
124 break;
125 } else if (fromUnix && (input[0] == _UT('/'))) {
126 /* Copy separators unmodified */
127 output[0] = _UT('/');
128 output++;
129 lastSep = input;
130 } else if (!fromUnix && (input[0] == _UT('\\'))) {
131 /* Convert backslashes to forward slashes */
132 output[0] = _UT('/');
133 output++;
134 lastSep = input;
135 }
136 input++;
137 }
138
139 return URI_SUCCESS;
140}
141
142
143
144static URI_INLINE int URI_FUNC(UriStringToFilename)(const URI_CHAR * uriString,
145 URI_CHAR * filename, UriBool toUnix) {
146 if ((uriString == NULL) || (filename == NULL)) {
147 return URI_ERROR_NULL;
148 }
149
150 {
151 const UriBool file_two_slashes =
152 URI_STRNCMP(uriString, _UT("file://"), URI_STRLEN(_UT("file://"))) == 0;
153 const UriBool file_three_slashes = file_two_slashes
154 && (URI_STRNCMP(uriString, _UT("file:///"), URI_STRLEN(_UT("file:///"))) == 0);
155
156 const size_t charsToSkip = file_two_slashes
157 ? file_three_slashes
158 ? toUnix
159 /* file:///bin/bash */
160 ? URI_STRLEN(_UT("file://"))
161 /* file:///E:/Documents%20and%20Settings */
162 : URI_STRLEN(_UT("file:///"))
163 /* file://Server01/Letter.txt */
164 : URI_STRLEN(_UT("file://"))
165 : 0;
166 const size_t charsToCopy = URI_STRLEN(uriString + charsToSkip) + 1;
167
168 const UriBool is_windows_network_with_authority =
169 (toUnix == URI_FALSE)
170 && file_two_slashes
171 && ! file_three_slashes;
172
173 URI_CHAR * const unescape_target = is_windows_network_with_authority
174 ? (filename + 2)
175 : filename;
176
177 if (is_windows_network_with_authority) {
178 filename[0] = '\\';
179 filename[1] = '\\';
180 }
181
182 memcpy(unescape_target, uriString + charsToSkip, charsToCopy * sizeof(URI_CHAR));
183 URI_FUNC(UnescapeInPlaceEx)(filename, URI_FALSE, URI_BR_DONT_TOUCH);
184 }
185
186 /* Convert forward slashes to backslashes */
187 if (!toUnix) {
188 URI_CHAR * walker = filename;
189 while (walker[0] != _UT('\0')) {
190 if (walker[0] == _UT('/')) {
191 walker[0] = _UT('\\');
192 }
193 walker++;
194 }
195 }
196
197 return URI_SUCCESS;
198}
199
200
201
202int URI_FUNC(UnixFilenameToUriString)(const URI_CHAR * filename, URI_CHAR * uriString) {
203 return URI_FUNC(FilenameToUriString)(filename, uriString, URI_TRUE);
204}
205
206
207
208int URI_FUNC(WindowsFilenameToUriString)(const URI_CHAR * filename, URI_CHAR * uriString) {
209 return URI_FUNC(FilenameToUriString)(filename, uriString, URI_FALSE);
210}
211
212
213
214int URI_FUNC(UriStringToUnixFilename)(const URI_CHAR * uriString, URI_CHAR * filename) {
215 return URI_FUNC(UriStringToFilename)(uriString, filename, URI_TRUE);
216}
217
218
219
220int URI_FUNC(UriStringToWindowsFilename)(const URI_CHAR * uriString, URI_CHAR * filename) {
221 return URI_FUNC(UriStringToFilename)(uriString, filename, URI_FALSE);
222}
223
224
225
226#endif