Absolute File Name: | /home/qt/qt5_coco/qt5/qtbase/src/corelib/io/qurlrecode.cpp |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | /**************************************************************************** | - | ||||||||||||||||||
2 | ** | - | ||||||||||||||||||
3 | ** Copyright (C) 2016 Intel Corporation. | - | ||||||||||||||||||
4 | ** Contact: https://www.qt.io/licensing/ | - | ||||||||||||||||||
5 | ** | - | ||||||||||||||||||
6 | ** This file is part of the QtCore module of the Qt Toolkit. | - | ||||||||||||||||||
7 | ** | - | ||||||||||||||||||
8 | ** $QT_BEGIN_LICENSE:LGPL$ | - | ||||||||||||||||||
9 | ** Commercial License Usage | - | ||||||||||||||||||
10 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||||||||||||||
11 | ** accordance with the commercial license agreement provided with the | - | ||||||||||||||||||
12 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||||||||||||||
13 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||||||||||||||
14 | ** and conditions see https://www.qt.io/terms-conditions. For further | - | ||||||||||||||||||
15 | ** information use the contact form at https://www.qt.io/contact-us. | - | ||||||||||||||||||
16 | ** | - | ||||||||||||||||||
17 | ** GNU Lesser General Public License Usage | - | ||||||||||||||||||
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||||||||||||||
19 | ** General Public License version 3 as published by the Free Software | - | ||||||||||||||||||
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | - | ||||||||||||||||||
21 | ** packaging of this file. Please review the following information to | - | ||||||||||||||||||
22 | ** ensure the GNU Lesser General Public License version 3 requirements | - | ||||||||||||||||||
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | - | ||||||||||||||||||
24 | ** | - | ||||||||||||||||||
25 | ** GNU General Public License Usage | - | ||||||||||||||||||
26 | ** Alternatively, this file may be used under the terms of the GNU | - | ||||||||||||||||||
27 | ** General Public License version 2.0 or (at your option) the GNU General | - | ||||||||||||||||||
28 | ** Public license version 3 or any later version approved by the KDE Free | - | ||||||||||||||||||
29 | ** Qt Foundation. The licenses are as published by the Free Software | - | ||||||||||||||||||
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | - | ||||||||||||||||||
31 | ** included in the packaging of this file. Please review the following | - | ||||||||||||||||||
32 | ** information to ensure the GNU General Public License requirements will | - | ||||||||||||||||||
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | - | ||||||||||||||||||
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | - | ||||||||||||||||||
35 | ** | - | ||||||||||||||||||
36 | ** $QT_END_LICENSE$ | - | ||||||||||||||||||
37 | ** | - | ||||||||||||||||||
38 | ****************************************************************************/ | - | ||||||||||||||||||
39 | - | |||||||||||||||||||
40 | #include "qurl.h" | - | ||||||||||||||||||
41 | #include "private/qutfcodec_p.h" | - | ||||||||||||||||||
42 | #include "private/qtools_p.h" | - | ||||||||||||||||||
43 | - | |||||||||||||||||||
44 | QT_BEGIN_NAMESPACE | - | ||||||||||||||||||
45 | - | |||||||||||||||||||
46 | // ### move to qurl_p.h | - | ||||||||||||||||||
47 | enum EncodingAction { | - | ||||||||||||||||||
48 | DecodeCharacter = 0, | - | ||||||||||||||||||
49 | LeaveCharacter = 1, | - | ||||||||||||||||||
50 | EncodeCharacter = 2 | - | ||||||||||||||||||
51 | }; | - | ||||||||||||||||||
52 | - | |||||||||||||||||||
53 | // From RFC 3896, Appendix A Collected ABNF for URI | - | ||||||||||||||||||
54 | // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" | - | ||||||||||||||||||
55 | // reserved = gen-delims / sub-delims | - | ||||||||||||||||||
56 | // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" | - | ||||||||||||||||||
57 | // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" | - | ||||||||||||||||||
58 | // / "*" / "+" / "," / ";" / "=" | - | ||||||||||||||||||
59 | static const uchar defaultActionTable[96] = { | - | ||||||||||||||||||
60 | 2, // space | - | ||||||||||||||||||
61 | 1, // '!' (sub-delim) | - | ||||||||||||||||||
62 | 2, // '"' | - | ||||||||||||||||||
63 | 1, // '#' (gen-delim) | - | ||||||||||||||||||
64 | 1, // '$' (gen-delim) | - | ||||||||||||||||||
65 | 2, // '%' (percent) | - | ||||||||||||||||||
66 | 1, // '&' (gen-delim) | - | ||||||||||||||||||
67 | 1, // "'" (sub-delim) | - | ||||||||||||||||||
68 | 1, // '(' (sub-delim) | - | ||||||||||||||||||
69 | 1, // ')' (sub-delim) | - | ||||||||||||||||||
70 | 1, // '*' (sub-delim) | - | ||||||||||||||||||
71 | 1, // '+' (sub-delim) | - | ||||||||||||||||||
72 | 1, // ',' (sub-delim) | - | ||||||||||||||||||
73 | 0, // '-' (unreserved) | - | ||||||||||||||||||
74 | 0, // '.' (unreserved) | - | ||||||||||||||||||
75 | 1, // '/' (gen-delim) | - | ||||||||||||||||||
76 | - | |||||||||||||||||||
77 | 0, 0, 0, 0, 0, // '0' to '4' (unreserved) | - | ||||||||||||||||||
78 | 0, 0, 0, 0, 0, // '5' to '9' (unreserved) | - | ||||||||||||||||||
79 | 1, // ':' (gen-delim) | - | ||||||||||||||||||
80 | 1, // ';' (sub-delim) | - | ||||||||||||||||||
81 | 2, // '<' | - | ||||||||||||||||||
82 | 1, // '=' (sub-delim) | - | ||||||||||||||||||
83 | 2, // '>' | - | ||||||||||||||||||
84 | 1, // '?' (gen-delim) | - | ||||||||||||||||||
85 | - | |||||||||||||||||||
86 | 1, // '@' (gen-delim) | - | ||||||||||||||||||
87 | 0, 0, 0, 0, 0, // 'A' to 'E' (unreserved) | - | ||||||||||||||||||
88 | 0, 0, 0, 0, 0, // 'F' to 'J' (unreserved) | - | ||||||||||||||||||
89 | 0, 0, 0, 0, 0, // 'K' to 'O' (unreserved) | - | ||||||||||||||||||
90 | 0, 0, 0, 0, 0, // 'P' to 'T' (unreserved) | - | ||||||||||||||||||
91 | 0, 0, 0, 0, 0, 0, // 'U' to 'Z' (unreserved) | - | ||||||||||||||||||
92 | 1, // '[' (gen-delim) | - | ||||||||||||||||||
93 | 2, // '\' | - | ||||||||||||||||||
94 | 1, // ']' (gen-delim) | - | ||||||||||||||||||
95 | 2, // '^' | - | ||||||||||||||||||
96 | 0, // '_' (unreserved) | - | ||||||||||||||||||
97 | - | |||||||||||||||||||
98 | 2, // '`' | - | ||||||||||||||||||
99 | 0, 0, 0, 0, 0, // 'a' to 'e' (unreserved) | - | ||||||||||||||||||
100 | 0, 0, 0, 0, 0, // 'f' to 'j' (unreserved) | - | ||||||||||||||||||
101 | 0, 0, 0, 0, 0, // 'k' to 'o' (unreserved) | - | ||||||||||||||||||
102 | 0, 0, 0, 0, 0, // 'p' to 't' (unreserved) | - | ||||||||||||||||||
103 | 0, 0, 0, 0, 0, 0, // 'u' to 'z' (unreserved) | - | ||||||||||||||||||
104 | 2, // '{' | - | ||||||||||||||||||
105 | 2, // '|' | - | ||||||||||||||||||
106 | 2, // '}' | - | ||||||||||||||||||
107 | 0, // '~' (unreserved) | - | ||||||||||||||||||
108 | - | |||||||||||||||||||
109 | 2 // BSKP | - | ||||||||||||||||||
110 | }; | - | ||||||||||||||||||
111 | - | |||||||||||||||||||
112 | // mask tables, in negative polarity | - | ||||||||||||||||||
113 | // 0x00 if it belongs to this category | - | ||||||||||||||||||
114 | // 0xff if it doesn't | - | ||||||||||||||||||
115 | - | |||||||||||||||||||
116 | static const uchar reservedMask[96] = { | - | ||||||||||||||||||
117 | 0xff, // space | - | ||||||||||||||||||
118 | 0xff, // '!' (sub-delim) | - | ||||||||||||||||||
119 | 0x00, // '"' | - | ||||||||||||||||||
120 | 0xff, // '#' (gen-delim) | - | ||||||||||||||||||
121 | 0xff, // '$' (gen-delim) | - | ||||||||||||||||||
122 | 0xff, // '%' (percent) | - | ||||||||||||||||||
123 | 0xff, // '&' (gen-delim) | - | ||||||||||||||||||
124 | 0xff, // "'" (sub-delim) | - | ||||||||||||||||||
125 | 0xff, // '(' (sub-delim) | - | ||||||||||||||||||
126 | 0xff, // ')' (sub-delim) | - | ||||||||||||||||||
127 | 0xff, // '*' (sub-delim) | - | ||||||||||||||||||
128 | 0xff, // '+' (sub-delim) | - | ||||||||||||||||||
129 | 0xff, // ',' (sub-delim) | - | ||||||||||||||||||
130 | 0xff, // '-' (unreserved) | - | ||||||||||||||||||
131 | 0xff, // '.' (unreserved) | - | ||||||||||||||||||
132 | 0xff, // '/' (gen-delim) | - | ||||||||||||||||||
133 | - | |||||||||||||||||||
134 | 0xff, 0xff, 0xff, 0xff, 0xff, // '0' to '4' (unreserved) | - | ||||||||||||||||||
135 | 0xff, 0xff, 0xff, 0xff, 0xff, // '5' to '9' (unreserved) | - | ||||||||||||||||||
136 | 0xff, // ':' (gen-delim) | - | ||||||||||||||||||
137 | 0xff, // ';' (sub-delim) | - | ||||||||||||||||||
138 | 0x00, // '<' | - | ||||||||||||||||||
139 | 0xff, // '=' (sub-delim) | - | ||||||||||||||||||
140 | 0x00, // '>' | - | ||||||||||||||||||
141 | 0xff, // '?' (gen-delim) | - | ||||||||||||||||||
142 | - | |||||||||||||||||||
143 | 0xff, // '@' (gen-delim) | - | ||||||||||||||||||
144 | 0xff, 0xff, 0xff, 0xff, 0xff, // 'A' to 'E' (unreserved) | - | ||||||||||||||||||
145 | 0xff, 0xff, 0xff, 0xff, 0xff, // 'F' to 'J' (unreserved) | - | ||||||||||||||||||
146 | 0xff, 0xff, 0xff, 0xff, 0xff, // 'K' to 'O' (unreserved) | - | ||||||||||||||||||
147 | 0xff, 0xff, 0xff, 0xff, 0xff, // 'P' to 'T' (unreserved) | - | ||||||||||||||||||
148 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'U' to 'Z' (unreserved) | - | ||||||||||||||||||
149 | 0xff, // '[' (gen-delim) | - | ||||||||||||||||||
150 | 0x00, // '\' | - | ||||||||||||||||||
151 | 0xff, // ']' (gen-delim) | - | ||||||||||||||||||
152 | 0x00, // '^' | - | ||||||||||||||||||
153 | 0xff, // '_' (unreserved) | - | ||||||||||||||||||
154 | - | |||||||||||||||||||
155 | 0x00, // '`' | - | ||||||||||||||||||
156 | 0xff, 0xff, 0xff, 0xff, 0xff, // 'a' to 'e' (unreserved) | - | ||||||||||||||||||
157 | 0xff, 0xff, 0xff, 0xff, 0xff, // 'f' to 'j' (unreserved) | - | ||||||||||||||||||
158 | 0xff, 0xff, 0xff, 0xff, 0xff, // 'k' to 'o' (unreserved) | - | ||||||||||||||||||
159 | 0xff, 0xff, 0xff, 0xff, 0xff, // 'p' to 't' (unreserved) | - | ||||||||||||||||||
160 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'u' to 'z' (unreserved) | - | ||||||||||||||||||
161 | 0x00, // '{' | - | ||||||||||||||||||
162 | 0x00, // '|' | - | ||||||||||||||||||
163 | 0x00, // '}' | - | ||||||||||||||||||
164 | 0xff, // '~' (unreserved) | - | ||||||||||||||||||
165 | - | |||||||||||||||||||
166 | 0xff // BSKP | - | ||||||||||||||||||
167 | }; | - | ||||||||||||||||||
168 | - | |||||||||||||||||||
169 | static inline bool isHex(ushort c) | - | ||||||||||||||||||
170 | { | - | ||||||||||||||||||
171 | return (c >= 'a' && c <= 'f') || executed 6573 times by 10 tests: return (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || (c >= '0' && c <= '9'); Executed by:
| 6573 | ||||||||||||||||||
172 | (c >= 'A' && c <= 'F') || executed 6573 times by 10 tests: return (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || (c >= '0' && c <= '9'); Executed by:
| 6573 | ||||||||||||||||||
173 | (c >= '0' && c <= '9'); executed 6573 times by 10 tests: return (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || (c >= '0' && c <= '9'); Executed by:
| 6573 | ||||||||||||||||||
174 | } | - | ||||||||||||||||||
175 | - | |||||||||||||||||||
176 | static inline bool isUpperHex(ushort c) | - | ||||||||||||||||||
177 | { | - | ||||||||||||||||||
178 | // undefined behaviour if c isn't an hex char! | - | ||||||||||||||||||
179 | return c < 0x60; executed 4803 times by 6 tests: return c < 0x60; Executed by:
| 4803 | ||||||||||||||||||
180 | } | - | ||||||||||||||||||
181 | - | |||||||||||||||||||
182 | static inline ushort toUpperHex(ushort c) | - | ||||||||||||||||||
183 | { | - | ||||||||||||||||||
184 | return isUpperHex(c) ? c : c - 0x20; executed 248 times by 4 tests: return isUpperHex(c) ? c : c - 0x20; Executed by:
| 248 | ||||||||||||||||||
185 | } | - | ||||||||||||||||||
186 | - | |||||||||||||||||||
187 | static inline ushort decodeNibble(ushort c) | - | ||||||||||||||||||
188 | { | - | ||||||||||||||||||
189 | return c >= 'a' ? c - 'a' + 0xA : executed 6506 times by 10 tests: return c >= 'a' ? c - 'a' + 0xA : c >= 'A' ? c - 'A' + 0xA : c - '0'; Executed by:
| 6506 | ||||||||||||||||||
190 | c >= 'A' ? c - 'A' + 0xA : c - '0'; executed 6506 times by 10 tests: return c >= 'a' ? c - 'a' + 0xA : c >= 'A' ? c - 'A' + 0xA : c - '0'; Executed by:
| 6506 | ||||||||||||||||||
191 | } | - | ||||||||||||||||||
192 | - | |||||||||||||||||||
193 | // if the sequence at input is 2*HEXDIG, returns its decoding | - | ||||||||||||||||||
194 | // returns -1 if it isn't. | - | ||||||||||||||||||
195 | // assumes that the range has been checked already | - | ||||||||||||||||||
196 | static inline ushort decodePercentEncoding(const ushort *input) | - | ||||||||||||||||||
197 | { | - | ||||||||||||||||||
198 | ushort c1 = input[1]; | - | ||||||||||||||||||
199 | ushort c2 = input[2]; | - | ||||||||||||||||||
200 | if (!isHex(c1) || !isHex(c2))
| 13-3189 | ||||||||||||||||||
201 | return ushort(-1); executed 33 times by 3 tests: return ushort(-1); Executed by:
| 33 | ||||||||||||||||||
202 | return decodeNibble(c1) << 4 | decodeNibble(c2); executed 3169 times by 10 tests: return decodeNibble(c1) << 4 | decodeNibble(c2); Executed by:
| 3169 | ||||||||||||||||||
203 | } | - | ||||||||||||||||||
204 | - | |||||||||||||||||||
205 | static inline ushort encodeNibble(ushort c) | - | ||||||||||||||||||
206 | { | - | ||||||||||||||||||
207 | return ushort(QtMiscUtils::toHexUpper(c)); executed 4489 times by 9 tests: return ushort(QtMiscUtils::toHexUpper(c)); Executed by:
| 4489 | ||||||||||||||||||
208 | } | - | ||||||||||||||||||
209 | - | |||||||||||||||||||
210 | static void ensureDetached(QString &result, ushort *&output, const ushort *begin, const ushort *input, const ushort *end, | - | ||||||||||||||||||
211 | int add = 0) | - | ||||||||||||||||||
212 | { | - | ||||||||||||||||||
213 | if (!output) {
| 1322-1460 | ||||||||||||||||||
214 | // now detach | - | ||||||||||||||||||
215 | // create enough space if the rest of the string needed to be percent-encoded | - | ||||||||||||||||||
216 | int charsProcessed = input - begin; | - | ||||||||||||||||||
217 | int charsRemaining = end - input; | - | ||||||||||||||||||
218 | int spaceNeeded = end - begin + 2 * charsRemaining + add; | - | ||||||||||||||||||
219 | int origSize = result.size(); | - | ||||||||||||||||||
220 | result.resize(origSize + spaceNeeded); | - | ||||||||||||||||||
221 | - | |||||||||||||||||||
222 | // we know that resize() above detached, so we bypass the reference count check | - | ||||||||||||||||||
223 | output = const_cast<ushort *>(reinterpret_cast<const ushort *>(result.constData())) | - | ||||||||||||||||||
224 | + origSize; | - | ||||||||||||||||||
225 | - | |||||||||||||||||||
226 | // copy the chars we've already processed | - | ||||||||||||||||||
227 | int i; | - | ||||||||||||||||||
228 | for (i = 0; i < charsProcessed; ++i)
| 1460-10259 | ||||||||||||||||||
229 | output[i] = begin[i]; executed 10259 times by 9 tests: output[i] = begin[i]; Executed by:
| 10259 | ||||||||||||||||||
230 | output += i; | - | ||||||||||||||||||
231 | } executed 1460 times by 9 tests: end of block Executed by:
| 1460 | ||||||||||||||||||
232 | } executed 2782 times by 9 tests: end of block Executed by:
| 2782 | ||||||||||||||||||
233 | - | |||||||||||||||||||
234 | namespace { | - | ||||||||||||||||||
235 | struct QUrlUtf8Traits : public QUtf8BaseTraitsNoAscii | - | ||||||||||||||||||
236 | { | - | ||||||||||||||||||
237 | // From RFC 3987: | - | ||||||||||||||||||
238 | // iunreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" / ucschar | - | ||||||||||||||||||
239 | // | - | ||||||||||||||||||
240 | // ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF | - | ||||||||||||||||||
241 | // / %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD | - | ||||||||||||||||||
242 | // / %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD | - | ||||||||||||||||||
243 | // / %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD | - | ||||||||||||||||||
244 | // / %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD | - | ||||||||||||||||||
245 | // / %xD0000-DFFFD / %xE1000-EFFFD | - | ||||||||||||||||||
246 | // | - | ||||||||||||||||||
247 | // iprivate = %xE000-F8FF / %xF0000-FFFFD / %x100000-10FFFD | - | ||||||||||||||||||
248 | // | - | ||||||||||||||||||
249 | // That RFC allows iprivate only as part of iquery, but we don't know here | - | ||||||||||||||||||
250 | // whether we're looking at a query or another part of an URI, so we accept | - | ||||||||||||||||||
251 | // them too. The definition above excludes U+FFF0 to U+FFFD from appearing | - | ||||||||||||||||||
252 | // unencoded, but we see no reason for its exclusion, so we allow them to | - | ||||||||||||||||||
253 | // be decoded (and we need U+FFFD the replacement character to indicate | - | ||||||||||||||||||
254 | // failure to decode). | - | ||||||||||||||||||
255 | // | - | ||||||||||||||||||
256 | // That means we must disallow: | - | ||||||||||||||||||
257 | // * unpaired surrogates (QUtf8Functions takes care of that for us) | - | ||||||||||||||||||
258 | // * non-characters | - | ||||||||||||||||||
259 | static const bool allowNonCharacters = false; | - | ||||||||||||||||||
260 | - | |||||||||||||||||||
261 | // override: our "bytes" are three percent-encoded UTF-16 characters | - | ||||||||||||||||||
262 | static void appendByte(ushort *&ptr, uchar b) | - | ||||||||||||||||||
263 | { | - | ||||||||||||||||||
264 | // b >= 0x80, by construction, so percent-encode | - | ||||||||||||||||||
265 | *ptr++ = '%'; | - | ||||||||||||||||||
266 | *ptr++ = encodeNibble(b >> 4); | - | ||||||||||||||||||
267 | *ptr++ = encodeNibble(b & 0xf); | - | ||||||||||||||||||
268 | } executed 233 times by 4 tests: end of block Executed by:
| 233 | ||||||||||||||||||
269 | - | |||||||||||||||||||
270 | static uchar peekByte(const ushort *ptr, int n = 0) | - | ||||||||||||||||||
271 | { | - | ||||||||||||||||||
272 | // decodePercentEncoding returns ushort(-1) if it can't decode, | - | ||||||||||||||||||
273 | // which means we return 0xff, which is not a valid continuation byte. | - | ||||||||||||||||||
274 | // If ptr[i * 3] is not '%', we'll multiply by zero and return 0, | - | ||||||||||||||||||
275 | // also not a valid continuation byte (if it's '%', we multiply by 1). | - | ||||||||||||||||||
276 | return uchar(decodePercentEncoding(ptr + n * 3)) executed 321 times by 4 tests: return uchar(decodePercentEncoding(ptr + n * 3)) * uchar(ptr[n * 3] == '%'); Executed by:
| 321 | ||||||||||||||||||
277 | * uchar(ptr[n * 3] == '%'); executed 321 times by 4 tests: return uchar(decodePercentEncoding(ptr + n * 3)) * uchar(ptr[n * 3] == '%'); Executed by:
| 321 | ||||||||||||||||||
278 | } | - | ||||||||||||||||||
279 | - | |||||||||||||||||||
280 | static qptrdiff availableBytes(const ushort *ptr, const ushort *end) | - | ||||||||||||||||||
281 | { | - | ||||||||||||||||||
282 | return (end - ptr) / 3; executed 204 times by 5 tests: return (end - ptr) / 3; Executed by:
| 204 | ||||||||||||||||||
283 | } | - | ||||||||||||||||||
284 | - | |||||||||||||||||||
285 | static void advanceByte(const ushort *&ptr, int n = 1) | - | ||||||||||||||||||
286 | { | - | ||||||||||||||||||
287 | ptr += n * 3; | - | ||||||||||||||||||
288 | } executed 96 times by 4 tests: end of block Executed by:
| 96 | ||||||||||||||||||
289 | }; | - | ||||||||||||||||||
290 | } | - | ||||||||||||||||||
291 | - | |||||||||||||||||||
292 | // returns true if we performed an UTF-8 decoding | - | ||||||||||||||||||
293 | static bool encodedUtf8ToUtf16(QString &result, ushort *&output, const ushort *begin, const ushort *&input, | - | ||||||||||||||||||
294 | const ushort *end, ushort decoded) | - | ||||||||||||||||||
295 | { | - | ||||||||||||||||||
296 | uint ucs4, *dst = &ucs4; | - | ||||||||||||||||||
297 | const ushort *src = input + 3;// skip the %XX that yielded \a decoded | - | ||||||||||||||||||
298 | int charsNeeded = QUtf8Functions::fromUtf8<QUrlUtf8Traits>(decoded, dst, src, end); | - | ||||||||||||||||||
299 | if (charsNeeded < 0)
| 96-395 | ||||||||||||||||||
300 | return false; executed 395 times by 3 tests: return false; Executed by:
| 395 | ||||||||||||||||||
301 | - | |||||||||||||||||||
302 | if (!QChar::requiresSurrogates(ucs4)) {
| 4-92 | ||||||||||||||||||
303 | // UTF-8 decoded and no surrogates are required | - | ||||||||||||||||||
304 | // detach if necessary | - | ||||||||||||||||||
305 | // possibilities are: 6 chars (%XX%XX) -> one char; 9 chars (%XX%XX%XX) -> one char | - | ||||||||||||||||||
306 | ensureDetached(result, output, begin, input, end, -3 * charsNeeded + 1); | - | ||||||||||||||||||
307 | *output++ = ucs4; | - | ||||||||||||||||||
308 | } else { executed 92 times by 4 tests: end of block Executed by:
| 92 | ||||||||||||||||||
309 | // UTF-8 decoded to something that requires a surrogate pair | - | ||||||||||||||||||
310 | // compressing from %XX%XX%XX%XX (12 chars) to two | - | ||||||||||||||||||
311 | ensureDetached(result, output, begin, input, end, -10); | - | ||||||||||||||||||
312 | *output++ = QChar::highSurrogate(ucs4); | - | ||||||||||||||||||
313 | *output++ = QChar::lowSurrogate(ucs4); | - | ||||||||||||||||||
314 | } executed 4 times by 2 tests: end of block Executed by:
| 4 | ||||||||||||||||||
315 | - | |||||||||||||||||||
316 | input = src - 1; | - | ||||||||||||||||||
317 | return true; executed 96 times by 4 tests: return true; Executed by:
| 96 | ||||||||||||||||||
318 | } | - | ||||||||||||||||||
319 | - | |||||||||||||||||||
320 | static void unicodeToEncodedUtf8(QString &result, ushort *&output, const ushort *begin, | - | ||||||||||||||||||
321 | const ushort *&input, const ushort *end, ushort decoded) | - | ||||||||||||||||||
322 | { | - | ||||||||||||||||||
323 | // calculate the utf8 length and ensure enough space is available | - | ||||||||||||||||||
324 | int utf8len = QChar::isHighSurrogate(decoded) ? 4 : decoded >= 0x800 ? 3 : 2;
| 11-91 | ||||||||||||||||||
325 | - | |||||||||||||||||||
326 | // detach | - | ||||||||||||||||||
327 | if (!output) {
| 15-87 | ||||||||||||||||||
328 | // we need 3 * utf8len for the encoded UTF-8 sequence | - | ||||||||||||||||||
329 | // but ensureDetached already adds 3 for the char we're processing | - | ||||||||||||||||||
330 | ensureDetached(result, output, begin, input, end, 3*utf8len - 3); | - | ||||||||||||||||||
331 | } else { executed 87 times by 4 tests: end of block Executed by:
| 87 | ||||||||||||||||||
332 | // verify that there's enough space or expand | - | ||||||||||||||||||
333 | int charsRemaining = end - input - 1; // not including this one | - | ||||||||||||||||||
334 | int pos = output - reinterpret_cast<const ushort *>(result.constData()); | - | ||||||||||||||||||
335 | int spaceRemaining = result.size() - pos; | - | ||||||||||||||||||
336 | if (spaceRemaining < 3*charsRemaining + 3*utf8len) {
| 5-10 | ||||||||||||||||||
337 | // must resize | - | ||||||||||||||||||
338 | result.resize(result.size() + 3*utf8len); | - | ||||||||||||||||||
339 | - | |||||||||||||||||||
340 | // we know that resize() above detached, so we bypass the reference count check | - | ||||||||||||||||||
341 | output = const_cast<ushort *>(reinterpret_cast<const ushort *>(result.constData())); | - | ||||||||||||||||||
342 | output += pos; | - | ||||||||||||||||||
343 | } executed 10 times by 2 tests: end of block Executed by:
| 10 | ||||||||||||||||||
344 | } executed 15 times by 3 tests: end of block Executed by:
| 15 | ||||||||||||||||||
345 | - | |||||||||||||||||||
346 | ++input; | - | ||||||||||||||||||
347 | int res = QUtf8Functions::toUtf8<QUrlUtf8Traits>(decoded, output, input, end); | - | ||||||||||||||||||
348 | --input; | - | ||||||||||||||||||
349 | if (res < 0) {
| 3-99 | ||||||||||||||||||
350 | // bad surrogate pair sequence | - | ||||||||||||||||||
351 | // we will encode bad UTF-16 to UTF-8 | - | ||||||||||||||||||
352 | // but they don't get decoded back | - | ||||||||||||||||||
353 | - | |||||||||||||||||||
354 | // first of three bytes | - | ||||||||||||||||||
355 | uchar c = 0xe0 | uchar(decoded >> 12); | - | ||||||||||||||||||
356 | *output++ = '%'; | - | ||||||||||||||||||
357 | *output++ = 'E'; | - | ||||||||||||||||||
358 | *output++ = encodeNibble(c & 0xf); | - | ||||||||||||||||||
359 | - | |||||||||||||||||||
360 | // second byte | - | ||||||||||||||||||
361 | c = 0x80 | (uchar(decoded >> 6) & 0x3f); | - | ||||||||||||||||||
362 | *output++ = '%'; | - | ||||||||||||||||||
363 | *output++ = encodeNibble(c >> 4); | - | ||||||||||||||||||
364 | *output++ = encodeNibble(c & 0xf); | - | ||||||||||||||||||
365 | - | |||||||||||||||||||
366 | // third byte | - | ||||||||||||||||||
367 | c = 0x80 | (decoded & 0x3f); | - | ||||||||||||||||||
368 | *output++ = '%'; | - | ||||||||||||||||||
369 | *output++ = encodeNibble(c >> 4); | - | ||||||||||||||||||
370 | *output++ = encodeNibble(c & 0xf); | - | ||||||||||||||||||
371 | } executed 3 times by 1 test: end of block Executed by:
| 3 | ||||||||||||||||||
372 | } executed 102 times by 4 tests: end of block Executed by:
| 102 | ||||||||||||||||||
373 | - | |||||||||||||||||||
374 | static int recode(QString &result, const ushort *begin, const ushort *end, QUrl::ComponentFormattingOptions encoding, | - | ||||||||||||||||||
375 | const uchar *actionTable, bool retryBadEncoding) | - | ||||||||||||||||||
376 | { | - | ||||||||||||||||||
377 | const int origSize = result.size(); | - | ||||||||||||||||||
378 | const ushort *input = begin; | - | ||||||||||||||||||
379 | ushort *output = 0; | - | ||||||||||||||||||
380 | - | |||||||||||||||||||
381 | EncodingAction action = EncodeCharacter; | - | ||||||||||||||||||
382 | for ( ; input != end; ++input) {
| 7992-38619 | ||||||||||||||||||
383 | ushort c; | - | ||||||||||||||||||
384 | // try a run where no change is necessary | - | ||||||||||||||||||
385 | for ( ; input != end; ++input) {
| 33290-783079 | ||||||||||||||||||
386 | c = *input; | - | ||||||||||||||||||
387 | if (c < 0x20U)
| 20-783059 | ||||||||||||||||||
388 | action = EncodeCharacter; executed 20 times by 3 tests: action = EncodeCharacter; Executed by:
| 20 | ||||||||||||||||||
389 | if (c < 0x20U || c >= 0x80U) // also: (c - 0x20 < 0x60U)
| 20-783059 | ||||||||||||||||||
390 | goto non_trivial; executed 334 times by 4 tests: goto non_trivial; Executed by:
| 334 | ||||||||||||||||||
391 | action = EncodingAction(actionTable[c - ' ']); | - | ||||||||||||||||||
392 | if (action == EncodeCharacter)
| 4995-777750 | ||||||||||||||||||
393 | goto non_trivial; executed 4995 times by 11 tests: goto non_trivial; Executed by:
| 4995 | ||||||||||||||||||
394 | if (output)
| 8369-769381 | ||||||||||||||||||
395 | *output++ = c; executed 8369 times by 7 tests: *output++ = c; Executed by:
| 8369 | ||||||||||||||||||
396 | } executed 777750 times by 51 tests: end of block Executed by:
| 777750 | ||||||||||||||||||
397 | break; executed 33290 times by 51 tests: break; Executed by:
| 33290 | ||||||||||||||||||
398 | - | |||||||||||||||||||
399 | non_trivial: | - | ||||||||||||||||||
400 | uint decoded; | - | ||||||||||||||||||
401 | if (c == '%' && retryBadEncoding) {
| 103-3021 | ||||||||||||||||||
402 | // always write "%25" | - | ||||||||||||||||||
403 | ensureDetached(result, output, begin, input, end); | - | ||||||||||||||||||
404 | *output++ = '%'; | - | ||||||||||||||||||
405 | *output++ = '2'; | - | ||||||||||||||||||
406 | *output++ = '5'; | - | ||||||||||||||||||
407 | continue; executed 103 times by 4 tests: continue; Executed by:
| 103 | ||||||||||||||||||
408 | } else if (c == '%') {
| 2308-2918 | ||||||||||||||||||
409 | // check if the input is valid | - | ||||||||||||||||||
410 | if (input + 2 >= end || (decoded = decodePercentEncoding(input)) == ushort(-1)) {
| 30-2881 | ||||||||||||||||||
411 | // not valid, retry | - | ||||||||||||||||||
412 | result.resize(origSize); | - | ||||||||||||||||||
413 | return recode(result, begin, end, encoding, actionTable, true); executed 67 times by 4 tests: return recode(result, begin, end, encoding, actionTable, true); Executed by:
| 67 | ||||||||||||||||||
414 | } | - | ||||||||||||||||||
415 | - | |||||||||||||||||||
416 | if (decoded >= 0x80) {
| 1170-1681 | ||||||||||||||||||
417 | // decode the UTF-8 sequence | - | ||||||||||||||||||
418 | if (!(encoding & QUrl::EncodeUnicode) &&
| 491-679 | ||||||||||||||||||
419 | encodedUtf8ToUtf16(result, output, begin, input, end, decoded))
| 96-395 | ||||||||||||||||||
420 | continue; executed 96 times by 4 tests: continue; Executed by:
| 96 | ||||||||||||||||||
421 | - | |||||||||||||||||||
422 | // decoding the encoded UTF-8 failed | - | ||||||||||||||||||
423 | action = LeaveCharacter; | - | ||||||||||||||||||
424 | } else if (decoded >= 0x20) { executed 1074 times by 3 tests: end of block Executed by:
| 335-1346 | ||||||||||||||||||
425 | action = EncodingAction(actionTable[decoded - ' ']); | - | ||||||||||||||||||
426 | } executed 1346 times by 9 tests: end of block Executed by:
| 1346 | ||||||||||||||||||
427 | } else { executed 2755 times by 9 tests: end of block Executed by:
| 2755 | ||||||||||||||||||
428 | decoded = c; | - | ||||||||||||||||||
429 | if (decoded >= 0x80 && encoding & QUrl::EncodeUnicode) {
| 314-1994 | ||||||||||||||||||
430 | // encode the UTF-8 sequence | - | ||||||||||||||||||
431 | unicodeToEncodedUtf8(result, output, begin, input, end, decoded); | - | ||||||||||||||||||
432 | continue; executed 102 times by 4 tests: continue; Executed by:
| 102 | ||||||||||||||||||
433 | } else if (decoded >= 0x80) {
| 212-1994 | ||||||||||||||||||
434 | if (output)
| 0-212 | ||||||||||||||||||
435 | *output++ = c; never executed: *output++ = c; | 0 | ||||||||||||||||||
436 | continue; executed 212 times by 3 tests: continue; Executed by:
| 212 | ||||||||||||||||||
437 | } | - | ||||||||||||||||||
438 | } executed 1994 times by 8 tests: end of block Executed by:
| 1994 | ||||||||||||||||||
439 | - | |||||||||||||||||||
440 | // there are six possibilities: | - | ||||||||||||||||||
441 | // current \ action | DecodeCharacter | LeaveCharacter | EncodeCharacter | - | ||||||||||||||||||
442 | // decoded | 1:leave | 2:leave | 3:encode | - | ||||||||||||||||||
443 | // encoded | 4:decode | 5:leave | 6:leave | - | ||||||||||||||||||
444 | // cases 1 and 2 were handled before this section | - | ||||||||||||||||||
445 | - | |||||||||||||||||||
446 | if (c == '%' && action != DecodeCharacter) {
| 378-2755 | ||||||||||||||||||
447 | // cases 5 and 6: it's encoded and we're leaving it as it is | - | ||||||||||||||||||
448 | // except we're pedantic and we'll uppercase the hex | - | ||||||||||||||||||
449 | if (output || !isUpperHex(input[1]) || !isUpperHex(input[2])) {
| 7-2281 | ||||||||||||||||||
450 | ensureDetached(result, output, begin, input, end); | - | ||||||||||||||||||
451 | *output++ = '%'; | - | ||||||||||||||||||
452 | *output++ = toUpperHex(*++input); | - | ||||||||||||||||||
453 | *output++ = toUpperHex(*++input); | - | ||||||||||||||||||
454 | } executed 124 times by 4 tests: end of block Executed by:
| 124 | ||||||||||||||||||
455 | } else if (c == '%' && action == DecodeCharacter) { executed 2377 times by 6 tests: end of block Executed by:
| 0-2377 | ||||||||||||||||||
456 | // case 4: we need to decode | - | ||||||||||||||||||
457 | ensureDetached(result, output, begin, input, end); | - | ||||||||||||||||||
458 | *output++ = decoded; | - | ||||||||||||||||||
459 | input += 2; | - | ||||||||||||||||||
460 | } else { executed 378 times by 7 tests: end of block Executed by:
| 378 | ||||||||||||||||||
461 | // must be case 3: we need to encode | - | ||||||||||||||||||
462 | ensureDetached(result, output, begin, input, end); | - | ||||||||||||||||||
463 | *output++ = '%'; | - | ||||||||||||||||||
464 | *output++ = encodeNibble(c >> 4); | - | ||||||||||||||||||
465 | *output++ = encodeNibble(c & 0xf); | - | ||||||||||||||||||
466 | } executed 1994 times by 8 tests: end of block Executed by:
| 1994 | ||||||||||||||||||
467 | } | - | ||||||||||||||||||
468 | - | |||||||||||||||||||
469 | if (output) {
| 1458-39824 | ||||||||||||||||||
470 | int len = output - reinterpret_cast<const ushort *>(result.constData()); | - | ||||||||||||||||||
471 | result.truncate(len); | - | ||||||||||||||||||
472 | return len - origSize; executed 1458 times by 9 tests: return len - origSize; Executed by:
| 1458 | ||||||||||||||||||
473 | } | - | ||||||||||||||||||
474 | return 0; executed 39824 times by 51 tests: return 0; Executed by:
| 39824 | ||||||||||||||||||
475 | } | - | ||||||||||||||||||
476 | - | |||||||||||||||||||
477 | /*! | - | ||||||||||||||||||
478 | \since 5.0 | - | ||||||||||||||||||
479 | \internal | - | ||||||||||||||||||
480 | - | |||||||||||||||||||
481 | This function decodes a percent-encoded string located from \a begin to \a | - | ||||||||||||||||||
482 | end, by appending each character to \a appendTo. It returns the number of | - | ||||||||||||||||||
483 | characters appended. Each percent-encoded sequence is decoded as follows: | - | ||||||||||||||||||
484 | - | |||||||||||||||||||
485 | \list | - | ||||||||||||||||||
486 | \li from %00 to %7F: the exact decoded value is appended; | - | ||||||||||||||||||
487 | \li from %80 to %FF: QChar::ReplacementCharacter is appended; | - | ||||||||||||||||||
488 | \li bad encoding: original input is copied to the output, undecoded. | - | ||||||||||||||||||
489 | \endlist | - | ||||||||||||||||||
490 | - | |||||||||||||||||||
491 | Given the above, it's important for the input to already have all UTF-8 | - | ||||||||||||||||||
492 | percent sequences decoded by qt_urlRecode (that is, the input should not | - | ||||||||||||||||||
493 | have been processed with QUrl::EncodeUnicode). | - | ||||||||||||||||||
494 | - | |||||||||||||||||||
495 | The input should also be a valid percent-encoded sequence (the output of | - | ||||||||||||||||||
496 | qt_urlRecode is always valid). | - | ||||||||||||||||||
497 | */ | - | ||||||||||||||||||
498 | static int decode(QString &appendTo, const ushort *begin, const ushort *end) | - | ||||||||||||||||||
499 | { | - | ||||||||||||||||||
500 | const int origSize = appendTo.size(); | - | ||||||||||||||||||
501 | const ushort *input = begin; | - | ||||||||||||||||||
502 | ushort *output = 0; | - | ||||||||||||||||||
503 | while (input != end) {
| 16624-625217 | ||||||||||||||||||
504 | if (*input != '%') {
| 107-625110 | ||||||||||||||||||
505 | if (output)
| 142-624968 | ||||||||||||||||||
506 | *output++ = *input; executed 142 times by 2 tests: *output++ = *input; Executed by:
| 142 | ||||||||||||||||||
507 | ++input; | - | ||||||||||||||||||
508 | continue; executed 625110 times by 22 tests: continue; Executed by:
| 625110 | ||||||||||||||||||
509 | } | - | ||||||||||||||||||
510 | - | |||||||||||||||||||
511 | if (Q_UNLIKELY(end - input < 3 || !isHex(input[1]) || !isHex(input[2]))) {
| 23-84 | ||||||||||||||||||
512 | // badly-encoded data | - | ||||||||||||||||||
513 | appendTo.resize(origSize + (end - begin)); | - | ||||||||||||||||||
514 | memcpy(appendTo.begin() + origSize, begin, (end - begin) * sizeof(ushort)); | - | ||||||||||||||||||
515 | return end - begin; executed 23 times by 2 tests: return end - begin; Executed by:
| 23 | ||||||||||||||||||
516 | } | - | ||||||||||||||||||
517 | - | |||||||||||||||||||
518 | if (Q_UNLIKELY(!output)) {
| 39-45 | ||||||||||||||||||
519 | // detach | - | ||||||||||||||||||
520 | appendTo.resize(origSize + (end - begin)); | - | ||||||||||||||||||
521 | output = reinterpret_cast<ushort *>(appendTo.begin()) + origSize; | - | ||||||||||||||||||
522 | memcpy(output, begin, (input - begin) * sizeof(ushort)); | - | ||||||||||||||||||
523 | output += input - begin; | - | ||||||||||||||||||
524 | } executed 45 times by 2 tests: end of block Executed by:
| 45 | ||||||||||||||||||
525 | - | |||||||||||||||||||
526 | ++input; | - | ||||||||||||||||||
527 | *output++ = decodeNibble(input[0]) << 4 | decodeNibble(input[1]); | - | ||||||||||||||||||
528 | if (output[-1] >= 0x80)
| 18-66 | ||||||||||||||||||
529 | output[-1] = QChar::ReplacementCharacter; executed 18 times by 1 test: output[-1] = QChar::ReplacementCharacter; Executed by:
| 18 | ||||||||||||||||||
530 | input += 2; | - | ||||||||||||||||||
531 | } executed 84 times by 2 tests: end of block Executed by:
| 84 | ||||||||||||||||||
532 | - | |||||||||||||||||||
533 | if (output) {
| 34-16590 | ||||||||||||||||||
534 | int len = output - reinterpret_cast<ushort *>(appendTo.begin()); | - | ||||||||||||||||||
535 | appendTo.truncate(len); | - | ||||||||||||||||||
536 | return len - origSize; executed 34 times by 2 tests: return len - origSize; Executed by:
| 34 | ||||||||||||||||||
537 | } | - | ||||||||||||||||||
538 | return 0; executed 16590 times by 25 tests: return 0; Executed by:
| 16590 | ||||||||||||||||||
539 | } | - | ||||||||||||||||||
540 | - | |||||||||||||||||||
541 | template <size_t N> | - | ||||||||||||||||||
542 | static void maskTable(uchar (&table)[N], const uchar (&mask)[N]) | - | ||||||||||||||||||
543 | { | - | ||||||||||||||||||
544 | for (size_t i = 0; i < N; ++i)
| 709-68064 | ||||||||||||||||||
545 | table[i] &= mask[i]; executed 68064 times by 4 tests: table[i] &= mask[i]; Executed by:
| 68064 | ||||||||||||||||||
546 | } executed 709 times by 4 tests: end of block Executed by:
| 709 | ||||||||||||||||||
547 | - | |||||||||||||||||||
548 | /*! | - | ||||||||||||||||||
549 | \internal | - | ||||||||||||||||||
550 | - | |||||||||||||||||||
551 | Recodes the string from \a begin to \a end. If any transformations are | - | ||||||||||||||||||
552 | done, append them to \a appendTo and return the number of characters added. | - | ||||||||||||||||||
553 | If no transformations were required, return 0. | - | ||||||||||||||||||
554 | - | |||||||||||||||||||
555 | The \a encoding option modifies the default behaviour: | - | ||||||||||||||||||
556 | \list | - | ||||||||||||||||||
557 | \li QUrl::DecodeReserved: if set, reserved characters will be decoded; | - | ||||||||||||||||||
558 | if unset, reserved characters will be encoded | - | ||||||||||||||||||
559 | \li QUrl::EncodeSpaces: if set, spaces will be encoded to "%20"; if unset, they will be " " | - | ||||||||||||||||||
560 | \li QUrl::EncodeUnicode: if set, characters above U+0080 will be encoded to their UTF-8 | - | ||||||||||||||||||
561 | percent-encoded form; if unset, they will be decoded to UTF-16 | - | ||||||||||||||||||
562 | \li QUrl::FullyDecoded: if set, this function will decode all percent-encoded sequences, | - | ||||||||||||||||||
563 | including that of the percent character. The resulting string | - | ||||||||||||||||||
564 | will not be percent-encoded anymore. Use with caution! | - | ||||||||||||||||||
565 | In this mode, the behaviour is undefined if the input string | - | ||||||||||||||||||
566 | contains any percent-encoding sequences above %80. | - | ||||||||||||||||||
567 | Also, the function will not correct bad % sequences. | - | ||||||||||||||||||
568 | \endlist | - | ||||||||||||||||||
569 | - | |||||||||||||||||||
570 | Other flags are ignored (including QUrl::EncodeReserved). | - | ||||||||||||||||||
571 | - | |||||||||||||||||||
572 | The \a tableModifications argument can be used to supply extra | - | ||||||||||||||||||
573 | modifications to the tables, to be applied after the flags above are | - | ||||||||||||||||||
574 | handled. It consists of a sequence of 16-bit values, where the low 8 bits | - | ||||||||||||||||||
575 | indicate the character in question and the high 8 bits are either \c | - | ||||||||||||||||||
576 | EncodeCharacter, \c LeaveCharacter or \c DecodeCharacter. | - | ||||||||||||||||||
577 | - | |||||||||||||||||||
578 | This function corrects percent-encoded errors by interpreting every '%' as | - | ||||||||||||||||||
579 | meaning "%25" (all percents in the same content). | - | ||||||||||||||||||
580 | */ | - | ||||||||||||||||||
581 | - | |||||||||||||||||||
582 | Q_AUTOTEST_EXPORT int | - | ||||||||||||||||||
583 | qt_urlRecode(QString &appendTo, const QChar *begin, const QChar *end, | - | ||||||||||||||||||
584 | QUrl::ComponentFormattingOptions encoding, const ushort *tableModifications) | - | ||||||||||||||||||
585 | { | - | ||||||||||||||||||
586 | uchar actionTable[sizeof defaultActionTable]; | - | ||||||||||||||||||
587 | if (encoding == QUrl::FullyDecoded) {
| 16647-41282 | ||||||||||||||||||
588 | return decode(appendTo, reinterpret_cast<const ushort *>(begin), reinterpret_cast<const ushort *>(end)); executed 16647 times by 25 tests: return decode(appendTo, reinterpret_cast<const ushort *>(begin), reinterpret_cast<const ushort *>(end)); Executed by:
| 16647 | ||||||||||||||||||
589 | } | - | ||||||||||||||||||
590 | - | |||||||||||||||||||
591 | memcpy(actionTable, defaultActionTable, sizeof actionTable); | - | ||||||||||||||||||
592 | if (encoding & QUrl::DecodeReserved)
| 709-40573 | ||||||||||||||||||
593 | maskTable(actionTable, reservedMask); executed 709 times by 4 tests: maskTable(actionTable, reservedMask); Executed by:
| 709 | ||||||||||||||||||
594 | if (!(encoding & QUrl::EncodeSpaces))
| 6622-34660 | ||||||||||||||||||
595 | actionTable[0] = DecodeCharacter; // decode executed 34660 times by 51 tests: actionTable[0] = DecodeCharacter; Executed by:
| 34660 | ||||||||||||||||||
596 | - | |||||||||||||||||||
597 | if (tableModifications) {
| 10920-30362 | ||||||||||||||||||
598 | for (const ushort *p = tableModifications; *p; ++p)
| 30362-236719 | ||||||||||||||||||
599 | actionTable[uchar(*p) - ' '] = *p >> 8; executed 236719 times by 37 tests: actionTable[uchar(*p) - ' '] = *p >> 8; Executed by:
| 236719 | ||||||||||||||||||
600 | } executed 30362 times by 37 tests: end of block Executed by:
| 30362 | ||||||||||||||||||
601 | - | |||||||||||||||||||
602 | return recode(appendTo, reinterpret_cast<const ushort *>(begin), reinterpret_cast<const ushort *>(end), executed 41282 times by 51 tests: return recode(appendTo, reinterpret_cast<const ushort *>(begin), reinterpret_cast<const ushort *>(end), encoding, actionTable, false); Executed by:
| 41282 | ||||||||||||||||||
603 | encoding, actionTable, false); executed 41282 times by 51 tests: return recode(appendTo, reinterpret_cast<const ushort *>(begin), reinterpret_cast<const ushort *>(end), encoding, actionTable, false); Executed by:
| 41282 | ||||||||||||||||||
604 | } | - | ||||||||||||||||||
605 | - | |||||||||||||||||||
606 | /*! | - | ||||||||||||||||||
607 | \internal | - | ||||||||||||||||||
608 | \since 5.0 | - | ||||||||||||||||||
609 | - | |||||||||||||||||||
610 | \a ba contains an 8-bit form of the component and it might be | - | ||||||||||||||||||
611 | percent-encoded already. We can't use QString::fromUtf8 because it might | - | ||||||||||||||||||
612 | contain non-UTF8 sequences. We can't use QByteArray::toPercentEncoding | - | ||||||||||||||||||
613 | because it might already contain percent-encoded sequences. We can't use | - | ||||||||||||||||||
614 | qt_urlRecode because it needs UTF-16 input. | - | ||||||||||||||||||
615 | */ | - | ||||||||||||||||||
616 | Q_AUTOTEST_EXPORT | - | ||||||||||||||||||
617 | QString qt_urlRecodeByteArray(const QByteArray &ba) | - | ||||||||||||||||||
618 | { | - | ||||||||||||||||||
619 | if (ba.isNull())
| 3-40 | ||||||||||||||||||
620 | return QString(); executed 3 times by 2 tests: return QString(); Executed by:
| 3 | ||||||||||||||||||
621 | - | |||||||||||||||||||
622 | // scan ba for anything above or equal to 0x80 | - | ||||||||||||||||||
623 | // control points below 0x20 are fine in QString | - | ||||||||||||||||||
624 | const char *in = ba.constData(); | - | ||||||||||||||||||
625 | const char *const end = ba.constEnd(); | - | ||||||||||||||||||
626 | for ( ; in < end; ++in) {
| 35-552 | ||||||||||||||||||
627 | if (*in & 0x80)
| 5-547 | ||||||||||||||||||
628 | break; executed 5 times by 2 tests: break; Executed by:
| 5 | ||||||||||||||||||
629 | } executed 547 times by 2 tests: end of block Executed by:
| 547 | ||||||||||||||||||
630 | - | |||||||||||||||||||
631 | if (in == end) {
| 5-35 | ||||||||||||||||||
632 | // no non-ASCII found, we're safe to convert to QString | - | ||||||||||||||||||
633 | return QString::fromLatin1(ba, ba.size()); executed 35 times by 2 tests: return QString::fromLatin1(ba, ba.size()); Executed by:
| 35 | ||||||||||||||||||
634 | } | - | ||||||||||||||||||
635 | - | |||||||||||||||||||
636 | // we found something that we need to encode | - | ||||||||||||||||||
637 | QByteArray intermediate = ba; | - | ||||||||||||||||||
638 | intermediate.resize(ba.size() * 3 - (in - ba.constData())); | - | ||||||||||||||||||
639 | uchar *out = reinterpret_cast<uchar *>(intermediate.data() + (in - ba.constData())); | - | ||||||||||||||||||
640 | for ( ; in < end; ++in) {
| 5-10 | ||||||||||||||||||
641 | if (*in & 0x80) {
| 0-10 | ||||||||||||||||||
642 | // encode | - | ||||||||||||||||||
643 | *out++ = '%'; | - | ||||||||||||||||||
644 | *out++ = encodeNibble(uchar(*in) >> 4); | - | ||||||||||||||||||
645 | *out++ = encodeNibble(uchar(*in) & 0xf); | - | ||||||||||||||||||
646 | } else { executed 10 times by 2 tests: end of block Executed by:
| 10 | ||||||||||||||||||
647 | // keep | - | ||||||||||||||||||
648 | *out++ = uchar(*in); | - | ||||||||||||||||||
649 | } never executed: end of block | 0 | ||||||||||||||||||
650 | } | - | ||||||||||||||||||
651 | - | |||||||||||||||||||
652 | // now it's safe to call fromLatin1 | - | ||||||||||||||||||
653 | return QString::fromLatin1(intermediate, out - reinterpret_cast<uchar *>(intermediate.data())); executed 5 times by 2 tests: return QString::fromLatin1(intermediate, out - reinterpret_cast<uchar *>(intermediate.data())); Executed by:
| 5 | ||||||||||||||||||
654 | } | - | ||||||||||||||||||
655 | - | |||||||||||||||||||
656 | QT_END_NAMESPACE | - | ||||||||||||||||||
Source code | Switch to Preprocessed file |