| 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 blockExecuted by:
| 1460 | ||||||||||||||||||
| 232 | } executed 2782 times by 9 tests: end of blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted by:
| 10 | ||||||||||||||||||
| 344 | } executed 15 times by 3 tests: end of blockExecuted 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 blockExecuted by:
| 3 | ||||||||||||||||||
| 372 | } executed 102 times by 4 tests: end of blockExecuted 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 blockExecuted 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 blockExecuted by:
| 335-1346 | ||||||||||||||||||
| 425 | action = EncodingAction(actionTable[decoded - ' ']); | - | ||||||||||||||||||
| 426 | } executed 1346 times by 9 tests: end of blockExecuted by:
| 1346 | ||||||||||||||||||
| 427 | } else { executed 2755 times by 9 tests: end of blockExecuted 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 blockExecuted 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 blockExecuted by:
| 124 | ||||||||||||||||||
| 455 | } else if (c == '%' && action == DecodeCharacter) { executed 2377 times by 6 tests: end of blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 |