Coverage Report

Created: 2025-12-14 06:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/ext/uri/uriparser/src/UriFile.c
Line
Count
Source
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
 *     1. Redistributions  of  source  code   must  retain  the  above
13
 *        copyright notice, this list  of conditions and the following
14
 *        disclaimer.
15
 *
16
 *     2. 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
 *     3. Neither the  name of the  copyright holder nor the  names of
22
 *        its 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
30
 * THE  COPYRIGHT HOLDER  OR CONTRIBUTORS  BE LIABLE  FOR ANY  DIRECT,
31
 * INDIRECT, 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
#  ifndef URI_DOXYGEN
63
#    include <uriparser/Uri.h>
64
#  endif
65
66
#  include <stdlib.h> /* for size_t, avoiding stddef.h for older MSVCs */
67
68
static URI_INLINE int URI_FUNC(FilenameToUriString)(const URI_CHAR * filename,
69
                                                    URI_CHAR * uriString,
70
0
                                                    UriBool fromUnix) {
71
0
    const URI_CHAR * input = filename;
72
0
    const URI_CHAR * lastSep = input - 1;
73
0
    UriBool firstSegment = URI_TRUE;
74
0
    URI_CHAR * output = uriString;
75
0
    UriBool absolute;
76
0
    UriBool is_windows_network;
77
78
0
    if ((filename == NULL) || (uriString == NULL)) {
79
0
        return URI_ERROR_NULL;
80
0
    }
81
82
0
    is_windows_network = (filename[0] == _UT('\\')) && (filename[1] == _UT('\\'));
83
0
    absolute = fromUnix ? (filename[0] == _UT('/'))
84
0
                        : (((filename[0] != _UT('\0')) && (filename[1] == _UT(':')))
85
0
                           || is_windows_network);
86
87
0
    if (absolute) {
88
0
        const URI_CHAR * const prefix = fromUnix             ? _UT("file://")
89
0
                                        : is_windows_network ? _UT("file:")
90
0
                                                             : _UT("file:///");
91
0
        const size_t prefixLen = URI_STRLEN(prefix);
92
93
        /* Copy prefix */
94
0
        memcpy(uriString, prefix, prefixLen * sizeof(URI_CHAR));
95
0
        output += prefixLen;
96
0
    }
97
98
    /* Copy and escape on the fly */
99
0
    for (;;) {
100
0
        if ((input[0] == _UT('\0')) || (fromUnix && input[0] == _UT('/'))
101
0
            || (!fromUnix && input[0] == _UT('\\'))) {
102
            /* Copy text after last separator */
103
0
            if (lastSep + 1 < input) {
104
0
                if (!fromUnix && absolute && (firstSegment == URI_TRUE)) {
105
                    /* Quick hack to not convert "C:" to "C%3A" */
106
0
                    const int charsToCopy = (int)(input - (lastSep + 1));
107
0
                    memcpy(output, lastSep + 1, charsToCopy * sizeof(URI_CHAR));
108
0
                    output += charsToCopy;
109
0
                } else {
110
0
                    output = URI_FUNC(EscapeEx)(lastSep + 1, input, output, URI_FALSE,
111
0
                                                URI_FALSE);
112
0
                }
113
0
            }
114
0
            firstSegment = URI_FALSE;
115
0
        }
116
117
0
        if (input[0] == _UT('\0')) {
118
0
            output[0] = _UT('\0');
119
0
            break;
120
0
        } else if (fromUnix && (input[0] == _UT('/'))) {
121
            /* Copy separators unmodified */
122
0
            output[0] = _UT('/');
123
0
            output++;
124
0
            lastSep = input;
125
0
        } else if (!fromUnix && (input[0] == _UT('\\'))) {
126
            /* Convert backslashes to forward slashes */
127
0
            output[0] = _UT('/');
128
0
            output++;
129
0
            lastSep = input;
130
0
        }
131
0
        input++;
132
0
    }
133
134
0
    return URI_SUCCESS;
135
0
}
Unexecuted instantiation: UriFile.c:uriFilenameToUriStringA
Unexecuted instantiation: UriFile.c:uriFilenameToUriStringW
136
137
static URI_INLINE int URI_FUNC(UriStringToFilename)(const URI_CHAR * uriString,
138
0
                                                    URI_CHAR * filename, UriBool toUnix) {
139
0
    if ((uriString == NULL) || (filename == NULL)) {
140
0
        return URI_ERROR_NULL;
141
0
    }
142
143
0
    const UriBool file_unknown_slashes =
144
0
        URI_STRNCMP(uriString, _UT("file:"), URI_STRLEN(_UT("file:"))) == 0;
145
0
    const UriBool file_one_or_more_slashes =
146
0
        file_unknown_slashes
147
0
        && (URI_STRNCMP(uriString, _UT("file:/"), URI_STRLEN(_UT("file:/"))) == 0);
148
0
    const UriBool file_two_or_more_slashes =
149
0
        file_one_or_more_slashes
150
0
        && (URI_STRNCMP(uriString, _UT("file://"), URI_STRLEN(_UT("file://"))) == 0);
151
0
    const UriBool file_three_or_more_slashes =
152
0
        file_two_or_more_slashes
153
0
        && (URI_STRNCMP(uriString, _UT("file:///"), URI_STRLEN(_UT("file:///"))) == 0);
154
155
0
    const size_t charsToSkip =
156
0
        file_two_or_more_slashes
157
0
            ? file_three_or_more_slashes ? toUnix
158
                                               /* file:///bin/bash */
159
0
                                               ? URI_STRLEN(_UT("file://"))
160
                                               /* file:///E:/Documents%20and%20Settings */
161
0
                                               : URI_STRLEN(_UT("file:///"))
162
                                         /* file://Server01/Letter.txt */
163
0
                                         : URI_STRLEN(_UT("file://"))
164
0
            : ((file_one_or_more_slashes && toUnix)
165
                   /* file:/bin/bash */
166
                   /* https://tools.ietf.org/html/rfc8089#appendix-B */
167
0
                   ? URI_STRLEN(_UT("file:"))
168
0
                   : ((!toUnix && file_unknown_slashes && !file_one_or_more_slashes)
169
                          /* file:c:/path/to/file */
170
                          /* https://tools.ietf.org/html/rfc8089#appendix-E.2 */
171
0
                          ? URI_STRLEN(_UT("file:"))
172
0
                          : 0));
173
0
    const size_t charsToCopy = URI_STRLEN(uriString + charsToSkip) + 1;
174
175
0
    const UriBool is_windows_network_with_authority =
176
0
        (toUnix == URI_FALSE) && file_two_or_more_slashes && !file_three_or_more_slashes;
177
178
0
    URI_CHAR * const unescape_target =
179
0
        is_windows_network_with_authority ? (filename + 2) : filename;
180
181
0
    if (is_windows_network_with_authority) {
182
0
        filename[0] = '\\';
183
0
        filename[1] = '\\';
184
0
    }
185
186
0
    memcpy(unescape_target, uriString + charsToSkip, charsToCopy * sizeof(URI_CHAR));
187
0
    URI_FUNC(UnescapeInPlaceEx)(filename, URI_FALSE, URI_BR_DONT_TOUCH);
188
189
    /* Convert forward slashes to backslashes */
190
0
    if (!toUnix) {
191
0
        URI_CHAR * walker = filename;
192
0
        while (walker[0] != _UT('\0')) {
193
0
            if (walker[0] == _UT('/')) {
194
0
                walker[0] = _UT('\\');
195
0
            }
196
0
            walker++;
197
0
        }
198
0
    }
199
200
0
    return URI_SUCCESS;
201
0
}
Unexecuted instantiation: UriFile.c:uriUriStringToFilenameA
Unexecuted instantiation: UriFile.c:uriUriStringToFilenameW
202
203
0
int URI_FUNC(UnixFilenameToUriString)(const URI_CHAR * filename, URI_CHAR * uriString) {
204
0
    return URI_FUNC(FilenameToUriString)(filename, uriString, URI_TRUE);
205
0
}
Unexecuted instantiation: uriUnixFilenameToUriStringA
Unexecuted instantiation: uriUnixFilenameToUriStringW
206
207
int URI_FUNC(WindowsFilenameToUriString)(const URI_CHAR * filename,
208
0
                                         URI_CHAR * uriString) {
209
0
    return URI_FUNC(FilenameToUriString)(filename, uriString, URI_FALSE);
210
0
}
Unexecuted instantiation: uriWindowsFilenameToUriStringA
Unexecuted instantiation: uriWindowsFilenameToUriStringW
211
212
0
int URI_FUNC(UriStringToUnixFilename)(const URI_CHAR * uriString, URI_CHAR * filename) {
213
0
    return URI_FUNC(UriStringToFilename)(uriString, filename, URI_TRUE);
214
0
}
Unexecuted instantiation: uriUriStringToUnixFilenameA
Unexecuted instantiation: uriUriStringToUnixFilenameW
215
216
int URI_FUNC(UriStringToWindowsFilename)(const URI_CHAR * uriString,
217
0
                                         URI_CHAR * filename) {
218
0
    return URI_FUNC(UriStringToFilename)(uriString, filename, URI_FALSE);
219
0
}
Unexecuted instantiation: uriUriStringToWindowsFilenameA
Unexecuted instantiation: uriUriStringToWindowsFilenameW
220
221
#endif