]> git.proxmox.com Git - ceph.git/blame - ceph/src/arrow/cpp/src/arrow/vendored/uriparser/UriFile.c
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / cpp / src / arrow / vendored / uriparser / UriFile.c
CommitLineData
1d09f67e
TL
1/*
2 * uriparser - RFC 3986 URI parsing library
3 *
4 * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
5 * Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.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 "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 "UriDefsAnsi.h"
57# else
58# include "UriDefsUnicode.h"
59# include <wchar.h>
60# endif
61
62
63
64#ifndef URI_DOXYGEN
65# include "Uri.h"
66#endif
67
68
69
70#include <stdlib.h> /* for size_t, avoiding stddef.h for older MSVCs */
71
72
73
74static URI_INLINE int URI_FUNC(FilenameToUriString)(const URI_CHAR * filename,
75 URI_CHAR * uriString, UriBool fromUnix) {
76 const URI_CHAR * input = filename;
77 const URI_CHAR * lastSep = input - 1;
78 UriBool firstSegment = URI_TRUE;
79 URI_CHAR * output = uriString;
80 UriBool absolute;
81 UriBool is_windows_network;
82
83 if ((filename == NULL) || (uriString == NULL)) {
84 return URI_ERROR_NULL;
85 }
86
87 is_windows_network = (filename[0] == _UT('\\')) && (filename[1] == _UT('\\'));
88 absolute = fromUnix
89 ? (filename[0] == _UT('/'))
90 : (((filename[0] != _UT('\0')) && (filename[1] == _UT(':')))
91 || is_windows_network);
92
93 if (absolute) {
94 const URI_CHAR * const prefix = fromUnix
95 ? _UT("file://")
96 : is_windows_network
97 ? _UT("file:")
98 : _UT("file:///");
99 const size_t prefixLen = URI_STRLEN(prefix);
100
101 /* Copy prefix */
102 memcpy(uriString, prefix, prefixLen * sizeof(URI_CHAR));
103 output += prefixLen;
104 }
105
106 /* Copy and escape on the fly */
107 for (;;) {
108 if ((input[0] == _UT('\0'))
109 || (fromUnix && input[0] == _UT('/'))
110 || (!fromUnix && input[0] == _UT('\\'))) {
111 /* Copy text after last separator */
112 if (lastSep + 1 < input) {
113 if (!fromUnix && absolute && (firstSegment == URI_TRUE)) {
114 /* Quick hack to not convert "C:" to "C%3A" */
115 const int charsToCopy = (int)(input - (lastSep + 1));
116 memcpy(output, lastSep + 1, charsToCopy * sizeof(URI_CHAR));
117 output += charsToCopy;
118 } else {
119 output = URI_FUNC(EscapeEx)(lastSep + 1, input, output,
120 URI_FALSE, URI_FALSE);
121 }
122 }
123 firstSegment = URI_FALSE;
124 }
125
126 if (input[0] == _UT('\0')) {
127 output[0] = _UT('\0');
128 break;
129 } else if (fromUnix && (input[0] == _UT('/'))) {
130 /* Copy separators unmodified */
131 output[0] = _UT('/');
132 output++;
133 lastSep = input;
134 } else if (!fromUnix && (input[0] == _UT('\\'))) {
135 /* Convert backslashes to forward slashes */
136 output[0] = _UT('/');
137 output++;
138 lastSep = input;
139 }
140 input++;
141 }
142
143 return URI_SUCCESS;
144}
145
146
147
148static URI_INLINE int URI_FUNC(UriStringToFilename)(const URI_CHAR * uriString,
149 URI_CHAR * filename, UriBool toUnix) {
150 if ((uriString == NULL) || (filename == NULL)) {
151 return URI_ERROR_NULL;
152 }
153
154 {
155 const UriBool file_unknown_slashes =
156 URI_STRNCMP(uriString, _UT("file:"), URI_STRLEN(_UT("file:"))) == 0;
157 const UriBool file_one_or_more_slashes = file_unknown_slashes
158 && (URI_STRNCMP(uriString, _UT("file:/"), URI_STRLEN(_UT("file:/"))) == 0);
159 const UriBool file_two_or_more_slashes = file_one_or_more_slashes
160 && (URI_STRNCMP(uriString, _UT("file://"), URI_STRLEN(_UT("file://"))) == 0);
161 const UriBool file_three_or_more_slashes = file_two_or_more_slashes
162 && (URI_STRNCMP(uriString, _UT("file:///"), URI_STRLEN(_UT("file:///"))) == 0);
163
164 const size_t charsToSkip = file_two_or_more_slashes
165 ? file_three_or_more_slashes
166 ? toUnix
167 /* file:///bin/bash */
168 ? URI_STRLEN(_UT("file://"))
169 /* file:///E:/Documents%20and%20Settings */
170 : URI_STRLEN(_UT("file:///"))
171 /* file://Server01/Letter.txt */
172 : URI_STRLEN(_UT("file://"))
173 : ((file_one_or_more_slashes && toUnix)
174 /* file:/bin/bash */
175 /* https://tools.ietf.org/html/rfc8089#appendix-B */
176 ? URI_STRLEN(_UT("file:"))
177 : ((! toUnix && file_unknown_slashes && ! file_one_or_more_slashes)
178 /* file:c:/path/to/file */
179 /* https://tools.ietf.org/html/rfc8089#appendix-E.2 */
180 ? URI_STRLEN(_UT("file:"))
181 : 0));
182 const size_t charsToCopy = URI_STRLEN(uriString + charsToSkip) + 1;
183
184 const UriBool is_windows_network_with_authority =
185 (toUnix == URI_FALSE)
186 && file_two_or_more_slashes
187 && ! file_three_or_more_slashes;
188
189 URI_CHAR * const unescape_target = is_windows_network_with_authority
190 ? (filename + 2)
191 : filename;
192
193 if (is_windows_network_with_authority) {
194 filename[0] = '\\';
195 filename[1] = '\\';
196 }
197
198 memcpy(unescape_target, uriString + charsToSkip, charsToCopy * sizeof(URI_CHAR));
199 URI_FUNC(UnescapeInPlaceEx)(filename, URI_FALSE, URI_BR_DONT_TOUCH);
200 }
201
202 /* Convert forward slashes to backslashes */
203 if (!toUnix) {
204 URI_CHAR * walker = filename;
205 while (walker[0] != _UT('\0')) {
206 if (walker[0] == _UT('/')) {
207 walker[0] = _UT('\\');
208 }
209 walker++;
210 }
211 }
212
213 return URI_SUCCESS;
214}
215
216
217
218int URI_FUNC(UnixFilenameToUriString)(const URI_CHAR * filename, URI_CHAR * uriString) {
219 return URI_FUNC(FilenameToUriString)(filename, uriString, URI_TRUE);
220}
221
222
223
224int URI_FUNC(WindowsFilenameToUriString)(const URI_CHAR * filename, URI_CHAR * uriString) {
225 return URI_FUNC(FilenameToUriString)(filename, uriString, URI_FALSE);
226}
227
228
229
230int URI_FUNC(UriStringToUnixFilename)(const URI_CHAR * uriString, URI_CHAR * filename) {
231 return URI_FUNC(UriStringToFilename)(uriString, filename, URI_TRUE);
232}
233
234
235
236int URI_FUNC(UriStringToWindowsFilename)(const URI_CHAR * uriString, URI_CHAR * filename) {
237 return URI_FUNC(UriStringToFilename)(uriString, filename, URI_FALSE);
238}
239
240
241
242#endif