Absolute File Name: | /home/qt/qt5_coco/qt5/qtbase/src/corelib/io/qurl.cpp |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | /**************************************************************************** | - | ||||||||||||||||||||||||
2 | ** | - | ||||||||||||||||||||||||
3 | ** Copyright (C) 2016 The Qt Company Ltd. | - | ||||||||||||||||||||||||
4 | ** Copyright (C) 2016 Intel Corporation. | - | ||||||||||||||||||||||||
5 | ** Contact: https://www.qt.io/licensing/ | - | ||||||||||||||||||||||||
6 | ** | - | ||||||||||||||||||||||||
7 | ** This file is part of the QtCore module of the Qt Toolkit. | - | ||||||||||||||||||||||||
8 | ** | - | ||||||||||||||||||||||||
9 | ** $QT_BEGIN_LICENSE:LGPL$ | - | ||||||||||||||||||||||||
10 | ** Commercial License Usage | - | ||||||||||||||||||||||||
11 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||||||||||||||||||||
12 | ** accordance with the commercial license agreement provided with the | - | ||||||||||||||||||||||||
13 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||||||||||||||||||||
14 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||||||||||||||||||||
15 | ** and conditions see https://www.qt.io/terms-conditions. For further | - | ||||||||||||||||||||||||
16 | ** information use the contact form at https://www.qt.io/contact-us. | - | ||||||||||||||||||||||||
17 | ** | - | ||||||||||||||||||||||||
18 | ** GNU Lesser General Public License Usage | - | ||||||||||||||||||||||||
19 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||||||||||||||||||||
20 | ** General Public License version 3 as published by the Free Software | - | ||||||||||||||||||||||||
21 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | - | ||||||||||||||||||||||||
22 | ** packaging of this file. Please review the following information to | - | ||||||||||||||||||||||||
23 | ** ensure the GNU Lesser General Public License version 3 requirements | - | ||||||||||||||||||||||||
24 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | - | ||||||||||||||||||||||||
25 | ** | - | ||||||||||||||||||||||||
26 | ** GNU General Public License Usage | - | ||||||||||||||||||||||||
27 | ** Alternatively, this file may be used under the terms of the GNU | - | ||||||||||||||||||||||||
28 | ** General Public License version 2.0 or (at your option) the GNU General | - | ||||||||||||||||||||||||
29 | ** Public license version 3 or any later version approved by the KDE Free | - | ||||||||||||||||||||||||
30 | ** Qt Foundation. The licenses are as published by the Free Software | - | ||||||||||||||||||||||||
31 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | - | ||||||||||||||||||||||||
32 | ** included in the packaging of this file. Please review the following | - | ||||||||||||||||||||||||
33 | ** information to ensure the GNU General Public License requirements will | - | ||||||||||||||||||||||||
34 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | - | ||||||||||||||||||||||||
35 | ** https://www.gnu.org/licenses/gpl-3.0.html. | - | ||||||||||||||||||||||||
36 | ** | - | ||||||||||||||||||||||||
37 | ** $QT_END_LICENSE$ | - | ||||||||||||||||||||||||
38 | ** | - | ||||||||||||||||||||||||
39 | ****************************************************************************/ | - | ||||||||||||||||||||||||
40 | - | |||||||||||||||||||||||||
41 | /*! | - | ||||||||||||||||||||||||
42 | \class QUrl | - | ||||||||||||||||||||||||
43 | \inmodule QtCore | - | ||||||||||||||||||||||||
44 | - | |||||||||||||||||||||||||
45 | \brief The QUrl class provides a convenient interface for working | - | ||||||||||||||||||||||||
46 | with URLs. | - | ||||||||||||||||||||||||
47 | - | |||||||||||||||||||||||||
48 | \reentrant | - | ||||||||||||||||||||||||
49 | \ingroup io | - | ||||||||||||||||||||||||
50 | \ingroup network | - | ||||||||||||||||||||||||
51 | \ingroup shared | - | ||||||||||||||||||||||||
52 | - | |||||||||||||||||||||||||
53 | - | |||||||||||||||||||||||||
54 | It can parse and construct URLs in both encoded and unencoded | - | ||||||||||||||||||||||||
55 | form. QUrl also has support for internationalized domain names | - | ||||||||||||||||||||||||
56 | (IDNs). | - | ||||||||||||||||||||||||
57 | - | |||||||||||||||||||||||||
58 | The most common way to use QUrl is to initialize it via the | - | ||||||||||||||||||||||||
59 | constructor by passing a QString. Otherwise, setUrl() can also | - | ||||||||||||||||||||||||
60 | be used. | - | ||||||||||||||||||||||||
61 | - | |||||||||||||||||||||||||
62 | URLs can be represented in two forms: encoded or unencoded. The | - | ||||||||||||||||||||||||
63 | unencoded representation is suitable for showing to users, but | - | ||||||||||||||||||||||||
64 | the encoded representation is typically what you would send to | - | ||||||||||||||||||||||||
65 | a web server. For example, the unencoded URL | - | ||||||||||||||||||||||||
66 | "http://bühler.example.com/List of applicants.xml" | - | ||||||||||||||||||||||||
67 | would be sent to the server as | - | ||||||||||||||||||||||||
68 | "http://xn--bhler-kva.example.com/List%20of%20applicants.xml". | - | ||||||||||||||||||||||||
69 | - | |||||||||||||||||||||||||
70 | A URL can also be constructed piece by piece by calling | - | ||||||||||||||||||||||||
71 | setScheme(), setUserName(), setPassword(), setHost(), setPort(), | - | ||||||||||||||||||||||||
72 | setPath(), setQuery() and setFragment(). Some convenience | - | ||||||||||||||||||||||||
73 | functions are also available: setAuthority() sets the user name, | - | ||||||||||||||||||||||||
74 | password, host and port. setUserInfo() sets the user name and | - | ||||||||||||||||||||||||
75 | password at once. | - | ||||||||||||||||||||||||
76 | - | |||||||||||||||||||||||||
77 | Call isValid() to check if the URL is valid. This can be done at any point | - | ||||||||||||||||||||||||
78 | during the constructing of a URL. If isValid() returns \c false, you should | - | ||||||||||||||||||||||||
79 | clear() the URL before proceeding, or start over by parsing a new URL with | - | ||||||||||||||||||||||||
80 | setUrl(). | - | ||||||||||||||||||||||||
81 | - | |||||||||||||||||||||||||
82 | Constructing a query is particularly convenient through the use of the \l | - | ||||||||||||||||||||||||
83 | QUrlQuery class and its methods QUrlQuery::setQueryItems(), | - | ||||||||||||||||||||||||
84 | QUrlQuery::addQueryItem() and QUrlQuery::removeQueryItem(). Use | - | ||||||||||||||||||||||||
85 | QUrlQuery::setQueryDelimiters() to customize the delimiters used for | - | ||||||||||||||||||||||||
86 | generating the query string. | - | ||||||||||||||||||||||||
87 | - | |||||||||||||||||||||||||
88 | For the convenience of generating encoded URL strings or query | - | ||||||||||||||||||||||||
89 | strings, there are two static functions called | - | ||||||||||||||||||||||||
90 | fromPercentEncoding() and toPercentEncoding() which deal with | - | ||||||||||||||||||||||||
91 | percent encoding and decoding of QString objects. | - | ||||||||||||||||||||||||
92 | - | |||||||||||||||||||||||||
93 | Calling isRelative() will tell whether or not the URL is | - | ||||||||||||||||||||||||
94 | relative. A relative URL can be resolved by passing it as argument | - | ||||||||||||||||||||||||
95 | to resolved(), which returns an absolute URL. isParentOf() is used | - | ||||||||||||||||||||||||
96 | for determining whether one URL is a parent of another. | - | ||||||||||||||||||||||||
97 | - | |||||||||||||||||||||||||
98 | fromLocalFile() constructs a QUrl by parsing a local | - | ||||||||||||||||||||||||
99 | file path. toLocalFile() converts a URL to a local file path. | - | ||||||||||||||||||||||||
100 | - | |||||||||||||||||||||||||
101 | The human readable representation of the URL is fetched with | - | ||||||||||||||||||||||||
102 | toString(). This representation is appropriate for displaying a | - | ||||||||||||||||||||||||
103 | URL to a user in unencoded form. The encoded form however, as | - | ||||||||||||||||||||||||
104 | returned by toEncoded(), is for internal use, passing to web | - | ||||||||||||||||||||||||
105 | servers, mail clients and so on. Both forms are technically correct | - | ||||||||||||||||||||||||
106 | and represent the same URL unambiguously -- in fact, passing either | - | ||||||||||||||||||||||||
107 | form to QUrl's constructor or to setUrl() will yield the same QUrl | - | ||||||||||||||||||||||||
108 | object. | - | ||||||||||||||||||||||||
109 | - | |||||||||||||||||||||||||
110 | QUrl conforms to the URI specification from | - | ||||||||||||||||||||||||
111 | \l{RFC 3986} (Uniform Resource Identifier: Generic Syntax), and includes | - | ||||||||||||||||||||||||
112 | scheme extensions from \l{RFC 1738} (Uniform Resource Locators). Case | - | ||||||||||||||||||||||||
113 | folding rules in QUrl conform to \l{RFC 3491} (Nameprep: A Stringprep | - | ||||||||||||||||||||||||
114 | Profile for Internationalized Domain Names (IDN)). It is also compatible with the | - | ||||||||||||||||||||||||
115 | \l{http://freedesktop.org/wiki/Specifications/file-uri-spec/}{file URI specification} | - | ||||||||||||||||||||||||
116 | from freedesktop.org, provided that the locale encodes file names using | - | ||||||||||||||||||||||||
117 | UTF-8 (required by IDN). | - | ||||||||||||||||||||||||
118 | - | |||||||||||||||||||||||||
119 | \section2 Error checking | - | ||||||||||||||||||||||||
120 | - | |||||||||||||||||||||||||
121 | QUrl is capable of detecting many errors in URLs while parsing it or when | - | ||||||||||||||||||||||||
122 | components of the URL are set with individual setter methods (like | - | ||||||||||||||||||||||||
123 | setScheme(), setHost() or setPath()). If the parsing or setter function is | - | ||||||||||||||||||||||||
124 | successful, any previously recorded error conditions will be discarded. | - | ||||||||||||||||||||||||
125 | - | |||||||||||||||||||||||||
126 | By default, QUrl setter methods operate in QUrl::TolerantMode, which means | - | ||||||||||||||||||||||||
127 | they accept some common mistakes and mis-representation of data. An | - | ||||||||||||||||||||||||
128 | alternate method of parsing is QUrl::StrictMode, which applies further | - | ||||||||||||||||||||||||
129 | checks. See QUrl::ParsingMode for a description of the difference of the | - | ||||||||||||||||||||||||
130 | parsing modes. | - | ||||||||||||||||||||||||
131 | - | |||||||||||||||||||||||||
132 | QUrl only checks for conformance with the URL specification. It does not | - | ||||||||||||||||||||||||
133 | try to verify that high-level protocol URLs are in the format they are | - | ||||||||||||||||||||||||
134 | expected to be by handlers elsewhere. For example, the following URIs are | - | ||||||||||||||||||||||||
135 | all considered valid by QUrl, even if they do not make sense when used: | - | ||||||||||||||||||||||||
136 | - | |||||||||||||||||||||||||
137 | \list | - | ||||||||||||||||||||||||
138 | \li "http:/filename.html" | - | ||||||||||||||||||||||||
139 | \li "mailto://example.com" | - | ||||||||||||||||||||||||
140 | \endlist | - | ||||||||||||||||||||||||
141 | - | |||||||||||||||||||||||||
142 | When the parser encounters an error, it signals the event by making | - | ||||||||||||||||||||||||
143 | isValid() return false and toString() / toEncoded() return an empty string. | - | ||||||||||||||||||||||||
144 | If it is necessary to show the user the reason why the URL failed to parse, | - | ||||||||||||||||||||||||
145 | the error condition can be obtained from QUrl by calling errorString(). | - | ||||||||||||||||||||||||
146 | Note that this message is highly technical and may not make sense to | - | ||||||||||||||||||||||||
147 | end-users. | - | ||||||||||||||||||||||||
148 | - | |||||||||||||||||||||||||
149 | QUrl is capable of recording only one error condition. If more than one | - | ||||||||||||||||||||||||
150 | error is found, it is undefined which error is reported. | - | ||||||||||||||||||||||||
151 | - | |||||||||||||||||||||||||
152 | \section2 Character Conversions | - | ||||||||||||||||||||||||
153 | - | |||||||||||||||||||||||||
154 | Follow these rules to avoid erroneous character conversion when | - | ||||||||||||||||||||||||
155 | dealing with URLs and strings: | - | ||||||||||||||||||||||||
156 | - | |||||||||||||||||||||||||
157 | \list | - | ||||||||||||||||||||||||
158 | \li When creating a QString to contain a URL from a QByteArray or a | - | ||||||||||||||||||||||||
159 | char*, always use QString::fromUtf8(). | - | ||||||||||||||||||||||||
160 | \endlist | - | ||||||||||||||||||||||||
161 | */ | - | ||||||||||||||||||||||||
162 | - | |||||||||||||||||||||||||
163 | /*! | - | ||||||||||||||||||||||||
164 | \enum QUrl::ParsingMode | - | ||||||||||||||||||||||||
165 | - | |||||||||||||||||||||||||
166 | The parsing mode controls the way QUrl parses strings. | - | ||||||||||||||||||||||||
167 | - | |||||||||||||||||||||||||
168 | \value TolerantMode QUrl will try to correct some common errors in URLs. | - | ||||||||||||||||||||||||
169 | This mode is useful for parsing URLs coming from sources | - | ||||||||||||||||||||||||
170 | not known to be strictly standards-conforming. | - | ||||||||||||||||||||||||
171 | - | |||||||||||||||||||||||||
172 | \value StrictMode Only valid URLs are accepted. This mode is useful for | - | ||||||||||||||||||||||||
173 | general URL validation. | - | ||||||||||||||||||||||||
174 | - | |||||||||||||||||||||||||
175 | \value DecodedMode QUrl will interpret the URL component in the fully-decoded form, | - | ||||||||||||||||||||||||
176 | where percent characters stand for themselves, not as the beginning | - | ||||||||||||||||||||||||
177 | of a percent-encoded sequence. This mode is only valid for the | - | ||||||||||||||||||||||||
178 | setters setting components of a URL; it is not permitted in | - | ||||||||||||||||||||||||
179 | the QUrl constructor, in fromEncoded() or in setUrl(). | - | ||||||||||||||||||||||||
180 | For more information on this mode, see the documentation for | - | ||||||||||||||||||||||||
181 | \l {QUrl::ComponentFormattingOption}{QUrl::FullyDecoded}. | - | ||||||||||||||||||||||||
182 | - | |||||||||||||||||||||||||
183 | In TolerantMode, the parser has the following behaviour: | - | ||||||||||||||||||||||||
184 | - | |||||||||||||||||||||||||
185 | \list | - | ||||||||||||||||||||||||
186 | - | |||||||||||||||||||||||||
187 | \li Spaces and "%20": unencoded space characters will be accepted and will | - | ||||||||||||||||||||||||
188 | be treated as equivalent to "%20". | - | ||||||||||||||||||||||||
189 | - | |||||||||||||||||||||||||
190 | \li Single "%" characters: Any occurrences of a percent character "%" not | - | ||||||||||||||||||||||||
191 | followed by exactly two hexadecimal characters (e.g., "13% coverage.html") | - | ||||||||||||||||||||||||
192 | will be replaced by "%25". Note that one lone "%" character will trigger | - | ||||||||||||||||||||||||
193 | the correction mode for all percent characters. | - | ||||||||||||||||||||||||
194 | - | |||||||||||||||||||||||||
195 | \li Reserved and unreserved characters: An encoded URL should only | - | ||||||||||||||||||||||||
196 | contain a few characters as literals; all other characters should | - | ||||||||||||||||||||||||
197 | be percent-encoded. In TolerantMode, these characters will be | - | ||||||||||||||||||||||||
198 | accepted if they are found in the URL: | - | ||||||||||||||||||||||||
199 | space / double-quote / "<" / ">" / "\" / | - | ||||||||||||||||||||||||
200 | "^" / "`" / "{" / "|" / "}" | - | ||||||||||||||||||||||||
201 | Those same characters can be decoded again by passing QUrl::DecodeReserved | - | ||||||||||||||||||||||||
202 | to toString() or toEncoded(). In the getters of individual components, | - | ||||||||||||||||||||||||
203 | those characters are often returned in decoded form. | - | ||||||||||||||||||||||||
204 | - | |||||||||||||||||||||||||
205 | \endlist | - | ||||||||||||||||||||||||
206 | - | |||||||||||||||||||||||||
207 | When in StrictMode, if a parsing error is found, isValid() will return \c | - | ||||||||||||||||||||||||
208 | false and errorString() will return a message describing the error. | - | ||||||||||||||||||||||||
209 | If more than one error is detected, it is undefined which error gets | - | ||||||||||||||||||||||||
210 | reported. | - | ||||||||||||||||||||||||
211 | - | |||||||||||||||||||||||||
212 | Note that TolerantMode is not usually enough for parsing user input, which | - | ||||||||||||||||||||||||
213 | often contains more errors and expectations than the parser can deal with. | - | ||||||||||||||||||||||||
214 | When dealing with data coming directly from the user -- as opposed to data | - | ||||||||||||||||||||||||
215 | coming from data-transfer sources, such as other programs -- it is | - | ||||||||||||||||||||||||
216 | recommended to use fromUserInput(). | - | ||||||||||||||||||||||||
217 | - | |||||||||||||||||||||||||
218 | \sa fromUserInput(), setUrl(), toString(), toEncoded(), QUrl::FormattingOptions | - | ||||||||||||||||||||||||
219 | */ | - | ||||||||||||||||||||||||
220 | - | |||||||||||||||||||||||||
221 | /*! | - | ||||||||||||||||||||||||
222 | \enum QUrl::UrlFormattingOption | - | ||||||||||||||||||||||||
223 | - | |||||||||||||||||||||||||
224 | The formatting options define how the URL is formatted when written out | - | ||||||||||||||||||||||||
225 | as text. | - | ||||||||||||||||||||||||
226 | - | |||||||||||||||||||||||||
227 | \value None The format of the URL is unchanged. | - | ||||||||||||||||||||||||
228 | \value RemoveScheme The scheme is removed from the URL. | - | ||||||||||||||||||||||||
229 | \value RemovePassword Any password in the URL is removed. | - | ||||||||||||||||||||||||
230 | \value RemoveUserInfo Any user information in the URL is removed. | - | ||||||||||||||||||||||||
231 | \value RemovePort Any specified port is removed from the URL. | - | ||||||||||||||||||||||||
232 | \value RemoveAuthority | - | ||||||||||||||||||||||||
233 | \value RemovePath The URL's path is removed, leaving only the scheme, | - | ||||||||||||||||||||||||
234 | host address, and port (if present). | - | ||||||||||||||||||||||||
235 | \value RemoveQuery The query part of the URL (following a '?' character) | - | ||||||||||||||||||||||||
236 | is removed. | - | ||||||||||||||||||||||||
237 | \value RemoveFragment | - | ||||||||||||||||||||||||
238 | \value RemoveFilename The filename (i.e. everything after the last '/' in the path) is removed. | - | ||||||||||||||||||||||||
239 | The trailing '/' is kept, unless StripTrailingSlash is set. | - | ||||||||||||||||||||||||
240 | Only valid if RemovePath is not set. | - | ||||||||||||||||||||||||
241 | \value PreferLocalFile If the URL is a local file according to isLocalFile() | - | ||||||||||||||||||||||||
242 | and contains no query or fragment, a local file path is returned. | - | ||||||||||||||||||||||||
243 | \value StripTrailingSlash The trailing slash is removed if one is present. | - | ||||||||||||||||||||||||
244 | \value NormalizePathSegments Modifies the path to remove redundant directory separators, | - | ||||||||||||||||||||||||
245 | and to resolve "."s and ".."s (as far as possible). | - | ||||||||||||||||||||||||
246 | - | |||||||||||||||||||||||||
247 | Note that the case folding rules in \l{RFC 3491}{Nameprep}, which QUrl | - | ||||||||||||||||||||||||
248 | conforms to, require host names to always be converted to lower case, | - | ||||||||||||||||||||||||
249 | regardless of the Qt::FormattingOptions used. | - | ||||||||||||||||||||||||
250 | - | |||||||||||||||||||||||||
251 | The options from QUrl::ComponentFormattingOptions are also possible. | - | ||||||||||||||||||||||||
252 | - | |||||||||||||||||||||||||
253 | \sa QUrl::ComponentFormattingOptions | - | ||||||||||||||||||||||||
254 | */ | - | ||||||||||||||||||||||||
255 | - | |||||||||||||||||||||||||
256 | /*! | - | ||||||||||||||||||||||||
257 | \enum QUrl::ComponentFormattingOption | - | ||||||||||||||||||||||||
258 | \since 5.0 | - | ||||||||||||||||||||||||
259 | - | |||||||||||||||||||||||||
260 | The component formatting options define how the components of an URL will | - | ||||||||||||||||||||||||
261 | be formatted when written out as text. They can be combined with the | - | ||||||||||||||||||||||||
262 | options from QUrl::FormattingOptions when used in toString() and | - | ||||||||||||||||||||||||
263 | toEncoded(). | - | ||||||||||||||||||||||||
264 | - | |||||||||||||||||||||||||
265 | \value PrettyDecoded The component is returned in a "pretty form", with | - | ||||||||||||||||||||||||
266 | most percent-encoded characters decoded. The exact | - | ||||||||||||||||||||||||
267 | behavior of PrettyDecoded varies from component to | - | ||||||||||||||||||||||||
268 | component and may also change from Qt release to Qt | - | ||||||||||||||||||||||||
269 | release. This is the default. | - | ||||||||||||||||||||||||
270 | - | |||||||||||||||||||||||||
271 | \value EncodeSpaces Leave space characters in their encoded form ("%20"). | - | ||||||||||||||||||||||||
272 | - | |||||||||||||||||||||||||
273 | \value EncodeUnicode Leave non-US-ASCII characters encoded in their UTF-8 | - | ||||||||||||||||||||||||
274 | percent-encoded form (e.g., "%C3%A9" for the U+00E9 | - | ||||||||||||||||||||||||
275 | codepoint, LATIN SMALL LETTER E WITH ACUTE). | - | ||||||||||||||||||||||||
276 | - | |||||||||||||||||||||||||
277 | \value EncodeDelimiters Leave certain delimiters in their encoded form, as | - | ||||||||||||||||||||||||
278 | would appear in the URL when the full URL is | - | ||||||||||||||||||||||||
279 | represented as text. The delimiters are affected | - | ||||||||||||||||||||||||
280 | by this option change from component to component. | - | ||||||||||||||||||||||||
281 | This flag has no effect in toString() or toEncoded(). | - | ||||||||||||||||||||||||
282 | - | |||||||||||||||||||||||||
283 | \value EncodeReserved Leave US-ASCII characters not permitted in the URL by | - | ||||||||||||||||||||||||
284 | the specification in their encoded form. This is the | - | ||||||||||||||||||||||||
285 | default on toString() and toEncoded(). | - | ||||||||||||||||||||||||
286 | - | |||||||||||||||||||||||||
287 | \value DecodeReserved Decode the US-ASCII characters that the URL specification | - | ||||||||||||||||||||||||
288 | does not allow to appear in the URL. This is the | - | ||||||||||||||||||||||||
289 | default on the getters of individual components. | - | ||||||||||||||||||||||||
290 | - | |||||||||||||||||||||||||
291 | \value FullyEncoded Leave all characters in their properly-encoded form, | - | ||||||||||||||||||||||||
292 | as this component would appear as part of a URL. When | - | ||||||||||||||||||||||||
293 | used with toString(), this produces a fully-compliant | - | ||||||||||||||||||||||||
294 | URL in QString form, exactly equal to the result of | - | ||||||||||||||||||||||||
295 | toEncoded() | - | ||||||||||||||||||||||||
296 | - | |||||||||||||||||||||||||
297 | \value FullyDecoded Attempt to decode as much as possible. For individual | - | ||||||||||||||||||||||||
298 | components of the URL, this decodes every percent | - | ||||||||||||||||||||||||
299 | encoding sequence, including control characters (U+0000 | - | ||||||||||||||||||||||||
300 | to U+001F) and UTF-8 sequences found in percent-encoded form. | - | ||||||||||||||||||||||||
301 | Use of this mode may cause data loss, see below for more information. | - | ||||||||||||||||||||||||
302 | - | |||||||||||||||||||||||||
303 | The values of EncodeReserved and DecodeReserved should not be used together | - | ||||||||||||||||||||||||
304 | in one call. The behavior is undefined if that happens. They are provided | - | ||||||||||||||||||||||||
305 | as separate values because the behavior of the "pretty mode" with regards | - | ||||||||||||||||||||||||
306 | to reserved characters is different on certain components and specially on | - | ||||||||||||||||||||||||
307 | the full URL. | - | ||||||||||||||||||||||||
308 | - | |||||||||||||||||||||||||
309 | \section2 Full decoding | - | ||||||||||||||||||||||||
310 | - | |||||||||||||||||||||||||
311 | The FullyDecoded mode is similar to the behavior of the functions returning | - | ||||||||||||||||||||||||
312 | QString in Qt 4.x, in that every character represents itself and never has | - | ||||||||||||||||||||||||
313 | any special meaning. This is true even for the percent character ('%'), | - | ||||||||||||||||||||||||
314 | which should be interpreted to mean a literal percent, not the beginning of | - | ||||||||||||||||||||||||
315 | a percent-encoded sequence. The same actual character, in all other | - | ||||||||||||||||||||||||
316 | decoding modes, is represented by the sequence "%25". | - | ||||||||||||||||||||||||
317 | - | |||||||||||||||||||||||||
318 | Whenever re-applying data obtained with QUrl::FullyDecoded into a QUrl, | - | ||||||||||||||||||||||||
319 | care must be taken to use the QUrl::DecodedMode parameter to the setters | - | ||||||||||||||||||||||||
320 | (like setPath() and setUserName()). Failure to do so may cause | - | ||||||||||||||||||||||||
321 | re-interpretation of the percent character ('%') as the beginning of a | - | ||||||||||||||||||||||||
322 | percent-encoded sequence. | - | ||||||||||||||||||||||||
323 | - | |||||||||||||||||||||||||
324 | This mode is quite useful when portions of a URL are used in a non-URL | - | ||||||||||||||||||||||||
325 | context. For example, to extract the username, password or file paths in an | - | ||||||||||||||||||||||||
326 | FTP client application, the FullyDecoded mode should be used. | - | ||||||||||||||||||||||||
327 | - | |||||||||||||||||||||||||
328 | This mode should be used with care, since there are two conditions that | - | ||||||||||||||||||||||||
329 | cannot be reliably represented in the returned QString. They are: | - | ||||||||||||||||||||||||
330 | - | |||||||||||||||||||||||||
331 | \list | - | ||||||||||||||||||||||||
332 | \li \b{Non-UTF-8 sequences:} URLs may contain sequences of | - | ||||||||||||||||||||||||
333 | percent-encoded characters that do not form valid UTF-8 sequences. Since | - | ||||||||||||||||||||||||
334 | URLs need to be decoded using UTF-8, any decoder failure will result in | - | ||||||||||||||||||||||||
335 | the QString containing one or more replacement characters where the | - | ||||||||||||||||||||||||
336 | sequence existed. | - | ||||||||||||||||||||||||
337 | - | |||||||||||||||||||||||||
338 | \li \b{Encoded delimiters:} URLs are also allowed to make a distinction | - | ||||||||||||||||||||||||
339 | between a delimiter found in its literal form and its equivalent in | - | ||||||||||||||||||||||||
340 | percent-encoded form. This is most commonly found in the query, but is | - | ||||||||||||||||||||||||
341 | permitted in most parts of the URL. | - | ||||||||||||||||||||||||
342 | \endlist | - | ||||||||||||||||||||||||
343 | - | |||||||||||||||||||||||||
344 | The following example illustrates the problem: | - | ||||||||||||||||||||||||
345 | - | |||||||||||||||||||||||||
346 | \code | - | ||||||||||||||||||||||||
347 | QUrl original("http://example.com/?q=a%2B%3Db%26c"); | - | ||||||||||||||||||||||||
348 | QUrl copy(original); | - | ||||||||||||||||||||||||
349 | copy.setQuery(copy.query(QUrl::FullyDecoded), QUrl::DecodedMode); | - | ||||||||||||||||||||||||
350 | - | |||||||||||||||||||||||||
351 | qDebug() << original.toString(); // prints: http://example.com/?q=a%2B%3Db%26c | - | ||||||||||||||||||||||||
352 | qDebug() << copy.toString(); // prints: http://example.com/?q=a+=b&c | - | ||||||||||||||||||||||||
353 | \endcode | - | ||||||||||||||||||||||||
354 | - | |||||||||||||||||||||||||
355 | If the two URLs were used via HTTP GET, the interpretation by the web | - | ||||||||||||||||||||||||
356 | server would probably be different. In the first case, it would interpret | - | ||||||||||||||||||||||||
357 | as one parameter, with a key of "q" and value "a+=b&c". In the second | - | ||||||||||||||||||||||||
358 | case, it would probably interpret as two parameters, one with a key of "q" | - | ||||||||||||||||||||||||
359 | and value "a =b", and the second with a key "c" and no value. | - | ||||||||||||||||||||||||
360 | - | |||||||||||||||||||||||||
361 | \sa QUrl::FormattingOptions | - | ||||||||||||||||||||||||
362 | */ | - | ||||||||||||||||||||||||
363 | - | |||||||||||||||||||||||||
364 | /*! | - | ||||||||||||||||||||||||
365 | \enum QUrl::UserInputResolutionOption | - | ||||||||||||||||||||||||
366 | \since 5.4 | - | ||||||||||||||||||||||||
367 | - | |||||||||||||||||||||||||
368 | The user input resolution options define how fromUserInput() should | - | ||||||||||||||||||||||||
369 | interpret strings that could either be a relative path or the short | - | ||||||||||||||||||||||||
370 | form of a HTTP URL. For instance \c{file.pl} can be either a local file | - | ||||||||||||||||||||||||
371 | or the URL \c{http://file.pl}. | - | ||||||||||||||||||||||||
372 | - | |||||||||||||||||||||||||
373 | \value DefaultResolution The default resolution mechanism is to check | - | ||||||||||||||||||||||||
374 | whether a local file exists, in the working | - | ||||||||||||||||||||||||
375 | directory given to fromUserInput, and only | - | ||||||||||||||||||||||||
376 | return a local path in that case. Otherwise a URL | - | ||||||||||||||||||||||||
377 | is assumed. | - | ||||||||||||||||||||||||
378 | \value AssumeLocalFile This option makes fromUserInput() always return | - | ||||||||||||||||||||||||
379 | a local path unless the input contains a scheme, such as | - | ||||||||||||||||||||||||
380 | \c{http://file.pl}. This is useful for applications | - | ||||||||||||||||||||||||
381 | such as text editors, which are able to create | - | ||||||||||||||||||||||||
382 | the file if it doesn't exist. | - | ||||||||||||||||||||||||
383 | - | |||||||||||||||||||||||||
384 | \sa fromUserInput() | - | ||||||||||||||||||||||||
385 | */ | - | ||||||||||||||||||||||||
386 | - | |||||||||||||||||||||||||
387 | /*! | - | ||||||||||||||||||||||||
388 | \fn QUrl::QUrl(QUrl &&other) | - | ||||||||||||||||||||||||
389 | - | |||||||||||||||||||||||||
390 | Move-constructs a QUrl instance, making it point at the same | - | ||||||||||||||||||||||||
391 | object that \a other was pointing to. | - | ||||||||||||||||||||||||
392 | - | |||||||||||||||||||||||||
393 | \since 5.2 | - | ||||||||||||||||||||||||
394 | */ | - | ||||||||||||||||||||||||
395 | - | |||||||||||||||||||||||||
396 | /*! | - | ||||||||||||||||||||||||
397 | \fn QUrl &QUrl::operator=(QUrl &&other) | - | ||||||||||||||||||||||||
398 | - | |||||||||||||||||||||||||
399 | Move-assigns \a other to this QUrl instance. | - | ||||||||||||||||||||||||
400 | - | |||||||||||||||||||||||||
401 | \since 5.2 | - | ||||||||||||||||||||||||
402 | */ | - | ||||||||||||||||||||||||
403 | - | |||||||||||||||||||||||||
404 | #include "qurl.h" | - | ||||||||||||||||||||||||
405 | #include "qurl_p.h" | - | ||||||||||||||||||||||||
406 | #include "qplatformdefs.h" | - | ||||||||||||||||||||||||
407 | #include "qstring.h" | - | ||||||||||||||||||||||||
408 | #include "qstringlist.h" | - | ||||||||||||||||||||||||
409 | #include "qdebug.h" | - | ||||||||||||||||||||||||
410 | #include "qhash.h" | - | ||||||||||||||||||||||||
411 | #include "qdir.h" // for QDir::fromNativeSeparators | - | ||||||||||||||||||||||||
412 | #include "qdatastream.h" | - | ||||||||||||||||||||||||
413 | #include "qtldurl_p.h" | - | ||||||||||||||||||||||||
414 | #include "private/qipaddress_p.h" | - | ||||||||||||||||||||||||
415 | #include "qurlquery.h" | - | ||||||||||||||||||||||||
416 | #if defined(Q_OS_WINCE_WM) | - | ||||||||||||||||||||||||
417 | #pragma optimize("g", off) | - | ||||||||||||||||||||||||
418 | #endif | - | ||||||||||||||||||||||||
419 | - | |||||||||||||||||||||||||
420 | QT_BEGIN_NAMESPACE | - | ||||||||||||||||||||||||
421 | extern QString qt_normalizePathSegments(const QString &name, bool allowUncPaths); // qdir.cpp | - | ||||||||||||||||||||||||
422 | - | |||||||||||||||||||||||||
423 | inline static bool isHex(char c) | - | ||||||||||||||||||||||||
424 | { | - | ||||||||||||||||||||||||
425 | c |= 0x20; | - | ||||||||||||||||||||||||
426 | return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'); executed 59 times by 2 tests: return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'); Executed by:
| 59 | ||||||||||||||||||||||||
427 | } | - | ||||||||||||||||||||||||
428 | - | |||||||||||||||||||||||||
429 | static inline QString ftpScheme() | - | ||||||||||||||||||||||||
430 | { | - | ||||||||||||||||||||||||
431 | return QStringLiteral("ftp"); executed 55 times by 2 tests: return ([]() -> QString { enum { Size = sizeof(u"" "ftp")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "ftp" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }()); Executed by:
executed 55 times by 2 tests: return qstring_literal_temp; Executed by:
| 55 | ||||||||||||||||||||||||
432 | } | - | ||||||||||||||||||||||||
433 | - | |||||||||||||||||||||||||
434 | static inline QString fileScheme() | - | ||||||||||||||||||||||||
435 | { | - | ||||||||||||||||||||||||
436 | return QStringLiteral("file"); executed 17440 times by 33 tests: return ([]() -> QString { enum { Size = sizeof(u"" "file")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "file" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }()); Executed by:
executed 17440 times by 33 tests: return qstring_literal_temp; Executed by:
| 17440 | ||||||||||||||||||||||||
437 | } | - | ||||||||||||||||||||||||
438 | - | |||||||||||||||||||||||||
439 | static inline QString webDavScheme() | - | ||||||||||||||||||||||||
440 | { | - | ||||||||||||||||||||||||
441 | return QStringLiteral("webdavs"); executed 1 time by 1 test: return ([]() -> QString { enum { Size = sizeof(u"" "webdavs")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "webdavs" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }()); Executed by:
executed 1 time by 1 test: return qstring_literal_temp; Executed by:
| 1 | ||||||||||||||||||||||||
442 | } | - | ||||||||||||||||||||||||
443 | - | |||||||||||||||||||||||||
444 | static inline QString webDavSslTag() | - | ||||||||||||||||||||||||
445 | { | - | ||||||||||||||||||||||||
446 | return QStringLiteral("@SSL"); executed 4 times by 1 test: return ([]() -> QString { enum { Size = sizeof(u"" "@SSL")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "@SSL" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }()); Executed by:
executed 4 times by 1 test: return qstring_literal_temp; Executed by:
| 4 | ||||||||||||||||||||||||
447 | } | - | ||||||||||||||||||||||||
448 | - | |||||||||||||||||||||||||
449 | #ifdef Q_COMPILER_CLASS_ENUM | - | ||||||||||||||||||||||||
450 | # define colon_uchar : uchar | - | ||||||||||||||||||||||||
451 | #else | - | ||||||||||||||||||||||||
452 | # define colon_uchar | - | ||||||||||||||||||||||||
453 | #endif | - | ||||||||||||||||||||||||
454 | - | |||||||||||||||||||||||||
455 | class QUrlPrivate | - | ||||||||||||||||||||||||
456 | { | - | ||||||||||||||||||||||||
457 | public: | - | ||||||||||||||||||||||||
458 | enum Section colon_uchar { | - | ||||||||||||||||||||||||
459 | Scheme = 0x01, | - | ||||||||||||||||||||||||
460 | UserName = 0x02, | - | ||||||||||||||||||||||||
461 | Password = 0x04, | - | ||||||||||||||||||||||||
462 | UserInfo = UserName | Password, | - | ||||||||||||||||||||||||
463 | Host = 0x08, | - | ||||||||||||||||||||||||
464 | Port = 0x10, | - | ||||||||||||||||||||||||
465 | Authority = UserInfo | Host | Port, | - | ||||||||||||||||||||||||
466 | Path = 0x20, | - | ||||||||||||||||||||||||
467 | Hierarchy = Authority | Path, | - | ||||||||||||||||||||||||
468 | Query = 0x40, | - | ||||||||||||||||||||||||
469 | Fragment = 0x80, | - | ||||||||||||||||||||||||
470 | FullUrl = 0xff | - | ||||||||||||||||||||||||
471 | }; | - | ||||||||||||||||||||||||
472 | - | |||||||||||||||||||||||||
473 | enum Flags colon_uchar { | - | ||||||||||||||||||||||||
474 | IsLocalFile = 0x01 | - | ||||||||||||||||||||||||
475 | }; | - | ||||||||||||||||||||||||
476 | - | |||||||||||||||||||||||||
477 | enum ErrorCode { | - | ||||||||||||||||||||||||
478 | // the high byte of the error code matches the Section | - | ||||||||||||||||||||||||
479 | // the first item in each value must be the generic "Invalid xxx Error" | - | ||||||||||||||||||||||||
480 | InvalidSchemeError = Scheme << 8, | - | ||||||||||||||||||||||||
481 | - | |||||||||||||||||||||||||
482 | InvalidUserNameError = UserName << 8, | - | ||||||||||||||||||||||||
483 | - | |||||||||||||||||||||||||
484 | InvalidPasswordError = Password << 8, | - | ||||||||||||||||||||||||
485 | - | |||||||||||||||||||||||||
486 | InvalidRegNameError = Host << 8, | - | ||||||||||||||||||||||||
487 | InvalidIPv4AddressError, | - | ||||||||||||||||||||||||
488 | InvalidIPv6AddressError, | - | ||||||||||||||||||||||||
489 | InvalidCharacterInIPv6Error, | - | ||||||||||||||||||||||||
490 | InvalidIPvFutureError, | - | ||||||||||||||||||||||||
491 | HostMissingEndBracket, | - | ||||||||||||||||||||||||
492 | - | |||||||||||||||||||||||||
493 | InvalidPortError = Port << 8, | - | ||||||||||||||||||||||||
494 | PortEmptyError, | - | ||||||||||||||||||||||||
495 | - | |||||||||||||||||||||||||
496 | InvalidPathError = Path << 8, | - | ||||||||||||||||||||||||
497 | - | |||||||||||||||||||||||||
498 | InvalidQueryError = Query << 8, | - | ||||||||||||||||||||||||
499 | - | |||||||||||||||||||||||||
500 | InvalidFragmentError = Fragment << 8, | - | ||||||||||||||||||||||||
501 | - | |||||||||||||||||||||||||
502 | // the following two cases are only possible in combination | - | ||||||||||||||||||||||||
503 | // with presence/absence of the authority and scheme. See validityError(). | - | ||||||||||||||||||||||||
504 | AuthorityPresentAndPathIsRelative = Authority << 8 | Path << 8 | 0x10000, | - | ||||||||||||||||||||||||
505 | RelativeUrlPathContainsColonBeforeSlash = Scheme << 8 | Authority << 8 | Path << 8 | 0x10000, | - | ||||||||||||||||||||||||
506 | - | |||||||||||||||||||||||||
507 | NoError = 0 | - | ||||||||||||||||||||||||
508 | }; | - | ||||||||||||||||||||||||
509 | - | |||||||||||||||||||||||||
510 | struct Error { | - | ||||||||||||||||||||||||
511 | QString source; | - | ||||||||||||||||||||||||
512 | ErrorCode code; | - | ||||||||||||||||||||||||
513 | int position; | - | ||||||||||||||||||||||||
514 | }; | - | ||||||||||||||||||||||||
515 | - | |||||||||||||||||||||||||
516 | QUrlPrivate(); | - | ||||||||||||||||||||||||
517 | QUrlPrivate(const QUrlPrivate ©); | - | ||||||||||||||||||||||||
518 | ~QUrlPrivate(); | - | ||||||||||||||||||||||||
519 | - | |||||||||||||||||||||||||
520 | void parse(const QString &url, QUrl::ParsingMode parsingMode); | - | ||||||||||||||||||||||||
521 | bool isEmpty() const | - | ||||||||||||||||||||||||
522 | { return sectionIsPresent == 0 && port == -1 && path.isEmpty(); } executed 17289 times by 32 tests: return sectionIsPresent == 0 && port == -1 && path.isEmpty(); Executed by:
| 17289 | ||||||||||||||||||||||||
523 | - | |||||||||||||||||||||||||
524 | Error *cloneError() const; | - | ||||||||||||||||||||||||
525 | void clearError(); | - | ||||||||||||||||||||||||
526 | void setError(ErrorCode errorCode, const QString &source, int supplement = -1); | - | ||||||||||||||||||||||||
527 | ErrorCode validityError(QString *source = 0, int *position = 0) const; | - | ||||||||||||||||||||||||
528 | bool validateComponent(Section section, const QString &input, int begin, int end); | - | ||||||||||||||||||||||||
529 | bool validateComponent(Section section, const QString &input) | - | ||||||||||||||||||||||||
530 | { return validateComponent(section, input, 0, uint(input.length())); } executed 21 times by 1 test: return validateComponent(section, input, 0, uint(input.length())); Executed by:
| 21 | ||||||||||||||||||||||||
531 | - | |||||||||||||||||||||||||
532 | // no QString scheme() const; | - | ||||||||||||||||||||||||
533 | void appendAuthority(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const; | - | ||||||||||||||||||||||||
534 | void appendUserInfo(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const; | - | ||||||||||||||||||||||||
535 | void appendUserName(QString &appendTo, QUrl::FormattingOptions options) const; | - | ||||||||||||||||||||||||
536 | void appendPassword(QString &appendTo, QUrl::FormattingOptions options) const; | - | ||||||||||||||||||||||||
537 | void appendHost(QString &appendTo, QUrl::FormattingOptions options) const; | - | ||||||||||||||||||||||||
538 | void appendPath(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const; | - | ||||||||||||||||||||||||
539 | void appendQuery(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const; | - | ||||||||||||||||||||||||
540 | void appendFragment(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const; | - | ||||||||||||||||||||||||
541 | - | |||||||||||||||||||||||||
542 | // the "end" parameters are like STL iterators: they point to one past the last valid element | - | ||||||||||||||||||||||||
543 | bool setScheme(const QString &value, int len, bool doSetError); | - | ||||||||||||||||||||||||
544 | void setAuthority(const QString &auth, int from, int end, QUrl::ParsingMode mode); | - | ||||||||||||||||||||||||
545 | void setUserInfo(const QString &userInfo, int from, int end); | - | ||||||||||||||||||||||||
546 | void setUserName(const QString &value, int from, int end); | - | ||||||||||||||||||||||||
547 | void setPassword(const QString &value, int from, int end); | - | ||||||||||||||||||||||||
548 | bool setHost(const QString &value, int from, int end, QUrl::ParsingMode mode); | - | ||||||||||||||||||||||||
549 | void setPath(const QString &value, int from, int end); | - | ||||||||||||||||||||||||
550 | void setQuery(const QString &value, int from, int end); | - | ||||||||||||||||||||||||
551 | void setFragment(const QString &value, int from, int end); | - | ||||||||||||||||||||||||
552 | - | |||||||||||||||||||||||||
553 | inline bool hasScheme() const { return sectionIsPresent & Scheme; } executed 10891 times by 31 tests: return sectionIsPresent & Scheme; Executed by:
| 10891 | ||||||||||||||||||||||||
554 | inline bool hasAuthority() const { return sectionIsPresent & Authority; } executed 10496 times by 30 tests: return sectionIsPresent & Authority; Executed by:
| 10496 | ||||||||||||||||||||||||
555 | inline bool hasUserInfo() const { return sectionIsPresent & UserInfo; } executed 6896 times by 20 tests: return sectionIsPresent & UserInfo; Executed by:
| 6896 | ||||||||||||||||||||||||
556 | inline bool hasUserName() const { return sectionIsPresent & UserName; } executed 4548 times by 17 tests: return sectionIsPresent & UserName; Executed by:
| 4548 | ||||||||||||||||||||||||
557 | inline bool hasPassword() const { return sectionIsPresent & Password; } executed 4337 times by 17 tests: return sectionIsPresent & Password; Executed by:
| 4337 | ||||||||||||||||||||||||
558 | inline bool hasHost() const { return sectionIsPresent & Host; } never executed: return sectionIsPresent & Host; | 0 | ||||||||||||||||||||||||
559 | inline bool hasPort() const { return port != -1; } never executed: return port != -1; | 0 | ||||||||||||||||||||||||
560 | inline bool hasPath() const { return !path.isEmpty(); } never executed: return !path.isEmpty(); | 0 | ||||||||||||||||||||||||
561 | inline bool hasQuery() const { return sectionIsPresent & Query; } executed 10978 times by 33 tests: return sectionIsPresent & Query; Executed by:
| 10978 | ||||||||||||||||||||||||
562 | inline bool hasFragment() const { return sectionIsPresent & Fragment; } executed 10982 times by 30 tests: return sectionIsPresent & Fragment; Executed by:
| 10982 | ||||||||||||||||||||||||
563 | - | |||||||||||||||||||||||||
564 | inline bool isLocalFile() const { return flags & IsLocalFile; } executed 21307 times by 34 tests: return flags & IsLocalFile; Executed by:
| 21307 | ||||||||||||||||||||||||
565 | QString toLocalFile(QUrl::FormattingOptions options) const; | - | ||||||||||||||||||||||||
566 | - | |||||||||||||||||||||||||
567 | QString mergePaths(const QString &relativePath) const; | - | ||||||||||||||||||||||||
568 | - | |||||||||||||||||||||||||
569 | QAtomicInt ref; | - | ||||||||||||||||||||||||
570 | int port; | - | ||||||||||||||||||||||||
571 | - | |||||||||||||||||||||||||
572 | QString scheme; | - | ||||||||||||||||||||||||
573 | QString userName; | - | ||||||||||||||||||||||||
574 | QString password; | - | ||||||||||||||||||||||||
575 | QString host; | - | ||||||||||||||||||||||||
576 | QString path; | - | ||||||||||||||||||||||||
577 | QString query; | - | ||||||||||||||||||||||||
578 | QString fragment; | - | ||||||||||||||||||||||||
579 | - | |||||||||||||||||||||||||
580 | Error *error; | - | ||||||||||||||||||||||||
581 | - | |||||||||||||||||||||||||
582 | // not used for: | - | ||||||||||||||||||||||||
583 | // - Port (port == -1 means absence) | - | ||||||||||||||||||||||||
584 | // - Path (there's no path delimiter, so we optimize its use out of existence) | - | ||||||||||||||||||||||||
585 | // Schemes are never supposed to be empty, but we keep the flag anyway | - | ||||||||||||||||||||||||
586 | uchar sectionIsPresent; | - | ||||||||||||||||||||||||
587 | uchar flags; | - | ||||||||||||||||||||||||
588 | - | |||||||||||||||||||||||||
589 | // 32-bit: 2 bytes tail padding available | - | ||||||||||||||||||||||||
590 | // 64-bit: 6 bytes tail padding available | - | ||||||||||||||||||||||||
591 | }; | - | ||||||||||||||||||||||||
592 | #undef colon_uchar | - | ||||||||||||||||||||||||
593 | - | |||||||||||||||||||||||||
594 | inline QUrlPrivate::QUrlPrivate() | - | ||||||||||||||||||||||||
595 | : ref(1), port(-1), | - | ||||||||||||||||||||||||
596 | error(0), | - | ||||||||||||||||||||||||
597 | sectionIsPresent(0), | - | ||||||||||||||||||||||||
598 | flags(0) | - | ||||||||||||||||||||||||
599 | { | - | ||||||||||||||||||||||||
600 | } executed 24302 times by 55 tests: end of block Executed by:
| 24302 | ||||||||||||||||||||||||
601 | - | |||||||||||||||||||||||||
602 | inline QUrlPrivate::QUrlPrivate(const QUrlPrivate ©) | - | ||||||||||||||||||||||||
603 | : ref(1), port(copy.port), | - | ||||||||||||||||||||||||
604 | scheme(copy.scheme), | - | ||||||||||||||||||||||||
605 | userName(copy.userName), | - | ||||||||||||||||||||||||
606 | password(copy.password), | - | ||||||||||||||||||||||||
607 | host(copy.host), | - | ||||||||||||||||||||||||
608 | path(copy.path), | - | ||||||||||||||||||||||||
609 | query(copy.query), | - | ||||||||||||||||||||||||
610 | fragment(copy.fragment), | - | ||||||||||||||||||||||||
611 | error(copy.cloneError()), | - | ||||||||||||||||||||||||
612 | sectionIsPresent(copy.sectionIsPresent), | - | ||||||||||||||||||||||||
613 | flags(copy.flags) | - | ||||||||||||||||||||||||
614 | { | - | ||||||||||||||||||||||||
615 | } executed 9132 times by 17 tests: end of block Executed by:
| 9132 | ||||||||||||||||||||||||
616 | - | |||||||||||||||||||||||||
617 | inline QUrlPrivate::~QUrlPrivate() | - | ||||||||||||||||||||||||
618 | { | - | ||||||||||||||||||||||||
619 | delete error; | - | ||||||||||||||||||||||||
620 | } executed 33428 times by 62 tests: end of block Executed by:
| 33428 | ||||||||||||||||||||||||
621 | - | |||||||||||||||||||||||||
622 | inline QUrlPrivate::Error *QUrlPrivate::cloneError() const | - | ||||||||||||||||||||||||
623 | { | - | ||||||||||||||||||||||||
624 | return error ? new Error(*error) : 0; executed 9132 times by 17 tests: return error ? new Error(*error) : 0; Executed by:
| 9132 | ||||||||||||||||||||||||
625 | } | - | ||||||||||||||||||||||||
626 | - | |||||||||||||||||||||||||
627 | inline void QUrlPrivate::clearError() | - | ||||||||||||||||||||||||
628 | { | - | ||||||||||||||||||||||||
629 | delete error; | - | ||||||||||||||||||||||||
630 | error = 0; | - | ||||||||||||||||||||||||
631 | } executed 46907 times by 55 tests: end of block Executed by:
| 46907 | ||||||||||||||||||||||||
632 | - | |||||||||||||||||||||||||
633 | inline void QUrlPrivate::setError(ErrorCode errorCode, const QString &source, int supplement) | - | ||||||||||||||||||||||||
634 | { | - | ||||||||||||||||||||||||
635 | if (error) {
| 41-263 | ||||||||||||||||||||||||
636 | // don't overwrite an error set in a previous section during parsing | - | ||||||||||||||||||||||||
637 | return; executed 41 times by 5 tests: return; Executed by:
| 41 | ||||||||||||||||||||||||
638 | } | - | ||||||||||||||||||||||||
639 | error = new Error; | - | ||||||||||||||||||||||||
640 | error->code = errorCode; | - | ||||||||||||||||||||||||
641 | error->source = source; | - | ||||||||||||||||||||||||
642 | error->position = supplement; | - | ||||||||||||||||||||||||
643 | } executed 263 times by 8 tests: end of block Executed by:
| 263 | ||||||||||||||||||||||||
644 | - | |||||||||||||||||||||||||
645 | // From RFC 3986, Appendix A Collected ABNF for URI | - | ||||||||||||||||||||||||
646 | // URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] | - | ||||||||||||||||||||||||
647 | //[...] | - | ||||||||||||||||||||||||
648 | // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) | - | ||||||||||||||||||||||||
649 | // | - | ||||||||||||||||||||||||
650 | // authority = [ userinfo "@" ] host [ ":" port ] | - | ||||||||||||||||||||||||
651 | // userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) | - | ||||||||||||||||||||||||
652 | // host = IP-literal / IPv4address / reg-name | - | ||||||||||||||||||||||||
653 | // port = *DIGIT | - | ||||||||||||||||||||||||
654 | //[...] | - | ||||||||||||||||||||||||
655 | // reg-name = *( unreserved / pct-encoded / sub-delims ) | - | ||||||||||||||||||||||||
656 | //[..] | - | ||||||||||||||||||||||||
657 | // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" | - | ||||||||||||||||||||||||
658 | // | - | ||||||||||||||||||||||||
659 | // query = *( pchar / "/" / "?" ) | - | ||||||||||||||||||||||||
660 | // | - | ||||||||||||||||||||||||
661 | // fragment = *( pchar / "/" / "?" ) | - | ||||||||||||||||||||||||
662 | // | - | ||||||||||||||||||||||||
663 | // pct-encoded = "%" HEXDIG HEXDIG | - | ||||||||||||||||||||||||
664 | // | - | ||||||||||||||||||||||||
665 | // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" | - | ||||||||||||||||||||||||
666 | // reserved = gen-delims / sub-delims | - | ||||||||||||||||||||||||
667 | // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" | - | ||||||||||||||||||||||||
668 | // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" | - | ||||||||||||||||||||||||
669 | // / "*" / "+" / "," / ";" / "=" | - | ||||||||||||||||||||||||
670 | // the path component has a complex ABNF that basically boils down to | - | ||||||||||||||||||||||||
671 | // slash-separated segments of "pchar" | - | ||||||||||||||||||||||||
672 | - | |||||||||||||||||||||||||
673 | // The above is the strict definition of the URL components and we mostly | - | ||||||||||||||||||||||||
674 | // adhere to it, with few exceptions. QUrl obeys the following behavior: | - | ||||||||||||||||||||||||
675 | // - percent-encoding sequences always use uppercase HEXDIG; | - | ||||||||||||||||||||||||
676 | // - unreserved characters are *always* decoded, no exceptions; | - | ||||||||||||||||||||||||
677 | // - the space character and bytes with the high bit set are controlled by | - | ||||||||||||||||||||||||
678 | // the EncodeSpaces and EncodeUnicode bits; | - | ||||||||||||||||||||||||
679 | // - control characters, the percent sign itself, and bytes with the high | - | ||||||||||||||||||||||||
680 | // bit set that don't form valid UTF-8 sequences are always encoded, | - | ||||||||||||||||||||||||
681 | // except in FullyDecoded mode; | - | ||||||||||||||||||||||||
682 | // - sub-delims are always left alone, except in FullyDecoded mode; | - | ||||||||||||||||||||||||
683 | // - gen-delim change behavior depending on which section of the URL (or | - | ||||||||||||||||||||||||
684 | // the entire URL) we're looking at; see below; | - | ||||||||||||||||||||||||
685 | // - characters not mentioned above, like "<", and ">", are usually | - | ||||||||||||||||||||||||
686 | // decoded in individual sections of the URL, but encoded when the full | - | ||||||||||||||||||||||||
687 | // URL is put together (we can change on subjective definition of | - | ||||||||||||||||||||||||
688 | // "pretty"). | - | ||||||||||||||||||||||||
689 | // | - | ||||||||||||||||||||||||
690 | // The behavior for the delimiters bears some explanation. The spec says in | - | ||||||||||||||||||||||||
691 | // section 2.2: | - | ||||||||||||||||||||||||
692 | // URIs that differ in the replacement of a reserved character with its | - | ||||||||||||||||||||||||
693 | // corresponding percent-encoded octet are not equivalent. | - | ||||||||||||||||||||||||
694 | // (note: QUrl API mistakenly uses the "reserved" term, so we will refer to | - | ||||||||||||||||||||||||
695 | // them here as "delimiters"). | - | ||||||||||||||||||||||||
696 | // | - | ||||||||||||||||||||||||
697 | // For that reason, we cannot encode delimiters found in decoded form and we | - | ||||||||||||||||||||||||
698 | // cannot decode the ones found in encoded form if that would change the | - | ||||||||||||||||||||||||
699 | // interpretation. Conversely, we *can* perform the transformation if it would | - | ||||||||||||||||||||||||
700 | // not change the interpretation. From the last component of a URL to the first, | - | ||||||||||||||||||||||||
701 | // here are the gen-delims we can unambiguously transform when the field is | - | ||||||||||||||||||||||||
702 | // taken in isolation: | - | ||||||||||||||||||||||||
703 | // - fragment: none, since it's the last | - | ||||||||||||||||||||||||
704 | // - query: "#" is unambiguous | - | ||||||||||||||||||||||||
705 | // - path: "#" and "?" are unambiguous | - | ||||||||||||||||||||||||
706 | // - host: completely special but never ambiguous, see setHost() below. | - | ||||||||||||||||||||||||
707 | // - password: the "#", "?", "/", "[", "]" and "@" characters are unambiguous | - | ||||||||||||||||||||||||
708 | // - username: the "#", "?", "/", "[", "]", "@", and ":" characters are unambiguous | - | ||||||||||||||||||||||||
709 | // - scheme: doesn't accept any delimiter, see setScheme() below. | - | ||||||||||||||||||||||||
710 | // | - | ||||||||||||||||||||||||
711 | // Internally, QUrl stores each component in the format that corresponds to the | - | ||||||||||||||||||||||||
712 | // default mode (PrettyDecoded). It deviates from the "strict" FullyEncoded | - | ||||||||||||||||||||||||
713 | // mode in the following way: | - | ||||||||||||||||||||||||
714 | // - spaces are decoded | - | ||||||||||||||||||||||||
715 | // - valid UTF-8 sequences are decoded | - | ||||||||||||||||||||||||
716 | // - gen-delims that can be unambiguously transformed are decoded | - | ||||||||||||||||||||||||
717 | // - characters controlled by DecodeReserved are often decoded, though this behavior | - | ||||||||||||||||||||||||
718 | // can change depending on the subjective definition of "pretty" | - | ||||||||||||||||||||||||
719 | // | - | ||||||||||||||||||||||||
720 | // Note that the list of gen-delims that we can transform is different for the | - | ||||||||||||||||||||||||
721 | // user info (user name + password) and the authority (user info + host + | - | ||||||||||||||||||||||||
722 | // port). | - | ||||||||||||||||||||||||
723 | - | |||||||||||||||||||||||||
724 | - | |||||||||||||||||||||||||
725 | // list the recoding table modifications to be used with the recodeFromUser and | - | ||||||||||||||||||||||||
726 | // appendToUser functions, according to the rules above. Spaces and UTF-8 | - | ||||||||||||||||||||||||
727 | // sequences are handled outside the tables. | - | ||||||||||||||||||||||||
728 | - | |||||||||||||||||||||||||
729 | // the encodedXXX tables are run with the delimiters set to "leave" by default; | - | ||||||||||||||||||||||||
730 | // the decodedXXX tables are run with the delimiters set to "decode" by default | - | ||||||||||||||||||||||||
731 | // (except for the query, which doesn't use these functions) | - | ||||||||||||||||||||||||
732 | - | |||||||||||||||||||||||||
733 | #define decode(x) ushort(x) | - | ||||||||||||||||||||||||
734 | #define leave(x) ushort(0x100 | (x)) | - | ||||||||||||||||||||||||
735 | #define encode(x) ushort(0x200 | (x)) | - | ||||||||||||||||||||||||
736 | - | |||||||||||||||||||||||||
737 | static const ushort userNameInIsolation[] = { | - | ||||||||||||||||||||||||
738 | decode(':'), // 0 | - | ||||||||||||||||||||||||
739 | decode('@'), // 1 | - | ||||||||||||||||||||||||
740 | decode(']'), // 2 | - | ||||||||||||||||||||||||
741 | decode('['), // 3 | - | ||||||||||||||||||||||||
742 | decode('/'), // 4 | - | ||||||||||||||||||||||||
743 | decode('?'), // 5 | - | ||||||||||||||||||||||||
744 | decode('#'), // 6 | - | ||||||||||||||||||||||||
745 | - | |||||||||||||||||||||||||
746 | decode('"'), // 7 | - | ||||||||||||||||||||||||
747 | decode('<'), | - | ||||||||||||||||||||||||
748 | decode('>'), | - | ||||||||||||||||||||||||
749 | decode('^'), | - | ||||||||||||||||||||||||
750 | decode('\\'), | - | ||||||||||||||||||||||||
751 | decode('|'), | - | ||||||||||||||||||||||||
752 | decode('{'), | - | ||||||||||||||||||||||||
753 | decode('}'), | - | ||||||||||||||||||||||||
754 | 0 | - | ||||||||||||||||||||||||
755 | }; | - | ||||||||||||||||||||||||
756 | static const ushort * const passwordInIsolation = userNameInIsolation + 1; | - | ||||||||||||||||||||||||
757 | static const ushort * const pathInIsolation = userNameInIsolation + 5; | - | ||||||||||||||||||||||||
758 | static const ushort * const queryInIsolation = userNameInIsolation + 6; | - | ||||||||||||||||||||||||
759 | static const ushort * const fragmentInIsolation = userNameInIsolation + 7; | - | ||||||||||||||||||||||||
760 | - | |||||||||||||||||||||||||
761 | static const ushort userNameInUserInfo[] = { | - | ||||||||||||||||||||||||
762 | encode(':'), // 0 | - | ||||||||||||||||||||||||
763 | decode('@'), // 1 | - | ||||||||||||||||||||||||
764 | decode(']'), // 2 | - | ||||||||||||||||||||||||
765 | decode('['), // 3 | - | ||||||||||||||||||||||||
766 | decode('/'), // 4 | - | ||||||||||||||||||||||||
767 | decode('?'), // 5 | - | ||||||||||||||||||||||||
768 | decode('#'), // 6 | - | ||||||||||||||||||||||||
769 | - | |||||||||||||||||||||||||
770 | decode('"'), // 7 | - | ||||||||||||||||||||||||
771 | decode('<'), | - | ||||||||||||||||||||||||
772 | decode('>'), | - | ||||||||||||||||||||||||
773 | decode('^'), | - | ||||||||||||||||||||||||
774 | decode('\\'), | - | ||||||||||||||||||||||||
775 | decode('|'), | - | ||||||||||||||||||||||||
776 | decode('{'), | - | ||||||||||||||||||||||||
777 | decode('}'), | - | ||||||||||||||||||||||||
778 | 0 | - | ||||||||||||||||||||||||
779 | }; | - | ||||||||||||||||||||||||
780 | static const ushort * const passwordInUserInfo = userNameInUserInfo + 1; | - | ||||||||||||||||||||||||
781 | - | |||||||||||||||||||||||||
782 | static const ushort userNameInAuthority[] = { | - | ||||||||||||||||||||||||
783 | encode(':'), // 0 | - | ||||||||||||||||||||||||
784 | encode('@'), // 1 | - | ||||||||||||||||||||||||
785 | encode(']'), // 2 | - | ||||||||||||||||||||||||
786 | encode('['), // 3 | - | ||||||||||||||||||||||||
787 | decode('/'), // 4 | - | ||||||||||||||||||||||||
788 | decode('?'), // 5 | - | ||||||||||||||||||||||||
789 | decode('#'), // 6 | - | ||||||||||||||||||||||||
790 | - | |||||||||||||||||||||||||
791 | decode('"'), // 7 | - | ||||||||||||||||||||||||
792 | decode('<'), | - | ||||||||||||||||||||||||
793 | decode('>'), | - | ||||||||||||||||||||||||
794 | decode('^'), | - | ||||||||||||||||||||||||
795 | decode('\\'), | - | ||||||||||||||||||||||||
796 | decode('|'), | - | ||||||||||||||||||||||||
797 | decode('{'), | - | ||||||||||||||||||||||||
798 | decode('}'), | - | ||||||||||||||||||||||||
799 | 0 | - | ||||||||||||||||||||||||
800 | }; | - | ||||||||||||||||||||||||
801 | static const ushort * const passwordInAuthority = userNameInAuthority + 1; | - | ||||||||||||||||||||||||
802 | - | |||||||||||||||||||||||||
803 | static const ushort userNameInUrl[] = { | - | ||||||||||||||||||||||||
804 | encode(':'), // 0 | - | ||||||||||||||||||||||||
805 | encode('@'), // 1 | - | ||||||||||||||||||||||||
806 | encode(']'), // 2 | - | ||||||||||||||||||||||||
807 | encode('['), // 3 | - | ||||||||||||||||||||||||
808 | encode('/'), // 4 | - | ||||||||||||||||||||||||
809 | encode('?'), // 5 | - | ||||||||||||||||||||||||
810 | encode('#'), // 6 | - | ||||||||||||||||||||||||
811 | - | |||||||||||||||||||||||||
812 | // no need to list encode(x) for the other characters | - | ||||||||||||||||||||||||
813 | 0 | - | ||||||||||||||||||||||||
814 | }; | - | ||||||||||||||||||||||||
815 | static const ushort * const passwordInUrl = userNameInUrl + 1; | - | ||||||||||||||||||||||||
816 | static const ushort * const pathInUrl = userNameInUrl + 5; | - | ||||||||||||||||||||||||
817 | static const ushort * const queryInUrl = userNameInUrl + 6; | - | ||||||||||||||||||||||||
818 | static const ushort * const fragmentInUrl = userNameInUrl + 6; | - | ||||||||||||||||||||||||
819 | - | |||||||||||||||||||||||||
820 | static inline void parseDecodedComponent(QString &data) | - | ||||||||||||||||||||||||
821 | { | - | ||||||||||||||||||||||||
822 | data.replace(QLatin1Char('%'), QLatin1String("%25")); | - | ||||||||||||||||||||||||
823 | } executed 14930 times by 40 tests: end of block Executed by:
| 14930 | ||||||||||||||||||||||||
824 | - | |||||||||||||||||||||||||
825 | static inline QString | - | ||||||||||||||||||||||||
826 | recodeFromUser(const QString &input, const ushort *actions, int from, int to) | - | ||||||||||||||||||||||||
827 | { | - | ||||||||||||||||||||||||
828 | QString output; | - | ||||||||||||||||||||||||
829 | const QChar *begin = input.constData() + from; | - | ||||||||||||||||||||||||
830 | const QChar *end = input.constData() + to; | - | ||||||||||||||||||||||||
831 | if (qt_urlRecode(output, begin, end, 0, actions))
| 197-19883 | ||||||||||||||||||||||||
832 | return output; executed 197 times by 6 tests: return output; Executed by:
| 197 | ||||||||||||||||||||||||
833 | - | |||||||||||||||||||||||||
834 | return input.mid(from, to - from); executed 19883 times by 35 tests: return input.mid(from, to - from); Executed by:
| 19883 | ||||||||||||||||||||||||
835 | } | - | ||||||||||||||||||||||||
836 | - | |||||||||||||||||||||||||
837 | // appendXXXX functions: copy from the internal form to the external, user form. | - | ||||||||||||||||||||||||
838 | // the internal value is stored in its PrettyDecoded form, so that case is easy. | - | ||||||||||||||||||||||||
839 | static inline void appendToUser(QString &appendTo, const QString &value, QUrl::FormattingOptions options, | - | ||||||||||||||||||||||||
840 | const ushort *actions) | - | ||||||||||||||||||||||||
841 | { | - | ||||||||||||||||||||||||
842 | if (options == QUrl::PrettyDecoded) {
| 291-25323 | ||||||||||||||||||||||||
843 | appendTo += value; | - | ||||||||||||||||||||||||
844 | return; executed 291 times by 4 tests: return; Executed by:
| 291 | ||||||||||||||||||||||||
845 | } | - | ||||||||||||||||||||||||
846 | - | |||||||||||||||||||||||||
847 | if (!qt_urlRecode(appendTo, value.constData(), value.constEnd(), options, actions))
| 945-24378 | ||||||||||||||||||||||||
848 | appendTo += value; executed 24378 times by 33 tests: appendTo += value; Executed by:
| 24378 | ||||||||||||||||||||||||
849 | } executed 25323 times by 33 tests: end of block Executed by:
| 25323 | ||||||||||||||||||||||||
850 | - | |||||||||||||||||||||||||
851 | inline void QUrlPrivate::appendAuthority(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const | - | ||||||||||||||||||||||||
852 | { | - | ||||||||||||||||||||||||
853 | if ((options & QUrl::RemoveUserInfo) != QUrl::RemoveUserInfo) {
| 1081-4548 | ||||||||||||||||||||||||
854 | appendUserInfo(appendTo, options, appendingTo); | - | ||||||||||||||||||||||||
855 | - | |||||||||||||||||||||||||
856 | // add '@' only if we added anything | - | ||||||||||||||||||||||||
857 | if (hasUserName() || (hasPassword() && (options & QUrl::RemovePassword) == 0))
| 7-3921 | ||||||||||||||||||||||||
858 | appendTo += QLatin1Char('@'); executed 634 times by 5 tests: appendTo += QLatin1Char('@'); Executed by:
| 634 | ||||||||||||||||||||||||
859 | } executed 4548 times by 17 tests: end of block Executed by:
| 4548 | ||||||||||||||||||||||||
860 | appendHost(appendTo, options); | - | ||||||||||||||||||||||||
861 | if (!(options & QUrl::RemovePort) && port != -1)
| 4-5625 | ||||||||||||||||||||||||
862 | appendTo += QLatin1Char(':') + QString::number(port); executed 1782 times by 9 tests: appendTo += QLatin1Char(':') + QString::number(port); Executed by:
| 1782 | ||||||||||||||||||||||||
863 | } executed 5629 times by 20 tests: end of block Executed by:
| 5629 | ||||||||||||||||||||||||
864 | - | |||||||||||||||||||||||||
865 | inline void QUrlPrivate::appendUserInfo(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const | - | ||||||||||||||||||||||||
866 | { | - | ||||||||||||||||||||||||
867 | if (Q_LIKELY(!hasUserInfo()))
| 790-6106 | ||||||||||||||||||||||||
868 | return; executed 6106 times by 19 tests: return; Executed by:
| 6106 | ||||||||||||||||||||||||
869 | - | |||||||||||||||||||||||||
870 | const ushort *userNameActions; | - | ||||||||||||||||||||||||
871 | const ushort *passwordActions; | - | ||||||||||||||||||||||||
872 | if (options & QUrl::EncodeDelimiters) {
| 185-605 | ||||||||||||||||||||||||
873 | userNameActions = userNameInUrl; | - | ||||||||||||||||||||||||
874 | passwordActions = passwordInUrl; | - | ||||||||||||||||||||||||
875 | } else { executed 605 times by 5 tests: end of block Executed by:
| 605 | ||||||||||||||||||||||||
876 | switch (appendingTo) { | - | ||||||||||||||||||||||||
877 | case UserInfo: executed 57 times by 2 tests: case UserInfo: Executed by:
| 57 | ||||||||||||||||||||||||
878 | userNameActions = userNameInUserInfo; | - | ||||||||||||||||||||||||
879 | passwordActions = passwordInUserInfo; | - | ||||||||||||||||||||||||
880 | break; executed 57 times by 2 tests: break; Executed by:
| 57 | ||||||||||||||||||||||||
881 | - | |||||||||||||||||||||||||
882 | case Authority: executed 25 times by 1 test: case Authority: Executed by:
| 25 | ||||||||||||||||||||||||
883 | userNameActions = userNameInAuthority; | - | ||||||||||||||||||||||||
884 | passwordActions = passwordInAuthority; | - | ||||||||||||||||||||||||
885 | break; executed 25 times by 1 test: break; Executed by:
| 25 | ||||||||||||||||||||||||
886 | - | |||||||||||||||||||||||||
887 | case FullUrl: executed 103 times by 2 tests: case FullUrl: Executed by:
| 103 | ||||||||||||||||||||||||
888 | userNameActions = userNameInUrl; | - | ||||||||||||||||||||||||
889 | passwordActions = passwordInUrl; | - | ||||||||||||||||||||||||
890 | break; executed 103 times by 2 tests: break; Executed by:
| 103 | ||||||||||||||||||||||||
891 | - | |||||||||||||||||||||||||
892 | default: never executed: default: | 0 | ||||||||||||||||||||||||
893 | // can't happen | - | ||||||||||||||||||||||||
894 | Q_UNREACHABLE(); | - | ||||||||||||||||||||||||
895 | break; never executed: break; | 0 | ||||||||||||||||||||||||
896 | } | - | ||||||||||||||||||||||||
897 | } | - | ||||||||||||||||||||||||
898 | - | |||||||||||||||||||||||||
899 | if (!qt_urlRecode(appendTo, userName.constData(), userName.constEnd(), options, userNameActions))
| 67-723 | ||||||||||||||||||||||||
900 | appendTo += userName; executed 723 times by 5 tests: appendTo += userName; Executed by:
| 723 | ||||||||||||||||||||||||
901 | if (options & QUrl::RemovePassword || !hasPassword()) {
| 191-225 | ||||||||||||||||||||||||
902 | return; executed 565 times by 5 tests: return; Executed by:
| 565 | ||||||||||||||||||||||||
903 | } else { | - | ||||||||||||||||||||||||
904 | appendTo += QLatin1Char(':'); | - | ||||||||||||||||||||||||
905 | if (!qt_urlRecode(appendTo, password.constData(), password.constEnd(), options, passwordActions))
| 57-168 | ||||||||||||||||||||||||
906 | appendTo += password; executed 168 times by 2 tests: appendTo += password; Executed by:
| 168 | ||||||||||||||||||||||||
907 | } executed 225 times by 2 tests: end of block Executed by:
| 225 | ||||||||||||||||||||||||
908 | } | - | ||||||||||||||||||||||||
909 | - | |||||||||||||||||||||||||
910 | inline void QUrlPrivate::appendUserName(QString &appendTo, QUrl::FormattingOptions options) const | - | ||||||||||||||||||||||||
911 | { | - | ||||||||||||||||||||||||
912 | // only called from QUrl::userName() | - | ||||||||||||||||||||||||
913 | appendToUser(appendTo, userName, options, | - | ||||||||||||||||||||||||
914 | options & QUrl::EncodeDelimiters ? userNameInUrl : userNameInIsolation); | - | ||||||||||||||||||||||||
915 | } executed 783 times by 3 tests: end of block Executed by:
| 783 | ||||||||||||||||||||||||
916 | - | |||||||||||||||||||||||||
917 | inline void QUrlPrivate::appendPassword(QString &appendTo, QUrl::FormattingOptions options) const | - | ||||||||||||||||||||||||
918 | { | - | ||||||||||||||||||||||||
919 | // only called from QUrl::password() | - | ||||||||||||||||||||||||
920 | appendToUser(appendTo, password, options, | - | ||||||||||||||||||||||||
921 | options & QUrl::EncodeDelimiters ? passwordInUrl : passwordInIsolation); | - | ||||||||||||||||||||||||
922 | } executed 577 times by 6 tests: end of block Executed by:
| 577 | ||||||||||||||||||||||||
923 | - | |||||||||||||||||||||||||
924 | inline void QUrlPrivate::appendPath(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const | - | ||||||||||||||||||||||||
925 | { | - | ||||||||||||||||||||||||
926 | QString thePath = path; | - | ||||||||||||||||||||||||
927 | if (options & QUrl::NormalizePathSegments) {
| 19-22596 | ||||||||||||||||||||||||
928 | thePath = qt_normalizePathSegments(path, false); | - | ||||||||||||||||||||||||
929 | } executed 19 times by 1 test: end of block Executed by:
| 19 | ||||||||||||||||||||||||
930 | if (options & QUrl::RemoveFilename) {
| 54-22561 | ||||||||||||||||||||||||
931 | const int slash = path.lastIndexOf(QLatin1Char('/')); | - | ||||||||||||||||||||||||
932 | if (slash == -1)
| 5-49 | ||||||||||||||||||||||||
933 | return; executed 5 times by 1 test: return; Executed by:
| 5 | ||||||||||||||||||||||||
934 | thePath = path.left(slash+1); | - | ||||||||||||||||||||||||
935 | } executed 49 times by 1 test: end of block Executed by:
| 49 | ||||||||||||||||||||||||
936 | // check if we need to remove trailing slashes | - | ||||||||||||||||||||||||
937 | if (options & QUrl::StripTrailingSlash) {
| 44-22566 | ||||||||||||||||||||||||
938 | while (thePath.length() > 1 && thePath.endsWith(QLatin1Char('/')))
| 16-58 | ||||||||||||||||||||||||
939 | thePath.chop(1); executed 30 times by 1 test: thePath.chop(1); Executed by:
| 30 | ||||||||||||||||||||||||
940 | } executed 44 times by 1 test: end of block Executed by:
| 44 | ||||||||||||||||||||||||
941 | - | |||||||||||||||||||||||||
942 | appendToUser(appendTo, thePath, options, | - | ||||||||||||||||||||||||
943 | appendingTo == FullUrl || options & QUrl::EncodeDelimiters ? pathInUrl : pathInIsolation); | - | ||||||||||||||||||||||||
944 | - | |||||||||||||||||||||||||
945 | } executed 22610 times by 33 tests: end of block Executed by:
| 22610 | ||||||||||||||||||||||||
946 | - | |||||||||||||||||||||||||
947 | inline void QUrlPrivate::appendFragment(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const | - | ||||||||||||||||||||||||
948 | { | - | ||||||||||||||||||||||||
949 | appendToUser(appendTo, fragment, options, | - | ||||||||||||||||||||||||
950 | options & QUrl::EncodeDelimiters ? fragmentInUrl : | - | ||||||||||||||||||||||||
951 | appendingTo == FullUrl ? 0 : fragmentInIsolation); | - | ||||||||||||||||||||||||
952 | } executed 920 times by 4 tests: end of block Executed by:
| 920 | ||||||||||||||||||||||||
953 | - | |||||||||||||||||||||||||
954 | inline void QUrlPrivate::appendQuery(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const | - | ||||||||||||||||||||||||
955 | { | - | ||||||||||||||||||||||||
956 | appendToUser(appendTo, query, options, | - | ||||||||||||||||||||||||
957 | appendingTo == FullUrl || options & QUrl::EncodeDelimiters ? queryInUrl : queryInIsolation); | - | ||||||||||||||||||||||||
958 | } executed 724 times by 4 tests: end of block Executed by:
| 724 | ||||||||||||||||||||||||
959 | - | |||||||||||||||||||||||||
960 | // setXXX functions | - | ||||||||||||||||||||||||
961 | - | |||||||||||||||||||||||||
962 | inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetError) | - | ||||||||||||||||||||||||
963 | { | - | ||||||||||||||||||||||||
964 | // schemes are strictly RFC-compliant: | - | ||||||||||||||||||||||||
965 | // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) | - | ||||||||||||||||||||||||
966 | // we also lowercase the scheme | - | ||||||||||||||||||||||||
967 | - | |||||||||||||||||||||||||
968 | // schemes in URLs are not allowed to be empty, but they can be in | - | ||||||||||||||||||||||||
969 | // "Relative URIs" which QUrl also supports. QUrl::setScheme does | - | ||||||||||||||||||||||||
970 | // not call us with len == 0, so this can only be from parse() | - | ||||||||||||||||||||||||
971 | scheme.clear(); | - | ||||||||||||||||||||||||
972 | if (len == 0)
| 6-12241 | ||||||||||||||||||||||||
973 | return false; executed 6 times by 4 tests: return false; Executed by:
| 6 | ||||||||||||||||||||||||
974 | - | |||||||||||||||||||||||||
975 | sectionIsPresent |= Scheme; | - | ||||||||||||||||||||||||
976 | - | |||||||||||||||||||||||||
977 | // validate it: | - | ||||||||||||||||||||||||
978 | int needsLowercasing = -1; | - | ||||||||||||||||||||||||
979 | const ushort *p = reinterpret_cast<const ushort *>(value.constData()); | - | ||||||||||||||||||||||||
980 | for (int i = 0; i < len; ++i) {
| 12112-51343 | ||||||||||||||||||||||||
981 | if (p[i] >= 'a' && p[i] <= 'z')
| 18-50436 | ||||||||||||||||||||||||
982 | continue; executed 50418 times by 33 tests: continue; Executed by:
| 50418 | ||||||||||||||||||||||||
983 | if (p[i] >= 'A' && p[i] <= 'Z') {
| 36-617 | ||||||||||||||||||||||||
984 | needsLowercasing = i; | - | ||||||||||||||||||||||||
985 | continue; executed 272 times by 1 test: continue; Executed by:
| 272 | ||||||||||||||||||||||||
986 | } | - | ||||||||||||||||||||||||
987 | if (i) {
| 38-615 | ||||||||||||||||||||||||
988 | if (p[i] >= '0' && p[i] <= '9')
| 47-423 | ||||||||||||||||||||||||
989 | continue; executed 145 times by 4 tests: continue; Executed by:
| 145 | ||||||||||||||||||||||||
990 | if (p[i] == '+' || p[i] == '-' || p[i] == '.')
| 8-462 | ||||||||||||||||||||||||
991 | continue; executed 379 times by 3 tests: continue; Executed by:
| 379 | ||||||||||||||||||||||||
992 | } executed 91 times by 1 test: end of block Executed by:
| 91 | ||||||||||||||||||||||||
993 | - | |||||||||||||||||||||||||
994 | // found something else | - | ||||||||||||||||||||||||
995 | // don't call setError needlessly: | - | ||||||||||||||||||||||||
996 | // if we've been called from parse(), it will try to recover | - | ||||||||||||||||||||||||
997 | if (doSetError)
| 55-74 | ||||||||||||||||||||||||
998 | setError(InvalidSchemeError, value, i); executed 74 times by 1 test: setError(InvalidSchemeError, value, i); Executed by:
| 74 | ||||||||||||||||||||||||
999 | return false; executed 129 times by 2 tests: return false; Executed by:
| 129 | ||||||||||||||||||||||||
1000 | } | - | ||||||||||||||||||||||||
1001 | - | |||||||||||||||||||||||||
1002 | scheme = value.left(len); | - | ||||||||||||||||||||||||
1003 | - | |||||||||||||||||||||||||
1004 | if (needsLowercasing != -1) {
| 33-12079 | ||||||||||||||||||||||||
1005 | // schemes are ASCII only, so we don't need the full Unicode toLower | - | ||||||||||||||||||||||||
1006 | QChar *schemeData = scheme.data(); // force detaching here | - | ||||||||||||||||||||||||
1007 | for (int i = needsLowercasing; i >= 0; --i) {
| 33-192 | ||||||||||||||||||||||||
1008 | ushort c = schemeData[i].unicode(); | - | ||||||||||||||||||||||||
1009 | if (c >= 'A' && c <= 'Z')
| 2-180 | ||||||||||||||||||||||||
1010 | schemeData[i] = c + 0x20; executed 178 times by 1 test: schemeData[i] = c + 0x20; Executed by:
| 178 | ||||||||||||||||||||||||
1011 | } executed 192 times by 1 test: end of block Executed by:
| 192 | ||||||||||||||||||||||||
1012 | } executed 33 times by 1 test: end of block Executed by:
| 33 | ||||||||||||||||||||||||
1013 | - | |||||||||||||||||||||||||
1014 | // did we set to the file protocol? | - | ||||||||||||||||||||||||
1015 | if (scheme == fileScheme()
| 5570-6542 | ||||||||||||||||||||||||
1016 | #ifdef Q_OS_WIN | - | ||||||||||||||||||||||||
1017 | || scheme == webDavScheme() | - | ||||||||||||||||||||||||
1018 | #endif | - | ||||||||||||||||||||||||
1019 | ) { | - | ||||||||||||||||||||||||
1020 | flags |= IsLocalFile; | - | ||||||||||||||||||||||||
1021 | } else { executed 6542 times by 15 tests: end of block Executed by:
| 6542 | ||||||||||||||||||||||||
1022 | flags &= ~IsLocalFile; | - | ||||||||||||||||||||||||
1023 | } executed 5570 times by 22 tests: end of block Executed by:
| 5570 | ||||||||||||||||||||||||
1024 | return true; executed 12112 times by 33 tests: return true; Executed by:
| 12112 | ||||||||||||||||||||||||
1025 | } | - | ||||||||||||||||||||||||
1026 | - | |||||||||||||||||||||||||
1027 | inline void QUrlPrivate::setAuthority(const QString &auth, int from, int end, QUrl::ParsingMode mode) | - | ||||||||||||||||||||||||
1028 | { | - | ||||||||||||||||||||||||
1029 | sectionIsPresent &= ~Authority; | - | ||||||||||||||||||||||||
1030 | sectionIsPresent |= Host; | - | ||||||||||||||||||||||||
1031 | - | |||||||||||||||||||||||||
1032 | // we never actually _loop_ | - | ||||||||||||||||||||||||
1033 | while (from != end) {
| 618-4922 | ||||||||||||||||||||||||
1034 | int userInfoIndex = auth.indexOf(QLatin1Char('@'), from); | - | ||||||||||||||||||||||||
1035 | if (uint(userInfoIndex) < uint(end)) {
| 166-4756 | ||||||||||||||||||||||||
1036 | setUserInfo(auth, from, userInfoIndex); | - | ||||||||||||||||||||||||
1037 | if (mode == QUrl::StrictMode && !validateComponent(UserInfo, auth, from, userInfoIndex))
| 1-158 | ||||||||||||||||||||||||
1038 | break; executed 7 times by 1 test: break; Executed by:
| 7 | ||||||||||||||||||||||||
1039 | from = userInfoIndex + 1; | - | ||||||||||||||||||||||||
1040 | } executed 159 times by 4 tests: end of block Executed by:
| 159 | ||||||||||||||||||||||||
1041 | - | |||||||||||||||||||||||||
1042 | int colonIndex = auth.lastIndexOf(QLatin1Char(':'), end - 1); | - | ||||||||||||||||||||||||
1043 | if (colonIndex < from)
| 839-4076 | ||||||||||||||||||||||||
1044 | colonIndex = -1; executed 4076 times by 20 tests: colonIndex = -1; Executed by:
| 4076 | ||||||||||||||||||||||||
1045 | - | |||||||||||||||||||||||||
1046 | if (uint(colonIndex) < uint(end)) {
| 839-4076 | ||||||||||||||||||||||||
1047 | if (auth.at(from).unicode() == '[') {
| 65-774 | ||||||||||||||||||||||||
1048 | // check if colonIndex isn't inside the "[...]" part | - | ||||||||||||||||||||||||
1049 | int closingBracket = auth.indexOf(QLatin1Char(']'), from); | - | ||||||||||||||||||||||||
1050 | if (uint(closingBracket) > uint(colonIndex))
| 6-59 | ||||||||||||||||||||||||
1051 | colonIndex = -1; executed 59 times by 4 tests: colonIndex = -1; Executed by:
| 59 | ||||||||||||||||||||||||
1052 | } executed 65 times by 4 tests: end of block Executed by:
| 65 | ||||||||||||||||||||||||
1053 | } executed 839 times by 6 tests: end of block Executed by:
| 839 | ||||||||||||||||||||||||
1054 | - | |||||||||||||||||||||||||
1055 | if (colonIndex == end - 1) {
| 12-4903 | ||||||||||||||||||||||||
1056 | // found a colon but no digits after it | - | ||||||||||||||||||||||||
1057 | port = -1; | - | ||||||||||||||||||||||||
1058 | } else if (uint(colonIndex) < uint(end)) { executed 12 times by 2 tests: end of block Executed by:
| 12-4135 | ||||||||||||||||||||||||
1059 | unsigned long x = 0; | - | ||||||||||||||||||||||||
1060 | for (int i = colonIndex + 1; i < end; ++i) {
| 761-3040 | ||||||||||||||||||||||||
1061 | ushort c = auth.at(i).unicode(); | - | ||||||||||||||||||||||||
1062 | if (c >= '0' && c <= '9') {
| 1-3039 | ||||||||||||||||||||||||
1063 | x *= 10; | - | ||||||||||||||||||||||||
1064 | x += c - '0'; | - | ||||||||||||||||||||||||
1065 | } else { executed 3033 times by 6 tests: end of block Executed by:
| 3033 | ||||||||||||||||||||||||
1066 | x = ulong(-1); // x != ushort(x) | - | ||||||||||||||||||||||||
1067 | break; executed 7 times by 1 test: break; Executed by:
| 7 | ||||||||||||||||||||||||
1068 | } | - | ||||||||||||||||||||||||
1069 | } | - | ||||||||||||||||||||||||
1070 | if (x == ushort(x)) {
| 10-758 | ||||||||||||||||||||||||
1071 | port = ushort(x); | - | ||||||||||||||||||||||||
1072 | } else { executed 758 times by 6 tests: end of block Executed by:
| 758 | ||||||||||||||||||||||||
1073 | setError(InvalidPortError, auth, colonIndex + 1); | - | ||||||||||||||||||||||||
1074 | if (mode == QUrl::StrictMode)
| 4-6 | ||||||||||||||||||||||||
1075 | break; executed 4 times by 1 test: break; Executed by:
| 4 | ||||||||||||||||||||||||
1076 | } executed 6 times by 1 test: end of block Executed by:
| 6 | ||||||||||||||||||||||||
1077 | } else { | - | ||||||||||||||||||||||||
1078 | port = -1; | - | ||||||||||||||||||||||||
1079 | } executed 4135 times by 20 tests: end of block Executed by:
| 4135 | ||||||||||||||||||||||||
1080 | - | |||||||||||||||||||||||||
1081 | setHost(auth, from, qMin<uint>(end, colonIndex), mode); | - | ||||||||||||||||||||||||
1082 | if (mode == QUrl::StrictMode && !validateComponent(Host, auth, from, qMin<uint>(end, colonIndex))) {
| 6-4825 | ||||||||||||||||||||||||
1083 | // clear host too | - | ||||||||||||||||||||||||
1084 | sectionIsPresent &= ~Authority; | - | ||||||||||||||||||||||||
1085 | break; executed 6 times by 1 test: break; Executed by:
| 6 | ||||||||||||||||||||||||
1086 | } | - | ||||||||||||||||||||||||
1087 | - | |||||||||||||||||||||||||
1088 | // success | - | ||||||||||||||||||||||||
1089 | return; executed 4905 times by 22 tests: return; Executed by:
| 4905 | ||||||||||||||||||||||||
1090 | } | - | ||||||||||||||||||||||||
1091 | // clear all sections but host | - | ||||||||||||||||||||||||
1092 | sectionIsPresent &= ~Authority | Host; | - | ||||||||||||||||||||||||
1093 | userName.clear(); | - | ||||||||||||||||||||||||
1094 | password.clear(); | - | ||||||||||||||||||||||||
1095 | host.clear(); | - | ||||||||||||||||||||||||
1096 | port = -1; | - | ||||||||||||||||||||||||
1097 | } executed 635 times by 9 tests: end of block Executed by:
| 635 | ||||||||||||||||||||||||
1098 | - | |||||||||||||||||||||||||
1099 | inline void QUrlPrivate::setUserInfo(const QString &userInfo, int from, int end) | - | ||||||||||||||||||||||||
1100 | { | - | ||||||||||||||||||||||||
1101 | int delimIndex = userInfo.indexOf(QLatin1Char(':'), from); | - | ||||||||||||||||||||||||
1102 | setUserName(userInfo, from, qMin<uint>(delimIndex, end)); | - | ||||||||||||||||||||||||
1103 | - | |||||||||||||||||||||||||
1104 | if (uint(delimIndex) >= uint(end)) {
| 87-130 | ||||||||||||||||||||||||
1105 | password.clear(); | - | ||||||||||||||||||||||||
1106 | sectionIsPresent &= ~Password; | - | ||||||||||||||||||||||||
1107 | } else { executed 87 times by 4 tests: end of block Executed by:
| 87 | ||||||||||||||||||||||||
1108 | setPassword(userInfo, delimIndex + 1, end); | - | ||||||||||||||||||||||||
1109 | } executed 130 times by 4 tests: end of block Executed by:
| 130 | ||||||||||||||||||||||||
1110 | } | - | ||||||||||||||||||||||||
1111 | - | |||||||||||||||||||||||||
1112 | inline void QUrlPrivate::setUserName(const QString &value, int from, int end) | - | ||||||||||||||||||||||||
1113 | { | - | ||||||||||||||||||||||||
1114 | sectionIsPresent |= UserName; | - | ||||||||||||||||||||||||
1115 | userName = recodeFromUser(value, userNameInIsolation, from, end); | - | ||||||||||||||||||||||||
1116 | } executed 2114 times by 5 tests: end of block Executed by:
| 2114 | ||||||||||||||||||||||||
1117 | - | |||||||||||||||||||||||||
1118 | inline void QUrlPrivate::setPassword(const QString &value, int from, int end) | - | ||||||||||||||||||||||||
1119 | { | - | ||||||||||||||||||||||||
1120 | sectionIsPresent |= Password; | - | ||||||||||||||||||||||||
1121 | password = recodeFromUser(value, passwordInIsolation, from, end); | - | ||||||||||||||||||||||||
1122 | } executed 583 times by 5 tests: end of block Executed by:
| 583 | ||||||||||||||||||||||||
1123 | - | |||||||||||||||||||||||||
1124 | inline void QUrlPrivate::setPath(const QString &value, int from, int end) | - | ||||||||||||||||||||||||
1125 | { | - | ||||||||||||||||||||||||
1126 | // sectionIsPresent |= Path; // not used, save some cycles | - | ||||||||||||||||||||||||
1127 | path = recodeFromUser(value, pathInIsolation, from, end); | - | ||||||||||||||||||||||||
1128 | } executed 15047 times by 35 tests: end of block Executed by:
| 15047 | ||||||||||||||||||||||||
1129 | - | |||||||||||||||||||||||||
1130 | inline void QUrlPrivate::setFragment(const QString &value, int from, int end) | - | ||||||||||||||||||||||||
1131 | { | - | ||||||||||||||||||||||||
1132 | sectionIsPresent |= Fragment; | - | ||||||||||||||||||||||||
1133 | fragment = recodeFromUser(value, fragmentInIsolation, from, end); | - | ||||||||||||||||||||||||
1134 | } executed 1832 times by 8 tests: end of block Executed by:
| 1832 | ||||||||||||||||||||||||
1135 | - | |||||||||||||||||||||||||
1136 | inline void QUrlPrivate::setQuery(const QString &value, int from, int iend) | - | ||||||||||||||||||||||||
1137 | { | - | ||||||||||||||||||||||||
1138 | sectionIsPresent |= Query; | - | ||||||||||||||||||||||||
1139 | query = recodeFromUser(value, queryInIsolation, from, iend); | - | ||||||||||||||||||||||||
1140 | } executed 504 times by 5 tests: end of block Executed by:
| 504 | ||||||||||||||||||||||||
1141 | - | |||||||||||||||||||||||||
1142 | // Host handling | - | ||||||||||||||||||||||||
1143 | // The RFC says the host is: | - | ||||||||||||||||||||||||
1144 | // host = IP-literal / IPv4address / reg-name | - | ||||||||||||||||||||||||
1145 | // IP-literal = "[" ( IPv6address / IPvFuture ) "]" | - | ||||||||||||||||||||||||
1146 | // IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) | - | ||||||||||||||||||||||||
1147 | // [a strict definition of IPv6Address and IPv4Address] | - | ||||||||||||||||||||||||
1148 | // reg-name = *( unreserved / pct-encoded / sub-delims ) | - | ||||||||||||||||||||||||
1149 | // | - | ||||||||||||||||||||||||
1150 | // We deviate from the standard in all but IPvFuture. For IPvFuture we accept | - | ||||||||||||||||||||||||
1151 | // and store only exactly what the RFC says we should. No percent-encoding is | - | ||||||||||||||||||||||||
1152 | // permitted in this field, so Unicode characters and space aren't either. | - | ||||||||||||||||||||||||
1153 | // | - | ||||||||||||||||||||||||
1154 | // For IPv4 addresses, we accept broken addresses like inet_aton does (that is, | - | ||||||||||||||||||||||||
1155 | // less than three dots). However, we correct the address to the proper form | - | ||||||||||||||||||||||||
1156 | // and store the corrected address. After correction, we comply to the RFC and | - | ||||||||||||||||||||||||
1157 | // it's exclusively composed of unreserved characters. | - | ||||||||||||||||||||||||
1158 | // | - | ||||||||||||||||||||||||
1159 | // For IPv6 addresses, we accept addresses including trailing (embedded) IPv4 | - | ||||||||||||||||||||||||
1160 | // addresses, the so-called v4-compat and v4-mapped addresses. We also store | - | ||||||||||||||||||||||||
1161 | // those addresses like that in the hostname field, which violates the spec. | - | ||||||||||||||||||||||||
1162 | // IPv6 hosts are stored with the square brackets in the QString. It also | - | ||||||||||||||||||||||||
1163 | // requires no transformation in any way. | - | ||||||||||||||||||||||||
1164 | // | - | ||||||||||||||||||||||||
1165 | // As for registered names, it's the other way around: we accept only valid | - | ||||||||||||||||||||||||
1166 | // hostnames as specified by STD 3 and IDNA. That means everything we accept is | - | ||||||||||||||||||||||||
1167 | // valid in the RFC definition above, but there are many valid reg-names | - | ||||||||||||||||||||||||
1168 | // according to the RFC that we do not accept in the name of security. Since we | - | ||||||||||||||||||||||||
1169 | // do accept IDNA, reg-names are subject to ACE encoding and decoding, which is | - | ||||||||||||||||||||||||
1170 | // specified by the DecodeUnicode flag. The hostname is stored in its Unicode form. | - | ||||||||||||||||||||||||
1171 | - | |||||||||||||||||||||||||
1172 | inline void QUrlPrivate::appendHost(QString &appendTo, QUrl::FormattingOptions options) const | - | ||||||||||||||||||||||||
1173 | { | - | ||||||||||||||||||||||||
1174 | // EncodeUnicode is the only flag that matters | - | ||||||||||||||||||||||||
1175 | if ((options & QUrl::FullyDecoded) == QUrl::FullyDecoded)
| 5683-9958 | ||||||||||||||||||||||||
1176 | options = 0; executed 9958 times by 34 tests: options = 0; Executed by:
| 9958 | ||||||||||||||||||||||||
1177 | else | - | ||||||||||||||||||||||||
1178 | options &= QUrl::EncodeUnicode; executed 5683 times by 20 tests: options &= QUrl::EncodeUnicode; Executed by:
| 5683 | ||||||||||||||||||||||||
1179 | if (host.isEmpty())
| 1229-14412 | ||||||||||||||||||||||||
1180 | return; executed 1229 times by 21 tests: return; Executed by:
| 1229 | ||||||||||||||||||||||||
1181 | if (host.at(0).unicode() == '[') {
| 187-14225 | ||||||||||||||||||||||||
1182 | // IPv6Address and IPvFuture address never require any transformation | - | ||||||||||||||||||||||||
1183 | appendTo += host; | - | ||||||||||||||||||||||||
1184 | } else { executed 187 times by 7 tests: end of block Executed by:
| 187 | ||||||||||||||||||||||||
1185 | // this is either an IPv4Address or a reg-name | - | ||||||||||||||||||||||||
1186 | // if it is a reg-name, it is already stored in Unicode form | - | ||||||||||||||||||||||||
1187 | if (options & QUrl::EncodeUnicode && !(options & 0x4000000))
| 0-3829 | ||||||||||||||||||||||||
1188 | appendTo += qt_ACE_do(host, ToAceOnly, AllowLeadingDot); executed 3829 times by 17 tests: appendTo += qt_ACE_do(host, ToAceOnly, AllowLeadingDot); Executed by:
| 3829 | ||||||||||||||||||||||||
1189 | else | - | ||||||||||||||||||||||||
1190 | appendTo += host; executed 10396 times by 37 tests: appendTo += host; Executed by:
| 10396 | ||||||||||||||||||||||||
1191 | } | - | ||||||||||||||||||||||||
1192 | } | - | ||||||||||||||||||||||||
1193 | - | |||||||||||||||||||||||||
1194 | // the whole IPvFuture is passed and parsed here, including brackets; | - | ||||||||||||||||||||||||
1195 | // returns null if the parsing was successful, or the QChar of the first failure | - | ||||||||||||||||||||||||
1196 | static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar *end, QUrl::ParsingMode mode) | - | ||||||||||||||||||||||||
1197 | { | - | ||||||||||||||||||||||||
1198 | // IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) | - | ||||||||||||||||||||||||
1199 | static const char acceptable[] = | - | ||||||||||||||||||||||||
1200 | "!$&'()*+,;=" // sub-delims | - | ||||||||||||||||||||||||
1201 | ":" // ":" | - | ||||||||||||||||||||||||
1202 | "-._~"; // unreserved | - | ||||||||||||||||||||||||
1203 | - | |||||||||||||||||||||||||
1204 | // the brackets and the "v" have been checked | - | ||||||||||||||||||||||||
1205 | const QChar *const origBegin = begin; | - | ||||||||||||||||||||||||
1206 | if (begin[3].unicode() != '.')
| 3-28 | ||||||||||||||||||||||||
1207 | return &begin[3]; executed 3 times by 1 test: return &begin[3]; Executed by:
| 3 | ||||||||||||||||||||||||
1208 | if ((begin[2].unicode() >= 'A' && begin[2].unicode() <= 'F') ||
| 2-23 | ||||||||||||||||||||||||
1209 | (begin[2].unicode() >= 'a' && begin[2].unicode() <= 'f') ||
| 1-23 | ||||||||||||||||||||||||
1210 | (begin[2].unicode() >= '0' && begin[2].unicode() <= '9')) {
| 0-24 | ||||||||||||||||||||||||
1211 | // this is so unlikely that we'll just go down the slow path | - | ||||||||||||||||||||||||
1212 | // decode the whole string, skipping the "[vH." and "]" which we already know to be there | - | ||||||||||||||||||||||||
1213 | host += QString::fromRawData(begin, 4); | - | ||||||||||||||||||||||||
1214 | - | |||||||||||||||||||||||||
1215 | // uppercase the version, if necessary | - | ||||||||||||||||||||||||
1216 | if (begin[2].unicode() >= 'a')
| 1-26 | ||||||||||||||||||||||||
1217 | host[host.length() - 2] = begin[2].unicode() - 0x20; executed 1 time by 1 test: host[host.length() - 2] = begin[2].unicode() - 0x20; Executed by:
| 1 | ||||||||||||||||||||||||
1218 | - | |||||||||||||||||||||||||
1219 | begin += 4; | - | ||||||||||||||||||||||||
1220 | --end; | - | ||||||||||||||||||||||||
1221 | - | |||||||||||||||||||||||||
1222 | QString decoded; | - | ||||||||||||||||||||||||
1223 | if (mode == QUrl::TolerantMode && qt_urlRecode(decoded, begin, end, QUrl::FullyDecoded, 0)) {
| 2-25 | ||||||||||||||||||||||||
1224 | begin = decoded.constBegin(); | - | ||||||||||||||||||||||||
1225 | end = decoded.constEnd(); | - | ||||||||||||||||||||||||
1226 | } executed 6 times by 1 test: end of block Executed by:
| 6 | ||||||||||||||||||||||||
1227 | - | |||||||||||||||||||||||||
1228 | for ( ; begin != end; ++begin) {
| 18-123 | ||||||||||||||||||||||||
1229 | if (begin->unicode() >= 'A' && begin->unicode() <= 'Z')
| 12-83 | ||||||||||||||||||||||||
1230 | host += *begin; executed 12 times by 1 test: host += *begin; Executed by:
| 12 | ||||||||||||||||||||||||
1231 | else if (begin->unicode() >= 'a' && begin->unicode() <= 'z')
| 7-88 | ||||||||||||||||||||||||
1232 | host += *begin; executed 16 times by 1 test: host += *begin; Executed by:
| 16 | ||||||||||||||||||||||||
1233 | else if (begin->unicode() >= '0' && begin->unicode() <= '9')
| 22-48 | ||||||||||||||||||||||||
1234 | host += *begin; executed 22 times by 1 test: host += *begin; Executed by:
| 22 | ||||||||||||||||||||||||
1235 | else if (begin->unicode() < 0x80 && strchr(acceptable, begin->unicode()) != 0)
| 1-72 | ||||||||||||||||||||||||
1236 | host += *begin; executed 64 times by 1 test: host += *begin; Executed by:
| 64 | ||||||||||||||||||||||||
1237 | else | - | ||||||||||||||||||||||||
1238 | return decoded.isEmpty() ? begin : &origBegin[2]; executed 9 times by 1 test: return decoded.isEmpty() ? begin : &origBegin[2]; Executed by:
| 9 | ||||||||||||||||||||||||
1239 | } | - | ||||||||||||||||||||||||
1240 | host += QLatin1Char(']'); | - | ||||||||||||||||||||||||
1241 | return 0; executed 18 times by 1 test: return 0; Executed by:
| 18 | ||||||||||||||||||||||||
1242 | } | - | ||||||||||||||||||||||||
1243 | return &origBegin[2]; executed 1 time by 1 test: return &origBegin[2]; Executed by:
| 1 | ||||||||||||||||||||||||
1244 | } | - | ||||||||||||||||||||||||
1245 | - | |||||||||||||||||||||||||
1246 | // ONLY the IPv6 address is parsed here, WITHOUT the brackets | - | ||||||||||||||||||||||||
1247 | static const QChar *parseIp6(QString &host, const QChar *begin, const QChar *end, QUrl::ParsingMode mode) | - | ||||||||||||||||||||||||
1248 | { | - | ||||||||||||||||||||||||
1249 | QIPAddressUtils::IPv6Address address; | - | ||||||||||||||||||||||||
1250 | const QChar *ret = QIPAddressUtils::parseIp6(address, begin, end); | - | ||||||||||||||||||||||||
1251 | if (ret) {
| 44-112 | ||||||||||||||||||||||||
1252 | // this struct is kept in automatic storage because it's only 4 bytes | - | ||||||||||||||||||||||||
1253 | const ushort decodeColon[] = { decode(':'), 0 }; | - | ||||||||||||||||||||||||
1254 | - | |||||||||||||||||||||||||
1255 | // IPv6 failed parsing, check if it was a percent-encoded character in | - | ||||||||||||||||||||||||
1256 | // the middle and try again | - | ||||||||||||||||||||||||
1257 | QString decoded; | - | ||||||||||||||||||||||||
1258 | if (mode == QUrl::TolerantMode && qt_urlRecode(decoded, begin, end, 0, decodeColon)) {
| 4-36 | ||||||||||||||||||||||||
1259 | // recurse | - | ||||||||||||||||||||||||
1260 | // if the parsing fails again, the qt_urlRecode above will return 0 | - | ||||||||||||||||||||||||
1261 | ret = parseIp6(host, decoded.constBegin(), decoded.constEnd(), mode); | - | ||||||||||||||||||||||||
1262 | - | |||||||||||||||||||||||||
1263 | // we can't return ret, otherwise it would be dangling | - | ||||||||||||||||||||||||
1264 | return ret ? end : 0; executed 4 times by 2 tests: return ret ? end : 0; Executed by:
| 4 | ||||||||||||||||||||||||
1265 | } | - | ||||||||||||||||||||||||
1266 | - | |||||||||||||||||||||||||
1267 | // no transformation, nothing to re-parse | - | ||||||||||||||||||||||||
1268 | return ret; executed 40 times by 5 tests: return ret; Executed by:
| 40 | ||||||||||||||||||||||||
1269 | } | - | ||||||||||||||||||||||||
1270 | - | |||||||||||||||||||||||||
1271 | host.reserve(host.size() + (end - begin)); | - | ||||||||||||||||||||||||
1272 | host += QLatin1Char('['); | - | ||||||||||||||||||||||||
1273 | QIPAddressUtils::toString(host, address); | - | ||||||||||||||||||||||||
1274 | host += QLatin1Char(']'); | - | ||||||||||||||||||||||||
1275 | return 0; executed 112 times by 7 tests: return 0; Executed by:
| 112 | ||||||||||||||||||||||||
1276 | } | - | ||||||||||||||||||||||||
1277 | - | |||||||||||||||||||||||||
1278 | inline bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl::ParsingMode mode) | - | ||||||||||||||||||||||||
1279 | { | - | ||||||||||||||||||||||||
1280 | const QChar *begin = value.constData() + from; | - | ||||||||||||||||||||||||
1281 | const QChar *end = value.constData() + iend; | - | ||||||||||||||||||||||||
1282 | - | |||||||||||||||||||||||||
1283 | const int len = end - begin; | - | ||||||||||||||||||||||||
1284 | host.clear(); | - | ||||||||||||||||||||||||
1285 | sectionIsPresent |= Host; | - | ||||||||||||||||||||||||
1286 | if (len == 0)
| 184-11801 | ||||||||||||||||||||||||
1287 | return true; executed 184 times by 7 tests: return true; Executed by:
| 184 | ||||||||||||||||||||||||
1288 | - | |||||||||||||||||||||||||
1289 | if (begin[0].unicode() == '[') {
| 184-11617 | ||||||||||||||||||||||||
1290 | // IPv6Address or IPvFuture | - | ||||||||||||||||||||||||
1291 | // smallest IPv6 address is "[::]" (len = 4) | - | ||||||||||||||||||||||||
1292 | // smallest IPvFuture address is "[v7.X]" (len = 6) | - | ||||||||||||||||||||||||
1293 | if (end[-1].unicode() != ']') {
| 1-183 | ||||||||||||||||||||||||
1294 | setError(HostMissingEndBracket, value); | - | ||||||||||||||||||||||||
1295 | return false; executed 1 time by 1 test: return false; Executed by:
| 1 | ||||||||||||||||||||||||
1296 | } | - | ||||||||||||||||||||||||
1297 | - | |||||||||||||||||||||||||
1298 | if (len > 5 && begin[1].unicode() == 'v') {
| 31-126 | ||||||||||||||||||||||||
1299 | const QChar *c = parseIpFuture(host, begin, end, mode); | - | ||||||||||||||||||||||||
1300 | if (c)
| 13-18 | ||||||||||||||||||||||||
1301 | setError(InvalidIPvFutureError, value, c - value.constData()); executed 13 times by 1 test: setError(InvalidIPvFutureError, value, c - value.constData()); Executed by:
| 13 | ||||||||||||||||||||||||
1302 | return !c; executed 31 times by 1 test: return !c; Executed by:
| 31 | ||||||||||||||||||||||||
1303 | } else if (begin[1].unicode() == 'v') {
| 6-146 | ||||||||||||||||||||||||
1304 | setError(InvalidIPvFutureError, value, from); | - | ||||||||||||||||||||||||
1305 | } executed 6 times by 1 test: end of block Executed by:
| 6 | ||||||||||||||||||||||||
1306 | - | |||||||||||||||||||||||||
1307 | const QChar *c = parseIp6(host, begin + 1, end - 1, mode); | - | ||||||||||||||||||||||||
1308 | if (!c)
| 40-112 | ||||||||||||||||||||||||
1309 | return true; executed 112 times by 7 tests: return true; Executed by:
| 112 | ||||||||||||||||||||||||
1310 | - | |||||||||||||||||||||||||
1311 | if (c == end - 1)
| 12-28 | ||||||||||||||||||||||||
1312 | setError(InvalidIPv6AddressError, value, from); executed 28 times by 3 tests: setError(InvalidIPv6AddressError, value, from); Executed by:
| 28 | ||||||||||||||||||||||||
1313 | else | - | ||||||||||||||||||||||||
1314 | setError(InvalidCharacterInIPv6Error, value, c - value.constData()); executed 12 times by 4 tests: setError(InvalidCharacterInIPv6Error, value, c - value.constData()); Executed by:
| 12 | ||||||||||||||||||||||||
1315 | return false; executed 40 times by 5 tests: return false; Executed by:
| 40 | ||||||||||||||||||||||||
1316 | } | - | ||||||||||||||||||||||||
1317 | - | |||||||||||||||||||||||||
1318 | // check if it's an IPv4 address | - | ||||||||||||||||||||||||
1319 | QIPAddressUtils::IPv4Address ip4; | - | ||||||||||||||||||||||||
1320 | if (QIPAddressUtils::parseIp4(ip4, begin, end)) {
| 1234-10383 | ||||||||||||||||||||||||
1321 | // yes, it was | - | ||||||||||||||||||||||||
1322 | QIPAddressUtils::toString(host, ip4); | - | ||||||||||||||||||||||||
1323 | return true; executed 1234 times by 20 tests: return true; Executed by:
| 1234 | ||||||||||||||||||||||||
1324 | } | - | ||||||||||||||||||||||||
1325 | - | |||||||||||||||||||||||||
1326 | // This is probably a reg-name. | - | ||||||||||||||||||||||||
1327 | // But it can also be an encoded string that, when decoded becomes one | - | ||||||||||||||||||||||||
1328 | // of the types above. | - | ||||||||||||||||||||||||
1329 | // | - | ||||||||||||||||||||||||
1330 | // Two types of encoding are possible: | - | ||||||||||||||||||||||||
1331 | // percent encoding (e.g., "%31%30%2E%30%2E%30%2E%31" -> "10.0.0.1") | - | ||||||||||||||||||||||||
1332 | // Unicode encoding (some non-ASCII characters case-fold to digits | - | ||||||||||||||||||||||||
1333 | // when nameprepping is done) | - | ||||||||||||||||||||||||
1334 | // | - | ||||||||||||||||||||||||
1335 | // The qt_ACE_do function below applies nameprepping and the STD3 check. | - | ||||||||||||||||||||||||
1336 | // That means a Unicode string may become an IPv4 address, but it cannot | - | ||||||||||||||||||||||||
1337 | // produce a '[' or a '%'. | - | ||||||||||||||||||||||||
1338 | - | |||||||||||||||||||||||||
1339 | // check for percent-encoding first | - | ||||||||||||||||||||||||
1340 | QString s; | - | ||||||||||||||||||||||||
1341 | if (mode == QUrl::TolerantMode && qt_urlRecode(s, begin, end, 0, 0)) {
| 54-10255 | ||||||||||||||||||||||||
1342 | // something was decoded | - | ||||||||||||||||||||||||
1343 | // anything encoded left? | - | ||||||||||||||||||||||||
1344 | int pos = s.indexOf(QChar(0x25)); // '%' | - | ||||||||||||||||||||||||
1345 | if (pos != -1) {
| 4-50 | ||||||||||||||||||||||||
1346 | setError(InvalidRegNameError, s, pos); | - | ||||||||||||||||||||||||
1347 | return false; executed 4 times by 1 test: return false; Executed by:
| 4 | ||||||||||||||||||||||||
1348 | } | - | ||||||||||||||||||||||||
1349 | - | |||||||||||||||||||||||||
1350 | // recurse | - | ||||||||||||||||||||||||
1351 | return setHost(s, 0, s.length(), QUrl::StrictMode); executed 50 times by 1 test: return setHost(s, 0, s.length(), QUrl::StrictMode); Executed by:
| 50 | ||||||||||||||||||||||||
1352 | } | - | ||||||||||||||||||||||||
1353 | - | |||||||||||||||||||||||||
1354 | s = qt_ACE_do(QString::fromRawData(begin, len), NormalizeAce, ForbidLeadingDot); | - | ||||||||||||||||||||||||
1355 | if (s.isEmpty()) {
| 114-10215 | ||||||||||||||||||||||||
1356 | setError(InvalidRegNameError, value); | - | ||||||||||||||||||||||||
1357 | return false; executed 114 times by 7 tests: return false; Executed by:
| 114 | ||||||||||||||||||||||||
1358 | } | - | ||||||||||||||||||||||||
1359 | - | |||||||||||||||||||||||||
1360 | // check IPv4 again | - | ||||||||||||||||||||||||
1361 | if (QIPAddressUtils::parseIp4(ip4, s.constBegin(), s.constEnd())) {
| 0-10215 | ||||||||||||||||||||||||
1362 | QIPAddressUtils::toString(host, ip4); | - | ||||||||||||||||||||||||
1363 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
1364 | host = s; | - | ||||||||||||||||||||||||
1365 | } executed 10215 times by 37 tests: end of block Executed by:
| 10215 | ||||||||||||||||||||||||
1366 | return true; executed 10215 times by 37 tests: return true; Executed by:
| 10215 | ||||||||||||||||||||||||
1367 | } | - | ||||||||||||||||||||||||
1368 | - | |||||||||||||||||||||||||
1369 | inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode) | - | ||||||||||||||||||||||||
1370 | { | - | ||||||||||||||||||||||||
1371 | // URI-reference = URI / relative-ref | - | ||||||||||||||||||||||||
1372 | // URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] | - | ||||||||||||||||||||||||
1373 | // relative-ref = relative-part [ "?" query ] [ "#" fragment ] | - | ||||||||||||||||||||||||
1374 | // hier-part = "//" authority path-abempty | - | ||||||||||||||||||||||||
1375 | // / other path types | - | ||||||||||||||||||||||||
1376 | // relative-part = "//" authority path-abempty | - | ||||||||||||||||||||||||
1377 | // / other path types here | - | ||||||||||||||||||||||||
1378 | - | |||||||||||||||||||||||||
1379 | sectionIsPresent = 0; | - | ||||||||||||||||||||||||
1380 | flags = 0; | - | ||||||||||||||||||||||||
1381 | clearError(); | - | ||||||||||||||||||||||||
1382 | - | |||||||||||||||||||||||||
1383 | // find the important delimiters | - | ||||||||||||||||||||||||
1384 | int colon = -1; | - | ||||||||||||||||||||||||
1385 | int question = -1; | - | ||||||||||||||||||||||||
1386 | int hash = -1; | - | ||||||||||||||||||||||||
1387 | const int len = url.length(); | - | ||||||||||||||||||||||||
1388 | const QChar *const begin = url.constData(); | - | ||||||||||||||||||||||||
1389 | const ushort *const data = reinterpret_cast<const ushort *>(begin); | - | ||||||||||||||||||||||||
1390 | - | |||||||||||||||||||||||||
1391 | for (int i = 0; i < len; ++i) {
| 9845-250109 | ||||||||||||||||||||||||
1392 | uint uc = data[i]; | - | ||||||||||||||||||||||||
1393 | if (uc == '#' && hash == -1) {
| 0-249973 | ||||||||||||||||||||||||
1394 | hash = i; | - | ||||||||||||||||||||||||
1395 | - | |||||||||||||||||||||||||
1396 | // nothing more to be found | - | ||||||||||||||||||||||||
1397 | break; executed 136 times by 4 tests: break; Executed by:
| 136 | ||||||||||||||||||||||||
1398 | } | - | ||||||||||||||||||||||||
1399 | - | |||||||||||||||||||||||||
1400 | if (question == -1) {
| 3328-246645 | ||||||||||||||||||||||||
1401 | if (uc == ':' && colon == -1)
| 1146-239302 | ||||||||||||||||||||||||
1402 | colon = i; executed 6197 times by 30 tests: colon = i; Executed by:
| 6197 | ||||||||||||||||||||||||
1403 | else if (uc == '?')
| 345-240103 | ||||||||||||||||||||||||
1404 | question = i; executed 345 times by 5 tests: question = i; Executed by:
| 345 | ||||||||||||||||||||||||
1405 | } executed 246645 times by 34 tests: end of block Executed by:
| 246645 | ||||||||||||||||||||||||
1406 | } executed 249973 times by 34 tests: end of block Executed by:
| 249973 | ||||||||||||||||||||||||
1407 | - | |||||||||||||||||||||||||
1408 | // check if we have a scheme | - | ||||||||||||||||||||||||
1409 | int hierStart; | - | ||||||||||||||||||||||||
1410 | if (colon != -1 && setScheme(url, colon, /* don't set error */ false)) {
| 61-6197 | ||||||||||||||||||||||||
1411 | hierStart = colon + 1; | - | ||||||||||||||||||||||||
1412 | } else { executed 6136 times by 28 tests: end of block Executed by:
| 6136 | ||||||||||||||||||||||||
1413 | // recover from a failed scheme: it might not have been a scheme at all | - | ||||||||||||||||||||||||
1414 | scheme.clear(); | - | ||||||||||||||||||||||||
1415 | sectionIsPresent = 0; | - | ||||||||||||||||||||||||
1416 | hierStart = 0; | - | ||||||||||||||||||||||||
1417 | } executed 3845 times by 16 tests: end of block Executed by:
| 3845 | ||||||||||||||||||||||||
1418 | - | |||||||||||||||||||||||||
1419 | int pathStart; | - | ||||||||||||||||||||||||
1420 | int hierEnd = qMin<uint>(qMin<uint>(question, hash), len); | - | ||||||||||||||||||||||||
1421 | if (hierEnd - hierStart >= 2 && data[hierStart] == '/' && data[hierStart + 1] == '/') {
| 114-9308 | ||||||||||||||||||||||||
1422 | // we have an authority, it ends at the first slash after these | - | ||||||||||||||||||||||||
1423 | int authorityEnd = hierEnd; | - | ||||||||||||||||||||||||
1424 | for (int i = hierStart + 2; i < authorityEnd ; ++i) {
| 2868-86564 | ||||||||||||||||||||||||
1425 | if (data[i] == '/') {
| 2641-83923 | ||||||||||||||||||||||||
1426 | authorityEnd = i; | - | ||||||||||||||||||||||||
1427 | break; executed 2641 times by 22 tests: break; Executed by:
| 2641 | ||||||||||||||||||||||||
1428 | } | - | ||||||||||||||||||||||||
1429 | } executed 83923 times by 22 tests: end of block Executed by:
| 83923 | ||||||||||||||||||||||||
1430 | - | |||||||||||||||||||||||||
1431 | setAuthority(url, hierStart + 2, authorityEnd, parsingMode); | - | ||||||||||||||||||||||||
1432 | - | |||||||||||||||||||||||||
1433 | // even if we failed to set the authority properly, let's try to recover | - | ||||||||||||||||||||||||
1434 | pathStart = authorityEnd; | - | ||||||||||||||||||||||||
1435 | setPath(url, pathStart, hierEnd); | - | ||||||||||||||||||||||||
1436 | } else { executed 5509 times by 28 tests: end of block Executed by:
| 5509 | ||||||||||||||||||||||||
1437 | userName.clear(); | - | ||||||||||||||||||||||||
1438 | password.clear(); | - | ||||||||||||||||||||||||
1439 | host.clear(); | - | ||||||||||||||||||||||||
1440 | port = -1; | - | ||||||||||||||||||||||||
1441 | pathStart = hierStart; | - | ||||||||||||||||||||||||
1442 | - | |||||||||||||||||||||||||
1443 | if (hierStart < hierEnd)
| 642-3830 | ||||||||||||||||||||||||
1444 | setPath(url, hierStart, hierEnd); executed 3830 times by 16 tests: setPath(url, hierStart, hierEnd); Executed by:
| 3830 | ||||||||||||||||||||||||
1445 | else | - | ||||||||||||||||||||||||
1446 | path.clear(); executed 642 times by 13 tests: path.clear(); Executed by:
| 642 | ||||||||||||||||||||||||
1447 | } | - | ||||||||||||||||||||||||
1448 | - | |||||||||||||||||||||||||
1449 | if (uint(question) < uint(hash))
| 345-9636 | ||||||||||||||||||||||||
1450 | setQuery(url, question + 1, qMin<uint>(hash, len)); executed 345 times by 5 tests: setQuery(url, question + 1, qMin<uint>(hash, len)); Executed by:
| 345 | ||||||||||||||||||||||||
1451 | - | |||||||||||||||||||||||||
1452 | if (hash != -1)
| 136-9845 | ||||||||||||||||||||||||
1453 | setFragment(url, hash + 1, len); executed 136 times by 4 tests: setFragment(url, hash + 1, len); Executed by:
| 136 | ||||||||||||||||||||||||
1454 | - | |||||||||||||||||||||||||
1455 | if (error || parsingMode == QUrl::TolerantMode)
| 69-9910 | ||||||||||||||||||||||||
1456 | return; executed 9912 times by 34 tests: return; Executed by:
| 9912 | ||||||||||||||||||||||||
1457 | - | |||||||||||||||||||||||||
1458 | // The parsing so far was partially tolerant of errors, except for the | - | ||||||||||||||||||||||||
1459 | // scheme parser (which is always strict) and the authority (which was | - | ||||||||||||||||||||||||
1460 | // executed in strict mode). | - | ||||||||||||||||||||||||
1461 | // If we haven't found any errors so far, continue the strict-mode parsing | - | ||||||||||||||||||||||||
1462 | // from the path component onwards. | - | ||||||||||||||||||||||||
1463 | - | |||||||||||||||||||||||||
1464 | if (!validateComponent(Path, url, pathStart, hierEnd))
| 5-64 | ||||||||||||||||||||||||
1465 | return; executed 5 times by 2 tests: return; Executed by:
| 5 | ||||||||||||||||||||||||
1466 | if (uint(question) < uint(hash) && !validateComponent(Query, url, question + 1, qMin<uint>(hash, len)))
| 0-63 | ||||||||||||||||||||||||
1467 | return; executed 1 time by 1 test: return; Executed by:
| 1 | ||||||||||||||||||||||||
1468 | if (hash != -1)
| 1-62 | ||||||||||||||||||||||||
1469 | validateComponent(Fragment, url, hash + 1, len); executed 1 time by 1 test: validateComponent(Fragment, url, hash + 1, len); Executed by:
| 1 | ||||||||||||||||||||||||
1470 | } executed 63 times by 4 tests: end of block Executed by:
| 63 | ||||||||||||||||||||||||
1471 | - | |||||||||||||||||||||||||
1472 | QString QUrlPrivate::toLocalFile(QUrl::FormattingOptions options) const | - | ||||||||||||||||||||||||
1473 | { | - | ||||||||||||||||||||||||
1474 | QString tmp; | - | ||||||||||||||||||||||||
1475 | QString ourPath; | - | ||||||||||||||||||||||||
1476 | appendPath(ourPath, options, QUrlPrivate::Path); | - | ||||||||||||||||||||||||
1477 | - | |||||||||||||||||||||||||
1478 | // magic for shared drive on windows | - | ||||||||||||||||||||||||
1479 | if (!host.isEmpty()) {
| 4-10627 | ||||||||||||||||||||||||
1480 | tmp = QLatin1String("//") + host; | - | ||||||||||||||||||||||||
1481 | #ifdef Q_OS_WIN // QTBUG-42346, WebDAV is visible as local file on Windows only. | - | ||||||||||||||||||||||||
1482 | if (scheme == webDavScheme()) | - | ||||||||||||||||||||||||
1483 | tmp += webDavSslTag(); | - | ||||||||||||||||||||||||
1484 | #endif | - | ||||||||||||||||||||||||
1485 | if (!ourPath.isEmpty() && !ourPath.startsWith(QLatin1Char('/')))
| 1-3 | ||||||||||||||||||||||||
1486 | tmp += QLatin1Char('/'); executed 1 time by 1 test: tmp += QLatin1Char('/'); Executed by:
| 1 | ||||||||||||||||||||||||
1487 | tmp += ourPath; | - | ||||||||||||||||||||||||
1488 | } else { executed 4 times by 1 test: end of block Executed by:
| 4 | ||||||||||||||||||||||||
1489 | tmp = ourPath; | - | ||||||||||||||||||||||||
1490 | #ifdef Q_OS_WIN | - | ||||||||||||||||||||||||
1491 | // magic for drives on windows | - | ||||||||||||||||||||||||
1492 | if (ourPath.length() > 2 && ourPath.at(0) == QLatin1Char('/') && ourPath.at(2) == QLatin1Char(':')) | - | ||||||||||||||||||||||||
1493 | tmp.remove(0, 1); | - | ||||||||||||||||||||||||
1494 | #endif | - | ||||||||||||||||||||||||
1495 | } executed 10627 times by 15 tests: end of block Executed by:
| 10627 | ||||||||||||||||||||||||
1496 | return tmp; executed 10631 times by 15 tests: return tmp; Executed by:
| 10631 | ||||||||||||||||||||||||
1497 | } | - | ||||||||||||||||||||||||
1498 | - | |||||||||||||||||||||||||
1499 | /* | - | ||||||||||||||||||||||||
1500 | From http://www.ietf.org/rfc/rfc3986.txt, 5.2.3: Merge paths | - | ||||||||||||||||||||||||
1501 | - | |||||||||||||||||||||||||
1502 | Returns a merge of the current path with the relative path passed | - | ||||||||||||||||||||||||
1503 | as argument. | - | ||||||||||||||||||||||||
1504 | - | |||||||||||||||||||||||||
1505 | Note: \a relativePath is relative (does not start with '/'). | - | ||||||||||||||||||||||||
1506 | */ | - | ||||||||||||||||||||||||
1507 | inline QString QUrlPrivate::mergePaths(const QString &relativePath) const | - | ||||||||||||||||||||||||
1508 | { | - | ||||||||||||||||||||||||
1509 | // If the base URI has a defined authority component and an empty | - | ||||||||||||||||||||||||
1510 | // path, then return a string consisting of "/" concatenated with | - | ||||||||||||||||||||||||
1511 | // the reference's path; otherwise, | - | ||||||||||||||||||||||||
1512 | if (!host.isEmpty() && path.isEmpty())
| 43-2346 | ||||||||||||||||||||||||
1513 | return QLatin1Char('/') + relativePath; executed 1000 times by 1 test: return QLatin1Char('/') + relativePath; Executed by:
| 1000 | ||||||||||||||||||||||||
1514 | - | |||||||||||||||||||||||||
1515 | // Return a string consisting of the reference's path component | - | ||||||||||||||||||||||||
1516 | // appended to all but the last segment of the base URI's path | - | ||||||||||||||||||||||||
1517 | // (i.e., excluding any characters after the right-most "/" in the | - | ||||||||||||||||||||||||
1518 | // base URI path, or excluding the entire base URI path if it does | - | ||||||||||||||||||||||||
1519 | // not contain any "/" characters). | - | ||||||||||||||||||||||||
1520 | QString newPath; | - | ||||||||||||||||||||||||
1521 | if (!path.contains(QLatin1Char('/')))
| 19-2370 | ||||||||||||||||||||||||
1522 | newPath = relativePath; executed 19 times by 2 tests: newPath = relativePath; Executed by:
| 19 | ||||||||||||||||||||||||
1523 | else | - | ||||||||||||||||||||||||
1524 | newPath = path.leftRef(path.lastIndexOf(QLatin1Char('/')) + 1) + relativePath; executed 2370 times by 4 tests: newPath = path.leftRef(path.lastIndexOf(QLatin1Char('/')) + 1) + relativePath; Executed by:
| 2370 | ||||||||||||||||||||||||
1525 | - | |||||||||||||||||||||||||
1526 | return newPath; executed 2389 times by 4 tests: return newPath; Executed by:
| 2389 | ||||||||||||||||||||||||
1527 | } | - | ||||||||||||||||||||||||
1528 | - | |||||||||||||||||||||||||
1529 | /* | - | ||||||||||||||||||||||||
1530 | From http://www.ietf.org/rfc/rfc3986.txt, 5.2.4: Remove dot segments | - | ||||||||||||||||||||||||
1531 | - | |||||||||||||||||||||||||
1532 | Removes unnecessary ../ and ./ from the path. Used for normalizing | - | ||||||||||||||||||||||||
1533 | the URL. | - | ||||||||||||||||||||||||
1534 | */ | - | ||||||||||||||||||||||||
1535 | static void removeDotsFromPath(QString *path) | - | ||||||||||||||||||||||||
1536 | { | - | ||||||||||||||||||||||||
1537 | // The input buffer is initialized with the now-appended path | - | ||||||||||||||||||||||||
1538 | // components and the output buffer is initialized to the empty | - | ||||||||||||||||||||||||
1539 | // string. | - | ||||||||||||||||||||||||
1540 | QChar *out = path->data(); | - | ||||||||||||||||||||||||
1541 | const QChar *in = out; | - | ||||||||||||||||||||||||
1542 | const QChar *end = out + path->size(); | - | ||||||||||||||||||||||||
1543 | - | |||||||||||||||||||||||||
1544 | // If the input buffer consists only of | - | ||||||||||||||||||||||||
1545 | // "." or "..", then remove that from the input | - | ||||||||||||||||||||||||
1546 | // buffer; | - | ||||||||||||||||||||||||
1547 | if (path->size() == 1 && in[0].unicode() == '.')
| 0-4482 | ||||||||||||||||||||||||
1548 | ++in; never executed: ++in; | 0 | ||||||||||||||||||||||||
1549 | else if (path->size() == 2 && in[0].unicode() == '.' && in[1].unicode() == '.')
| 0-4483 | ||||||||||||||||||||||||
1550 | in += 2; never executed: in += 2; | 0 | ||||||||||||||||||||||||
1551 | // While the input buffer is not empty, loop: | - | ||||||||||||||||||||||||
1552 | while (in < end) {
| 4482-37799 | ||||||||||||||||||||||||
1553 | - | |||||||||||||||||||||||||
1554 | // otherwise, if the input buffer begins with a prefix of "../" or "./", | - | ||||||||||||||||||||||||
1555 | // then remove that prefix from the input buffer; | - | ||||||||||||||||||||||||
1556 | if (path->size() >= 2 && in[0].unicode() == '.' && in[1].unicode() == '/')
| 0-37795 | ||||||||||||||||||||||||
1557 | in += 2; never executed: in += 2; | 0 | ||||||||||||||||||||||||
1558 | else if (path->size() >= 3 && in[0].unicode() == '.'
| 1-37792 | ||||||||||||||||||||||||
1559 | && in[1].unicode() == '.' && in[2].unicode() == '/')
| 0-1 | ||||||||||||||||||||||||
1560 | in += 3; executed 1 time by 1 test: in += 3; Executed by:
| 1 | ||||||||||||||||||||||||
1561 | - | |||||||||||||||||||||||||
1562 | // otherwise, if the input buffer begins with a prefix of | - | ||||||||||||||||||||||||
1563 | // "/./" or "/.", where "." is a complete path segment, | - | ||||||||||||||||||||||||
1564 | // then replace that prefix with "/" in the input buffer; | - | ||||||||||||||||||||||||
1565 | if (in <= end - 3 && in[0].unicode() == '/' && in[1].unicode() == '.'
| 31-37746 | ||||||||||||||||||||||||
1566 | && in[2].unicode() == '/') {
| 7-39 | ||||||||||||||||||||||||
1567 | in += 2; | - | ||||||||||||||||||||||||
1568 | continue; executed 7 times by 1 test: continue; Executed by:
| 7 | ||||||||||||||||||||||||
1569 | } else if (in == end - 2 && in[0].unicode() == '/' && in[1].unicode() == '.') {
| 0-37763 | ||||||||||||||||||||||||
1570 | *out++ = QLatin1Char('/'); | - | ||||||||||||||||||||||||
1571 | in += 2; | - | ||||||||||||||||||||||||
1572 | break; executed 2 times by 1 test: break; Executed by:
| 2 | ||||||||||||||||||||||||
1573 | } | - | ||||||||||||||||||||||||
1574 | - | |||||||||||||||||||||||||
1575 | // otherwise, if the input buffer begins with a prefix | - | ||||||||||||||||||||||||
1576 | // of "/../" or "/..", where ".." is a complete path | - | ||||||||||||||||||||||||
1577 | // segment, then replace that prefix with "/" in the | - | ||||||||||||||||||||||||
1578 | // input buffer and remove the last //segment and its | - | ||||||||||||||||||||||||
1579 | // preceding "/" (if any) from the output buffer; | - | ||||||||||||||||||||||||
1580 | if (in <= end - 4 && in[0].unicode() == '/' && in[1].unicode() == '.'
| 31-37733 | ||||||||||||||||||||||||
1581 | && in[2].unicode() == '.' && in[3].unicode() == '/') {
| 0-36 | ||||||||||||||||||||||||
1582 | while (out > path->constData() && (--out)->unicode() != '/')
| 8-111 | ||||||||||||||||||||||||
1583 | ; executed 84 times by 3 tests: ; Executed by:
| 84 | ||||||||||||||||||||||||
1584 | if (out == path->constData() && out->unicode() != '/')
| 3-21 | ||||||||||||||||||||||||
1585 | ++in; executed 3 times by 2 tests: ++in; Executed by:
| 3 | ||||||||||||||||||||||||
1586 | in += 3; | - | ||||||||||||||||||||||||
1587 | continue; executed 35 times by 3 tests: continue; Executed by:
| 35 | ||||||||||||||||||||||||
1588 | } else if (in == end - 3 && in[0].unicode() == '/' && in[1].unicode() == '.'
| 0-37749 | ||||||||||||||||||||||||
1589 | && in[2].unicode() == '.') {
| 1-2 | ||||||||||||||||||||||||
1590 | while (out > path->constData() && (--out)->unicode() != '/')
| 0-4 | ||||||||||||||||||||||||
1591 | ; executed 2 times by 1 test: ; Executed by:
| 2 | ||||||||||||||||||||||||
1592 | if (out->unicode() == '/')
| 0-2 | ||||||||||||||||||||||||
1593 | ++out; executed 2 times by 1 test: ++out; Executed by:
| 2 | ||||||||||||||||||||||||
1594 | in += 3; | - | ||||||||||||||||||||||||
1595 | break; executed 2 times by 1 test: break; Executed by:
| 2 | ||||||||||||||||||||||||
1596 | } | - | ||||||||||||||||||||||||
1597 | - | |||||||||||||||||||||||||
1598 | // otherwise move the first path segment in | - | ||||||||||||||||||||||||
1599 | // the input buffer to the end of the output | - | ||||||||||||||||||||||||
1600 | // buffer, including the initial "/" character | - | ||||||||||||||||||||||||
1601 | // (if any) and any subsequent characters up | - | ||||||||||||||||||||||||
1602 | // to, but not including, the next "/" | - | ||||||||||||||||||||||||
1603 | // character or the end of the input buffer. | - | ||||||||||||||||||||||||
1604 | *out++ = *in++; | - | ||||||||||||||||||||||||
1605 | while (in < end && in->unicode() != '/')
| 3480-267871 | ||||||||||||||||||||||||
1606 | *out++ = *in++; executed 233598 times by 5 tests: *out++ = *in++; Executed by:
| 233598 | ||||||||||||||||||||||||
1607 | } executed 37753 times by 5 tests: end of block Executed by:
| 37753 | ||||||||||||||||||||||||
1608 | path->truncate(out - path->constData()); | - | ||||||||||||||||||||||||
1609 | } executed 4486 times by 5 tests: end of block Executed by:
| 4486 | ||||||||||||||||||||||||
1610 | - | |||||||||||||||||||||||||
1611 | inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, int *position) const | - | ||||||||||||||||||||||||
1612 | { | - | ||||||||||||||||||||||||
1613 | Q_ASSERT(!source == !position); | - | ||||||||||||||||||||||||
1614 | if (error) {
| 464-15857 | ||||||||||||||||||||||||
1615 | if (source) {
| 195-269 | ||||||||||||||||||||||||
1616 | *source = error->source; | - | ||||||||||||||||||||||||
1617 | *position = error->position; | - | ||||||||||||||||||||||||
1618 | } executed 195 times by 1 test: end of block Executed by:
| 195 | ||||||||||||||||||||||||
1619 | return error->code; executed 464 times by 3 tests: return error->code; Executed by:
| 464 | ||||||||||||||||||||||||
1620 | } | - | ||||||||||||||||||||||||
1621 | - | |||||||||||||||||||||||||
1622 | // There are two more cases of invalid URLs that QUrl recognizes and they | - | ||||||||||||||||||||||||
1623 | // are only possible with constructed URLs (setXXX methods), not with | - | ||||||||||||||||||||||||
1624 | // parsing. Therefore, they are tested here. | - | ||||||||||||||||||||||||
1625 | // | - | ||||||||||||||||||||||||
1626 | // The two cases are a non-empty path that doesn't start with a slash and: | - | ||||||||||||||||||||||||
1627 | // - with an authority | - | ||||||||||||||||||||||||
1628 | // - without an authority, without scheme but the path with a colon before | - | ||||||||||||||||||||||||
1629 | // the first slash | - | ||||||||||||||||||||||||
1630 | // Those cases are considered invalid because toString() would produce a URL | - | ||||||||||||||||||||||||
1631 | // that wouldn't be parsed back to the same QUrl. | - | ||||||||||||||||||||||||
1632 | - | |||||||||||||||||||||||||
1633 | if (path.isEmpty() || path.at(0) == QLatin1Char('/'))
| 725-11346 | ||||||||||||||||||||||||
1634 | return NoError; executed 15132 times by 26 tests: return NoError; Executed by:
| 15132 | ||||||||||||||||||||||||
1635 | if (sectionIsPresent & QUrlPrivate::Host) {
| 6-719 | ||||||||||||||||||||||||
1636 | if (source) {
| 1-5 | ||||||||||||||||||||||||
1637 | *source = path; | - | ||||||||||||||||||||||||
1638 | *position = 0; | - | ||||||||||||||||||||||||
1639 | } executed 1 time by 1 test: end of block Executed by:
| 1 | ||||||||||||||||||||||||
1640 | return AuthorityPresentAndPathIsRelative; executed 6 times by 1 test: return AuthorityPresentAndPathIsRelative; Executed by:
| 6 | ||||||||||||||||||||||||
1641 | } | - | ||||||||||||||||||||||||
1642 | if (sectionIsPresent & QUrlPrivate::Scheme)
| 359-360 | ||||||||||||||||||||||||
1643 | return NoError; executed 360 times by 6 tests: return NoError; Executed by:
| 360 | ||||||||||||||||||||||||
1644 | - | |||||||||||||||||||||||||
1645 | // check for a path of "text:text/" | - | ||||||||||||||||||||||||
1646 | for (int i = 0; i < path.length(); ++i) {
| 214-4073 | ||||||||||||||||||||||||
1647 | ushort c = path.at(i).unicode(); | - | ||||||||||||||||||||||||
1648 | if (c == '/') {
| 68-4005 | ||||||||||||||||||||||||
1649 | // found the slash before the colon | - | ||||||||||||||||||||||||
1650 | return NoError; executed 68 times by 4 tests: return NoError; Executed by:
| 68 | ||||||||||||||||||||||||
1651 | } | - | ||||||||||||||||||||||||
1652 | if (c == ':') {
| 77-3928 | ||||||||||||||||||||||||
1653 | // found the colon before the slash, it's invalid | - | ||||||||||||||||||||||||
1654 | if (source) {
| 6-71 | ||||||||||||||||||||||||
1655 | *source = path; | - | ||||||||||||||||||||||||
1656 | *position = i; | - | ||||||||||||||||||||||||
1657 | } executed 6 times by 1 test: end of block Executed by:
| 6 | ||||||||||||||||||||||||
1658 | return RelativeUrlPathContainsColonBeforeSlash; executed 77 times by 2 tests: return RelativeUrlPathContainsColonBeforeSlash; Executed by:
| 77 | ||||||||||||||||||||||||
1659 | } | - | ||||||||||||||||||||||||
1660 | } executed 3928 times by 9 tests: end of block Executed by:
| 3928 | ||||||||||||||||||||||||
1661 | return NoError; executed 214 times by 7 tests: return NoError; Executed by:
| 214 | ||||||||||||||||||||||||
1662 | } | - | ||||||||||||||||||||||||
1663 | - | |||||||||||||||||||||||||
1664 | bool QUrlPrivate::validateComponent(QUrlPrivate::Section section, const QString &input, | - | ||||||||||||||||||||||||
1665 | int begin, int end) | - | ||||||||||||||||||||||||
1666 | { | - | ||||||||||||||||||||||||
1667 | // What we need to look out for, that the regular parser tolerates: | - | ||||||||||||||||||||||||
1668 | // - percent signs not followed by two hex digits | - | ||||||||||||||||||||||||
1669 | // - forbidden characters, which should always appear encoded | - | ||||||||||||||||||||||||
1670 | // '"' / '<' / '>' / '\' / '^' / '`' / '{' / '|' / '}' / BKSP | - | ||||||||||||||||||||||||
1671 | // control characters | - | ||||||||||||||||||||||||
1672 | // - delimiters not allowed in certain positions | - | ||||||||||||||||||||||||
1673 | // . scheme: parser is already strict | - | ||||||||||||||||||||||||
1674 | // . user info: gen-delims except ":" disallowed ("/" / "?" / "#" / "[" / "]" / "@") | - | ||||||||||||||||||||||||
1675 | // . host: parser is stricter than the standard | - | ||||||||||||||||||||||||
1676 | // . port: parser is stricter than the standard | - | ||||||||||||||||||||||||
1677 | // . path: all delimiters allowed | - | ||||||||||||||||||||||||
1678 | // . fragment: all delimiters allowed | - | ||||||||||||||||||||||||
1679 | // . query: all delimiters allowed | - | ||||||||||||||||||||||||
1680 | static const char forbidden[] = "\"<>\\^`{|}\x7F"; | - | ||||||||||||||||||||||||
1681 | static const char forbiddenUserInfo[] = ":/?#[]@"; | - | ||||||||||||||||||||||||
1682 | - | |||||||||||||||||||||||||
1683 | Q_ASSERT(section != Authority && section != Hierarchy && section != FullUrl); | - | ||||||||||||||||||||||||
1684 | - | |||||||||||||||||||||||||
1685 | const ushort *const data = reinterpret_cast<const ushort *>(input.constData()); | - | ||||||||||||||||||||||||
1686 | for (uint i = uint(begin); i < uint(end); ++i) {
| 147-3620 | ||||||||||||||||||||||||
1687 | uint uc = data[i]; | - | ||||||||||||||||||||||||
1688 | if (uc >= 0x80)
| 11-3609 | ||||||||||||||||||||||||
1689 | continue; executed 11 times by 1 test: continue; Executed by:
| 11 | ||||||||||||||||||||||||
1690 | - | |||||||||||||||||||||||||
1691 | bool error = false; | - | ||||||||||||||||||||||||
1692 | if ((uc == '%' && (uint(end) < i + 2 || !isHex(data[i + 1]) || !isHex(data[i + 2])))
| 1-3576 | ||||||||||||||||||||||||
1693 | || uc <= 0x20 || strchr(forbidden, uc)) {
| 4-3589 | ||||||||||||||||||||||||
1694 | // found an error | - | ||||||||||||||||||||||||
1695 | error = true; | - | ||||||||||||||||||||||||
1696 | } else if (section & UserInfo) { executed 34 times by 2 tests: end of block Executed by:
| 34-3500 | ||||||||||||||||||||||||
1697 | if (section == UserInfo && strchr(forbiddenUserInfo + 1, uc))
| 1-53 | ||||||||||||||||||||||||
1698 | error = true; executed 1 time by 1 test: error = true; Executed by:
| 1 | ||||||||||||||||||||||||
1699 | else if (section != UserInfo && strchr(forbiddenUserInfo, uc))
| 4-52 | ||||||||||||||||||||||||
1700 | error = true; executed 4 times by 1 test: error = true; Executed by:
| 4 | ||||||||||||||||||||||||
1701 | } executed 75 times by 1 test: end of block Executed by:
| 75 | ||||||||||||||||||||||||
1702 | - | |||||||||||||||||||||||||
1703 | if (!error)
| 39-3570 | ||||||||||||||||||||||||
1704 | continue; executed 3570 times by 4 tests: continue; Executed by:
| 3570 | ||||||||||||||||||||||||
1705 | - | |||||||||||||||||||||||||
1706 | ErrorCode errorCode = ErrorCode(int(section) << 8); | - | ||||||||||||||||||||||||
1707 | if (section == UserInfo) {
| 12-27 | ||||||||||||||||||||||||
1708 | // is it the user name or the password? | - | ||||||||||||||||||||||||
1709 | errorCode = InvalidUserNameError; | - | ||||||||||||||||||||||||
1710 | for (uint j = uint(begin); j < i; ++j)
| 9-41 | ||||||||||||||||||||||||
1711 | if (data[j] == ':') {
|