Changeset 561 for trunk/src/corelib/io/qurl.cpp
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/corelib/io/qurl.cpp
r172 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information ([email protected]) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation ([email protected]) 5 6 ** 6 7 ** This file is part of the QtCore module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you 37 ** @nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 48 48 \reentrant 49 49 \ingroup io 50 \ingroup misc50 \ingroup 51 51 \ingroup shared 52 \mainclass 52 53 53 54 54 It can parse and construct URLs in both encoded and unencoded … … 173 173 #include "qatomic.h" 174 174 #include "qbytearray.h" 175 176 175 177 #include "qlist.h" 176 178 #ifndef QT_NO_REGEXP … … 2337 2339 }; 2338 2340 2339 static void mapToLowerCase(QString *str )2341 static void mapToLowerCase(QString *str) 2340 2342 { 2341 2343 int N = sizeof(NameprepCaseFolding) / sizeof(NameprepCaseFolding[0]); 2342 2344 2343 2345 QChar *d = 0; 2344 for (int i = 0; i < str->size(); ++i) {2346 for (int i = ; i < str->size(); ++i) { 2345 2347 int uc = str->at(i).unicode(); 2346 2348 if (uc < 0x80) { … … 2389 2391 2390 2392 2391 static void stripProhibitedOutput(QString *str )2392 { 2393 ushort *out = (ushort *)str->data() ;2393 static void stripProhibitedOutput(QString *str) 2394 { 2395 ushort *out = (ushort *)str->data() 2394 2396 const ushort *in = out; 2395 const ushort *end = out+ str->size();2397 const ushort *end = + str->size(); 2396 2398 while (in < end) { 2397 2399 ushort uc = *in; … … 2902 2904 } 2903 2905 2904 2905 Q_AUTOTEST_EXPORT QString qt_nameprep(const QString &source) 2906 { 2907 QString mapped = source; 2908 2909 bool simple = true; 2910 for (int i = 0; i < mapped.size(); ++i) { 2911 ushort uc = mapped.at(i).unicode(); 2906 #ifdef QT_BUILD_INTERNAL 2907 // export for tst_qurl.cpp 2908 Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from); 2909 Q_AUTOTEST_EXPORT bool qt_check_std3rules(const QChar *uc, int len); 2910 #else 2911 // non-test build, keep the symbols for ourselves 2912 static void qt_nameprep(QString *source, int from); 2913 static bool qt_check_std3rules(const QChar *uc, int len); 2914 #endif 2915 2916 void qt_nameprep(QString *source, int from) 2917 { 2918 QChar *src = source->data(); // causes a detach, so we're sure the only one using it 2919 QChar *out = src + from; 2920 const QChar *e = src + source->size(); 2921 2922 for ( ; out < e; ++out) { 2923 register ushort uc = out->unicode(); 2912 2924 if (uc > 0x80) { 2913 simple = false;2914 2925 break; 2915 2926 } else if (uc >= 'A' && uc <= 'Z') { 2916 mapped[i]= QChar(uc | 0x20);2927 = QChar(uc | 0x20); 2917 2928 } 2918 2929 } 2919 if (simple) 2920 return mapped; 2921 2930 if (out == e) 2931 return; // everything was mapped easily (lowercased, actually) 2932 int firstNonAscii = out - src; 2933 2922 2934 // Characters commonly mapped to nothing are simply removed 2923 2935 // (Table B.1) 2924 QChar *out = mapped.data();2925 2936 const QChar *in = out; 2926 const QChar *e = in + mapped.size();2927 2937 while (in < e) { 2928 2938 if (!isMappedToNothing(*in)) … … 2931 2941 } 2932 2942 if (out != in) 2933 mapped.truncate(out - mapped.constData());2943 ); 2934 2944 2935 2945 // Map to lowercase (Table B.2) 2936 mapToLowerCase( &mapped);2946 mapToLowerCase(); 2937 2947 2938 2948 // Normalize to Unicode 3.2 form KC 2939 mapped = mapped.normalized(QString::NormalizationForm_KC, QChar::Unicode_3_2); 2949 extern void qt_string_normalize(QString *data, QString::NormalizationForm mode, 2950 QChar::UnicodeVersion version, int from); 2951 qt_string_normalize(source, QString::NormalizationForm_KC, QChar::Unicode_3_2, firstNonAscii); 2940 2952 2941 2953 // Strip prohibited output 2942 stripProhibitedOutput( &mapped);2954 stripProhibitedOutput(); 2943 2955 2944 2956 // Check for valid bidirectional characters 2945 2957 bool containsLCat = false; 2946 2958 bool containsRandALCat = false; 2947 for (int j = 0; j < mapped.size() && (!containsLCat || !containsRandALCat); ++j) { 2948 if (isBidirectionalL(mapped.at(j))) 2959 src = source->data(); 2960 e = src + source->size(); 2961 for (in = src + from; in < e && (!containsLCat || !containsRandALCat); ++in) { 2962 if (isBidirectionalL(*in)) 2949 2963 containsLCat = true; 2950 else if (isBidirectionalRorAL( mapped.at(j)))2964 else if (isBidirectionalRorAL()) 2951 2965 containsRandALCat = true; 2952 2966 } 2953 2967 if (containsRandALCat) { 2954 if (containsLCat || (!isBidirectionalRorAL(mapped.at(0)) 2955 || !isBidirectionalRorAL(mapped.at(mapped.size() - 1)))) 2956 mapped.clear(); 2957 } 2958 2959 return mapped; 2960 } 2961 2962 2963 static inline char encodeDigit(uint digit) 2968 if (containsLCat || (!isBidirectionalRorAL(src[from]) 2969 || !isBidirectionalRorAL(e[-1]))) 2970 source->resize(from); // not allowed, clear the label 2971 } 2972 } 2973 2974 bool qt_check_std3rules(const QChar *uc, int len) 2975 { 2976 if (len > 63) 2977 return false; 2978 2979 for (int i = 0; i < len; ++i) { 2980 register ushort c = uc[i].unicode(); 2981 if (c == '-' && (i == 0 || i == len - 1)) 2982 return false; 2983 2984 // verifying the absence of LDH is the same as verifying that 2985 // only LDH is present 2986 if (c == '-' || (c >= '0' && c <= '9') 2987 || (c >= 'A' && c <= 'Z') 2988 || (c >= 'a' && c <= 'z')) 2989 continue; 2990 2991 return false; 2992 } 2993 2994 return true; 2995 } 2996 2997 2998 static inline uint encodeDigit(uint digit) 2964 2999 { 2965 3000 return digit + 22 + 75 * (digit < 26); … … 2978 3013 } 2979 3014 2980 static inline void appendEncode(Q ByteArray* output, uint& delta, uint& bias, uint& b, uint& h)3015 static inline void appendEncode(Q* output, uint& delta, uint& bias, uint& b, uint& h) 2981 3016 { 2982 3017 uint qq; … … 2992 3027 if (qq < t) break; 2993 3028 2994 *output += encodeDigit(t + (qq - t) % (base - t));3029 *output += )); 2995 3030 qq = (qq - t) / (base - t); 2996 3031 } 2997 3032 2998 *output += encodeDigit(qq);3033 *output += ); 2999 3034 bias = adapt(delta, h + 1, h == b); 3000 3035 delta = 0; … … 3002 3037 } 3003 3038 3004 static void toPunycodeHelper(const QChar *s, int ucLength, Q ByteArray*output)3039 static void toPunycodeHelper(const QChar *s, int ucLength, Q *output) 3005 3040 { 3006 3041 uint n = initial_n; … … 3011 3046 output->resize(outLen + ucLength); 3012 3047 3013 char *d = output->data() + outLen;3048 har *d = output->data() + outLen; 3014 3049 bool skipped = false; 3015 3050 // copy all basic code points verbatim to output. … … 3036 3071 // if basic code points were copied, add the delimiter character. 3037 3072 if (h > 0) 3038 *output += 0x2d;3073 *output += ; 3039 3074 3040 3075 // while there are still unprocessed non-basic code points left in … … 3084 3119 3085 3120 // prepend ACE prefix 3086 output->insert(outLen, "xn--");3121 output->insert(outLen, ); 3087 3122 return; 3088 3123 } … … 3145 3180 if (idx == -1) 3146 3181 return false; 3147 const QChar *tld = domain.constData() + idx + 1; 3182 3148 3183 int len = domain.size() - idx - 1; 3184 3185 3186 3187 3149 3188 3150 3189 if (user_idn_whitelist) 3151 return user_idn_whitelist->contains( QString(tld, len));3190 return user_idn_whitelist->contains(); 3152 3191 3153 3192 int l = 0; … … 3165 3204 } 3166 3205 3167 static QString qt_from_ACE(const QString &domainMC) 3168 { 3169 QString domain = domainMC.toLower(); 3170 int idx = domain.indexOf(QLatin1Char('.')); 3171 if (idx != -1) { 3172 if (!domain.contains(QLatin1String("xn--"))) { 3173 bool simple = true; 3174 for (int i = 0; i < domain.size(); ++i) { 3175 ushort ch = domain.at(i).unicode(); 3176 if (ch > 'z' || ch < '-' || ch == '/' || (ch > '9' && ch < 'A') || (ch > 'Z' && ch < 'a')) { 3206 static inline bool isDotDelimiter(ushort uc) 3207 { 3208 // IDNA / rfc3490 describes these four delimiters used for 3209 // separating labels in unicode international domain 3210 // names. 3211 return uc == 0x2e || uc == 0x3002 || uc == 0xff0e || uc == 0xff61; 3212 } 3213 3214 static int nextDotDelimiter(const QString &domain, int from = 0) 3215 { 3216 const QChar *b = domain.unicode(); 3217 const QChar *ch = b + from; 3218 const QChar *e = b + domain.length(); 3219 while (ch < e) { 3220 if (isDotDelimiter(ch->unicode())) 3221 break; 3222 else 3223 ++ch; 3224 } 3225 return ch - b; 3226 } 3227 3228 enum AceOperation { ToAceOnly, NormalizeAce }; 3229 static QString qt_ACE_do(const QString &domain, AceOperation op) 3230 { 3231 if (domain.isEmpty()) 3232 return domain; 3233 3234 QString result; 3235 result.reserve(domain.length()); 3236 3237 const bool isIdnEnabled = op == NormalizeAce ? qt_is_idn_enabled(domain) : false; 3238 int lastIdx = 0; 3239 QString aceForm; // this variable is here for caching 3240 3241 while (1) { 3242 int idx = nextDotDelimiter(domain, lastIdx); 3243 int labelLength = idx - lastIdx; 3244 if (labelLength == 0) 3245 return QString(); // two delimiters in a row -- empty label not allowed 3246 3247 // RFC 3490 says, about the ToASCII operation: 3248 // 3. If the UseSTD3ASCIIRules flag is set, then perform these checks: 3249 // 3250 // (a) Verify the absence of non-LDH ASCII code points; that is, the 3251 // absence of 0..2C, 2E..2F, 3A..40, 5B..60, and 7B..7F. 3252 // 3253 // (b) Verify the absence of leading and trailing hyphen-minus; that 3254 // is, the absence of U+002D at the beginning and end of the 3255 // sequence. 3256 // and: 3257 // 8. Verify that the number of code points is in the range 1 to 63 3258 // inclusive. 3259 3260 // copy the label to the destination, which also serves as our scratch area, lowercasing it 3261 int prevLen = result.size(); 3262 bool simple = true; 3263 result.resize(prevLen + labelLength); 3264 { 3265 QChar *out = result.data() + prevLen; 3266 const QChar *in = domain.constData() + lastIdx; 3267 const QChar *e = in + labelLength; 3268 for (; in < e; ++in, ++out) { 3269 register ushort uc = in->unicode(); 3270 if (uc > 0x7f) 3177 3271 simple = false; 3178 break; 3179 } 3272 if (uc >= 'A' && uc <= 'Z') 3273 *out = QChar(uc | 0x20); 3274 else 3275 *out = *in; 3180 3276 } 3181 if (simple)3182 return domain;3183 3277 } 3184 3185 const bool isIdnEnabled = qt_is_idn_enabled(domain); 3186 int lastIdx = 0; 3187 QString result; 3188 while (1) { 3189 // Nameprep the host. If the labels in the hostname are Punycode 3190 // encoded, we decode them immediately, then nameprep them. 3191 QByteArray label; 3192 toPunycodeHelper(domain.constData() + lastIdx, idx - lastIdx, &label); 3193 result += qt_nameprep(isIdnEnabled ? QUrl::fromPunycode(label) : QString::fromLatin1(label)); 3194 lastIdx = idx + 1; 3195 if (lastIdx < domain.size() + 1) 3196 result += QLatin1Char('.'); 3197 else 3198 break; 3199 idx = domain.indexOf(QLatin1Char('.'), lastIdx); 3200 if (idx == -1) 3201 idx = domain.size(); 3278 3279 if (simple && labelLength > 6) { 3280 // ACE form domains contain only ASCII characters, but we can't consider them simple 3281 // is this an ACE form? 3282 // the shortest valid ACE domain is 6 characters long (U+0080 would be 1, but it's not allowed) 3283 static const ushort acePrefixUtf16[] = { 'x', 'n', '-', '-' }; 3284 if (memcmp(result.constData() + prevLen, acePrefixUtf16, sizeof acePrefixUtf16) == 0) 3285 simple = false; 3202 3286 } 3203 return result; 3204 } else { 3205 return qt_nameprep(domain); 3206 } 3287 3288 if (simple) { 3289 // fastest case: this is the common case (non IDN-domains) 3290 // so we're done 3291 if (!qt_check_std3rules(result.constData() + prevLen, labelLength)) 3292 return QString(); 3293 } else { 3294 // Punycode encoding and decoding cannot be done in-place 3295 // That means we need one or two temporaries 3296 qt_nameprep(&result, prevLen); 3297 labelLength = result.length() - prevLen; 3298 register int toReserve = labelLength + 4 + 6; // "xn--" plus some extra bytes 3299 if (toReserve > aceForm.capacity()) 3300 aceForm.reserve(toReserve); 3301 toPunycodeHelper(result.constData() + prevLen, result.size() - prevLen, &aceForm); 3302 3303 // We use resize()+memcpy() here because we're overwriting the data we've copied 3304 if (isIdnEnabled) { 3305 QString tmp = QUrl::fromPunycode(aceForm.toLatin1()); 3306 if (tmp.isEmpty()) 3307 return QString(); // shouldn't happen, since we've just punycode-encoded it 3308 result.resize(prevLen + tmp.size()); 3309 memcpy(result.data() + prevLen, tmp.constData(), tmp.size() * sizeof(QChar)); 3310 } else { 3311 result.resize(prevLen + aceForm.size()); 3312 memcpy(result.data() + prevLen, aceForm.constData(), aceForm.size() * sizeof(QChar)); 3313 } 3314 3315 if (!qt_check_std3rules(aceForm.constData(), aceForm.size())) 3316 return QString(); 3317 } 3318 3319 3320 lastIdx = idx + 1; 3321 if (lastIdx < domain.size() + 1) 3322 result += QLatin1Char('.'); 3323 else 3324 break; 3325 } 3326 return result; 3207 3327 } 3208 3328 … … 3247 3367 QString QUrlPrivate::canonicalHost() const 3248 3368 { 3249 if (QURL_HASFLAG(stateFlags, HostCanonicalized) )3369 if (QURL_HASFLAG(stateFlags, HostCanonicalized)) 3250 3370 return host; 3251 3371 3252 3372 QUrlPrivate *that = const_cast<QUrlPrivate *>(this); 3253 3373 QURL_SETFLAG(that->stateFlags, HostCanonicalized); 3254 that->host = qt_from_ACE(host); 3374 if (host.contains(QLatin1Char(':'))) { 3375 // This is an IP Literal, use _IPLiteral to validate 3376 QByteArray ba = host.toLatin1(); 3377 if (!ba.startsWith('[')) { 3378 // surround the IP Literal with [ ] if it's not already done so 3379 ba.reserve(ba.length() + 2); 3380 ba.prepend('['); 3381 ba.append(']'); 3382 } 3383 3384 const char *ptr = ba.constData(); 3385 if (!_IPLiteral(&ptr)) 3386 that->host.clear(); 3387 else 3388 that->host = host.toLower(); 3389 } else { 3390 that->host = qt_ACE_do(host, NormalizeAce); 3391 } 3255 3392 return that->host; 3256 3393 } … … 3728 3865 3729 3866 if ((options & QUrl::RemoveUserInfo) != QUrl::RemoveUserInfo) { 3867 3730 3868 if (!userName.isEmpty()) { 3731 3869 url += encodedUserName; 3732 if (!(options & QUrl::RemovePassword) && !password.isEmpty()) { 3733 url += ':'; 3734 url += encodedPassword; 3735 } 3870 hasUserOrPass = true; 3871 } 3872 if (!(options & QUrl::RemovePassword) && !password.isEmpty()) { 3873 url += ':'; 3874 url += encodedPassword; 3875 hasUserOrPass = true; 3876 } 3877 if (hasUserOrPass) 3736 3878 url += '@'; 3737 }3738 3879 } 3739 3880 3740 url += QUrl::toAce(host); 3881 if (host.startsWith(QLatin1Char('['))) { 3882 url += host.toLatin1(); 3883 } else if (host.contains(QLatin1Char(':'))) { 3884 url += '['; 3885 url += host.toLatin1(); 3886 url += ']'; 3887 } else { 3888 url += QUrl::toAce(host); 3889 } 3741 3890 if (!(options & QUrl::RemovePort) && port != -1) { 3742 3891 url += ':'; … … 3889 4038 3890 4039 /*! 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 3891 4063 Constructs a URL by parsing \a url. \a url is assumed to be in human 3892 4064 readable representation, with no percent encoding. QUrl will automatically … … 3903 4075 \sa setUrl(), setEncodedUrl(), fromEncoded(), TolerantMode 3904 4076 */ 3905 QUrl::QUrl(const QString &url) : d( new QUrlPrivate)4077 QUrl::QUrl(const QString &url) : d() 3906 4078 { 3907 4079 if (!url.isEmpty()) … … 3916 4088 \sa setUrl() 3917 4089 */ 3918 QUrl::QUrl(const QString &url, ParsingMode parsingMode) : d( new QUrlPrivate)4090 QUrl::QUrl(const QString &url, ParsingMode parsingMode) : d() 3919 4091 { 3920 4092 if (!url.isEmpty()) 3921 4093 setUrl(url, parsingMode); 3922 else 4094 else { 4095 d = new QUrlPrivate; 3923 4096 d->parsingMode = parsingMode; 4097 3924 4098 } 3925 4099 … … 3927 4101 Constructs an empty QUrl object. 3928 4102 */ 3929 QUrl::QUrl() : d( new QUrlPrivate)4103 QUrl::QUrl() : d() 3930 4104 { 3931 4105 } … … 3936 4110 QUrl::QUrl(const QUrl &other) : d(other.d) 3937 4111 { 3938 d->ref.ref(); 4112 if (d) 4113 d->ref.ref(); 3939 4114 } 3940 4115 … … 3944 4119 QUrl::~QUrl() 3945 4120 { 3946 if ( !d->ref.deref())4121 if (!d->ref.deref()) 3947 4122 delete d; 3948 4123 } … … 3959 4134 bool QUrl::isValid() const 3960 4135 { 4136 4137 3961 4138 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 3962 4139 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Validated)) d->validate(); … … 3970 4147 bool QUrl::isEmpty() const 3971 4148 { 4149 4150 3972 4151 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) 3973 4152 return d->encodedOriginal.isEmpty(); … … 3990 4169 void QUrl::clear() 3991 4170 { 3992 detach(); 3993 d->clear(); 4171 if (d && !d->ref.deref()) 4172 delete d; 4173 d = 0; 3994 4174 } 3995 4175 … … 4090 4270 void QUrl::setEncodedUrl(const QByteArray &encodedUrl, ParsingMode parsingMode) 4091 4271 { 4092 clear();4093 4272 QByteArray tmp = encodedUrl; 4273 4274 4094 4275 if ((d->parsingMode = parsingMode) == TolerantMode) { 4095 4276 // Replace stray % with %25 … … 4165 4346 void QUrl::setScheme(const QString &scheme) 4166 4347 { 4348 4167 4349 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4168 4350 detach(); … … 4180 4362 QString QUrl::scheme() const 4181 4363 { 4364 4182 4365 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4183 4366 … … 4203 4386 void QUrl::setAuthority(const QString &authority) 4204 4387 { 4388 4389 4205 4390 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4206 4391 detach(); … … 4218 4403 QString QUrl::authority() const 4219 4404 { 4405 4406 4220 4407 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4221 4408 … … 4238 4425 void QUrl::setUserInfo(const QString &userInfo) 4239 4426 { 4427 4428 4240 4429 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4241 4430 detach(); … … 4251 4440 QString QUrl::userInfo() const 4252 4441 { 4442 4443 4253 4444 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4254 4445 … … 4265 4456 void QUrl::setUserName(const QString &userName) 4266 4457 { 4458 4459 4267 4460 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4268 4461 detach(); … … 4281 4474 QString QUrl::userName() const 4282 4475 { 4476 4477 4283 4478 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4284 4479 … … 4302 4497 void QUrl::setEncodedUserName(const QByteArray &userName) 4303 4498 { 4499 4304 4500 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4305 4501 detach(); … … 4322 4518 QByteArray QUrl::encodedUserName() const 4323 4519 { 4520 4324 4521 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4325 4522 … … 4337 4534 void QUrl::setPassword(const QString &password) 4338 4535 { 4536 4339 4537 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4340 4538 detach(); … … 4353 4551 QString QUrl::password() const 4354 4552 { 4553 4355 4554 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4356 4555 … … 4374 4573 void QUrl::setEncodedPassword(const QByteArray &password) 4375 4574 { 4575 4376 4576 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4377 4577 detach(); … … 4394 4594 QByteArray QUrl::encodedPassword() const 4395 4595 { 4596 4396 4597 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4397 4598 … … 4408 4609 void QUrl::setHost(const QString &host) 4409 4610 { 4611 4410 4612 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4411 4613 detach(); … … 4413 4615 4414 4616 d->host = host; 4415 if (d->host.contains(QLatin1Char(':')))4416 d->host = QLatin1Char('[') + d->host + QLatin1Char(']');4417 4617 } 4418 4618 … … 4423 4623 QString QUrl::host() const 4424 4624 { 4625 4425 4626 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4426 4627 … … 4476 4677 void QUrl::setPort(int port) 4477 4678 { 4679 4478 4680 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4479 4681 detach(); … … 4493 4695 int QUrl::port() const 4494 4696 { 4697 4495 4698 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4496 4699 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Validated)) d->validate(); … … 4511 4714 int QUrl::port(int defaultPort) const 4512 4715 { 4716 4513 4717 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4514 4718 return d->port == -1 ? defaultPort : d->port; … … 4530 4734 void QUrl::setPath(const QString &path) 4531 4735 { 4736 4532 4737 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4533 4738 detach(); … … 4545 4750 QString QUrl::path() const 4546 4751 { 4752 4547 4753 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4548 4754 … … 4576 4782 void QUrl::setEncodedPath(const QByteArray &path) 4577 4783 { 4784 4578 4785 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4579 4786 detach(); … … 4596 4803 QByteArray QUrl::encodedPath() const 4597 4804 { 4805 4598 4806 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4599 4807 … … 4611 4819 bool QUrl::hasQuery() const 4612 4820 { 4821 4613 4822 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4614 4823 … … 4640 4849 void QUrl::setQueryDelimiters(char valueDelimiter, char pairDelimiter) 4641 4850 { 4851 4642 4852 detach(); 4643 4853 … … 4652 4862 char QUrl::queryPairDelimiter() const 4653 4863 { 4864 4654 4865 return d->pairDelimiter; 4655 4866 } … … 4661 4872 char QUrl::queryValueDelimiter() const 4662 4873 { 4874 4663 4875 return d->valueDelimiter; 4664 4876 } … … 4683 4895 void QUrl::setEncodedQuery(const QByteArray &query) 4684 4896 { 4897 4685 4898 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4686 4899 detach(); … … 4702 4915 void QUrl::setQueryItems(const QList<QPair<QString, QString> > &query) 4703 4916 { 4917 4704 4918 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4705 4919 detach(); … … 4741 4955 void QUrl::setEncodedQueryItems(const QList<QPair<QByteArray, QByteArray> > &query) 4742 4956 { 4957 4743 4958 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4744 4959 detach(); … … 4760 4975 URL. 4761 4976 4977 4978 4979 4980 4981 4982 4762 4983 \sa addEncodedQueryItem() 4763 4984 */ 4764 4985 void QUrl::addQueryItem(const QString &key, const QString &value) 4765 4986 { 4987 4766 4988 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4767 4989 detach(); … … 4798 5020 void QUrl::addEncodedQueryItem(const QByteArray &key, const QByteArray &value) 4799 5021 { 5022 4800 5023 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4801 5024 detach(); … … 4818 5041 QList<QPair<QString, QString> > QUrl::queryItems() const 4819 5042 { 5043 4820 5044 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4821 5045 … … 4850 5074 QList<QPair<QByteArray, QByteArray> > QUrl::encodedQueryItems() const 4851 5075 { 5076 4852 5077 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4853 5078 … … 4878 5103 bool QUrl::hasQueryItem(const QString &key) const 4879 5104 { 5105 4880 5106 return hasEncodedQueryItem(toPercentEncoding(key, queryExcludeChars)); 4881 5107 } … … 4896 5122 bool QUrl::hasEncodedQueryItem(const QByteArray &key) const 4897 5123 { 5124 4898 5125 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4899 5126 … … 4918 5145 QString QUrl::queryItemValue(const QString &key) const 4919 5146 { 5147 4920 5148 QByteArray tmp = encodedQueryItemValue(toPercentEncoding(key, queryExcludeChars)); 4921 5149 return fromPercentEncodingMutable(&tmp); … … 4937 5165 QByteArray QUrl::encodedQueryItemValue(const QByteArray &key) const 4938 5166 { 5167 4939 5168 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4940 5169 … … 4960 5189 QStringList QUrl::allQueryItemValues(const QString &key) const 4961 5190 { 5191 4962 5192 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 4963 5193 … … 4997 5227 QList<QByteArray> QUrl::allEncodedQueryItemValues(const QByteArray &key) const 4998 5228 { 5229 4999 5230 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 5000 5231 … … 5024 5255 void QUrl::removeQueryItem(const QString &key) 5025 5256 { 5257 5026 5258 removeEncodedQueryItem(toPercentEncoding(key, queryExcludeChars)); 5027 5259 } … … 5042 5274 void QUrl::removeEncodedQueryItem(const QByteArray &key) 5043 5275 { 5276 5044 5277 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 5045 5278 detach(); … … 5068 5301 void QUrl::removeAllQueryItems(const QString &key) 5069 5302 { 5303 5070 5304 removeAllEncodedQueryItems(toPercentEncoding(key, queryExcludeChars)); 5071 5305 } … … 5086 5320 void QUrl::removeAllEncodedQueryItems(const QByteArray &key) 5087 5321 { 5322 5088 5323 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 5089 5324 detach(); … … 5109 5344 QByteArray QUrl::encodedQuery() const 5110 5345 { 5346 5111 5347 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 5112 5348 … … 5133 5369 void QUrl::setFragment(const QString &fragment) 5134 5370 { 5371 5135 5372 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 5136 5373 detach(); … … 5149 5386 QString QUrl::fragment() const 5150 5387 { 5388 5151 5389 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 5152 5390 … … 5179 5417 void QUrl::setEncodedFragment(const QByteArray &fragment) 5180 5418 { 5419 5181 5420 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 5182 5421 detach(); … … 5200 5439 QByteArray QUrl::encodedFragment() const 5201 5440 { 5441 5202 5442 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 5203 5443 … … 5215 5455 bool QUrl::hasFragment() const 5216 5456 { 5457 5217 5458 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 5218 5459 … … 5241 5482 QUrl QUrl::resolved(const QUrl &relative) const 5242 5483 { 5484 5485 5243 5486 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 5244 5487 … … 5257 5500 t = relative; 5258 5501 } else { 5502 5259 5503 if (relative.d->encodedPath.isEmpty()) { 5260 5504 t.d->encodedPath = d->encodedPath; … … 5287 5531 bool QUrl::isRelative() const 5288 5532 { 5533 5289 5534 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 5290 5535 … … 5301 5546 QString QUrl::toString(FormattingOptions options) const 5302 5547 { 5548 5303 5549 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 5304 5550 … … 5325 5571 url += ourPath; 5326 5572 // check if we need to remove trailing slashes 5327 while ((options & StripTrailingSlash) && url. right(1) == QLatin1String("/"))5573 while ((options & StripTrailingSlash) && url.)) 5328 5574 url.chop(1); 5329 5575 } … … 5352 5598 QByteArray QUrl::toEncoded(FormattingOptions options) const 5353 5599 { 5600 5354 5601 return d->toEncoded(options); 5355 5602 } … … 5420 5667 QByteArray QUrl::toPunycode(const QString &uc) 5421 5668 { 5422 Q ByteArrayoutput;5669 Q output; 5423 5670 toPunycodeHelper(uc.constData(), uc.size(), &output); 5424 return output ;5671 return output; 5425 5672 } 5426 5673 … … 5518 5765 and RFC 3492. It is part of the Internationalizing Domain Names in 5519 5766 Applications (IDNA) specification, which allows for domain names 5520 (like \c " qtsoftware.com") to be written using international5767 (like \c "e.com") to be written using international 5521 5768 characters. 5522 5769 */ 5523 5770 QString QUrl::fromAce(const QByteArray &domain) 5524 5771 { 5525 return qt_ from_ACE(QString::fromLatin1(domain));5772 return qt_); 5526 5773 } 5527 5774 … … 5535 5782 and RFC 3492. It is part of the Internationalizing Domain Names in 5536 5783 Applications (IDNA) specification, which allows for domain names 5537 (like \c " qtsoftware.com") to be written using international5784 (like \c "e.com") to be written using international 5538 5785 characters. 5786 5787 5788 5789 5539 5790 */ 5540 5791 QByteArray QUrl::toAce(const QString &domain) 5541 5792 { 5542 // IDNA / rfc3490 describes these four delimiters used for 5543 // separating labels in unicode international domain 5544 // names. 5545 QString nameprepped = qt_nameprep(domain); 5546 int lastIdx = 0; 5547 QByteArray result; 5548 for (int i = 0; i < nameprepped.size(); ++i) { 5549 ushort uc = nameprepped.at(i).unicode(); 5550 if (uc == 0x2e || uc == 0x3002 || uc == 0xff0e || uc == 0xff61) { 5551 if (lastIdx) 5552 result += '.'; 5553 toPunycodeHelper(nameprepped.constData() + lastIdx, i - lastIdx, &result); 5554 lastIdx = i + 1; 5555 } 5556 } 5557 if (lastIdx) 5558 result += '.'; 5559 toPunycodeHelper(nameprepped.constData() + lastIdx, nameprepped.size() - lastIdx, &result); 5560 5561 return result; 5793 QString result = qt_ACE_do(domain, ToAceOnly); 5794 return result.toLatin1(); 5562 5795 } 5563 5796 … … 5616 5849 bool QUrl::operator <(const QUrl &url) const 5617 5850 { 5851 5618 5852 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 5853 5619 5854 if (!QURL_HASFLAG(url.d->stateFlags, QUrlPrivate::Parsed)) url.d->parse(); 5620 5855 return d->normalized() < url.d->normalized(); … … 5627 5862 bool QUrl::operator ==(const QUrl &url) const 5628 5863 { 5864 5865 5629 5866 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 5630 5867 if (!QURL_HASFLAG(url.d->stateFlags, QUrlPrivate::Parsed)) url.d->parse(); … … 5646 5883 QUrl &QUrl::operator =(const QUrl &url) 5647 5884 { 5648 qAtomicAssign(d, url.d); 5885 if (!d) { 5886 if (url.d) { 5887 url.d->ref.ref(); 5888 d = url.d; 5889 } 5890 } else { 5891 if (url.d) 5892 qAtomicAssign(d, url.d); 5893 else 5894 clear(); 5895 } 5649 5896 return *this; 5650 5897 } … … 5655 5902 QUrl &QUrl::operator =(const QString &url) 5656 5903 { 5657 QUrl tmp(url); 5658 qAtomicAssign(d, tmp.d); 5904 if (url.isEmpty()) { 5905 clear(); 5906 } else { 5907 QUrl tmp(url); 5908 if (!d) d = new QUrlPrivate; 5909 qAtomicAssign(d, tmp.d); 5910 } 5659 5911 return *this; 5660 5912 } … … 5665 5917 */ 5666 5918 void QUrl::detach() 5667 { qAtomicDetach(d); } 5919 { 5920 if (!d) 5921 d = new QUrlPrivate; 5922 else 5923 qAtomicDetach(d); 5924 } 5668 5925 5669 5926 /*! … … 5672 5929 bool QUrl::isDetached() const 5673 5930 { 5674 return d->ref == 1;5931 return d->ref == 1; 5675 5932 } 5676 5933 … … 5693 5950 // magic for drives on windows 5694 5951 if (deslashified.length() > 1 && deslashified.at(1) == QLatin1Char(':') && deslashified.at(0) != QLatin1Char('/')) { 5695 url.setPath(QLatin1 String("/") + deslashified);5952 url.setPath(QLatin1) + deslashified); 5696 5953 // magic for shared drive on windows 5697 5954 } else if (deslashified.startsWith(QLatin1String("//"))) { … … 5714 5971 QString QUrl::toLocalFile() const 5715 5972 { 5973 5716 5974 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 5717 5975 5718 5976 QString tmp; 5719 5977 QString ourPath = path(); 5720 if (d->scheme.isEmpty() || d->scheme.toLower() == QLatin1String("file")) {5978 if (d->scheme.isEmpty() || ) { 5721 5979 5722 5980 // magic for shared drive on windows 5723 5981 if (!d->host.isEmpty()) { 5724 5982 tmp = QLatin1String("//") + d->host + (ourPath.length() > 0 && ourPath.at(0) != QLatin1Char('/') 5725 ? QLatin1 String("/") + ourPath : ourPath);5983 ? QLatin1) + ourPath : ourPath); 5726 5984 } else { 5727 5985 tmp = ourPath; … … 5742 6000 bool QUrl::isParentOf(const QUrl &childUrl) const 5743 6001 { 6002 6003 6004 6005 6006 6007 6008 5744 6009 if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); 5745 6010 5746 QString childPath = childUrl.path();5747 6011 QString ourPath = path(); 5748 6012 … … 5845 6109 5846 6110 \oldcode 5847 QUrl url("http:// qtsoftware.com/Developer/");6111 QUrl url("http://e.com/Developer/"); 5848 6112 url.cdUp(); 5849 6113 \newcode 5850 QUrl url("http:// qtsoftware.com/Developer/");6114 QUrl url("http://e.com/Developer/"); 5851 6115 url = url.resolved(".."); 5852 6116 \endcode … … 5971 6235 QDebug operator<<(QDebug d, const QUrl &url) 5972 6236 { 5973 d.maybeSpace() << "QUrl(" << url.toString() << ")";6237 d.maybeSpace() << "QUrl(" << url.toString() << ; 5974 6238 return d.space(); 5975 6239 } … … 5984 6248 QString QUrl::errorString() const 5985 6249 { 6250 6251 5986 6252 return d->createErrorString(); 5987 6253 } … … 5997 6263 */ 5998 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 5999 6369 QT_END_NAMESPACE
Note:
See TracChangeset
for help on using the changeset viewer.