1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/base/src/nsStandardURL.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,378 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef nsStandardURL_h__ 1.10 +#define nsStandardURL_h__ 1.11 + 1.12 +#include "nsString.h" 1.13 +#include "nsISerializable.h" 1.14 +#include "nsIFileURL.h" 1.15 +#include "nsIStandardURL.h" 1.16 +#include "nsIUnicodeEncoder.h" 1.17 +#include "nsIObserver.h" 1.18 +#include "nsCOMPtr.h" 1.19 +#include "nsURLHelper.h" 1.20 +#include "nsIClassInfo.h" 1.21 +#include "nsISizeOf.h" 1.22 +#include "prclist.h" 1.23 +#include "mozilla/Attributes.h" 1.24 +#include "mozilla/MemoryReporting.h" 1.25 +#include "nsIIPCSerializableURI.h" 1.26 + 1.27 +#ifdef NS_BUILD_REFCNT_LOGGING 1.28 +#define DEBUG_DUMP_URLS_AT_SHUTDOWN 1.29 +#endif 1.30 + 1.31 +class nsIBinaryInputStream; 1.32 +class nsIBinaryOutputStream; 1.33 +class nsIIDNService; 1.34 +class nsICharsetConverterManager; 1.35 +class nsIPrefBranch; 1.36 +class nsIFile; 1.37 +class nsIURLParser; 1.38 + 1.39 +//----------------------------------------------------------------------------- 1.40 +// standard URL implementation 1.41 +//----------------------------------------------------------------------------- 1.42 + 1.43 +class nsStandardURL : public nsIFileURL 1.44 + , public nsIStandardURL 1.45 + , public nsISerializable 1.46 + , public nsIClassInfo 1.47 + , public nsISizeOf 1.48 + , public nsIIPCSerializableURI 1.49 +{ 1.50 +public: 1.51 + NS_DECL_ISUPPORTS 1.52 + NS_DECL_NSIURI 1.53 + NS_DECL_NSIURL 1.54 + NS_DECL_NSIFILEURL 1.55 + NS_DECL_NSISTANDARDURL 1.56 + NS_DECL_NSISERIALIZABLE 1.57 + NS_DECL_NSICLASSINFO 1.58 + NS_DECL_NSIMUTABLE 1.59 + NS_DECL_NSIIPCSERIALIZABLEURI 1.60 + 1.61 + // nsISizeOf 1.62 + virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 1.63 + virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 1.64 + 1.65 + nsStandardURL(bool aSupportsFileURL = false); 1.66 + virtual ~nsStandardURL(); 1.67 + 1.68 + static void InitGlobalObjects(); 1.69 + static void ShutdownGlobalObjects(); 1.70 + 1.71 +public: /* internal -- HPUX compiler can't handle this being private */ 1.72 + // 1.73 + // location and length of an url segment relative to mSpec 1.74 + // 1.75 + struct URLSegment 1.76 + { 1.77 + uint32_t mPos; 1.78 + int32_t mLen; 1.79 + 1.80 + URLSegment() : mPos(0), mLen(-1) {} 1.81 + URLSegment(uint32_t pos, int32_t len) : mPos(pos), mLen(len) {} 1.82 + void Reset() { mPos = 0; mLen = -1; } 1.83 + // Merge another segment following this one to it if they're contiguous 1.84 + // Assumes we have something like "foo;bar" where this object is 'foo' and right 1.85 + // is 'bar'. 1.86 + void Merge(const nsCString &spec, const char separator, const URLSegment &right) { 1.87 + if (mLen >= 0 && 1.88 + *(spec.get() + mPos + mLen) == separator && 1.89 + mPos + mLen + 1 == right.mPos) { 1.90 + mLen += 1 + right.mLen; 1.91 + } 1.92 + } 1.93 + }; 1.94 + 1.95 + // 1.96 + // Pref observer 1.97 + // 1.98 + class nsPrefObserver MOZ_FINAL : public nsIObserver 1.99 + { 1.100 + public: 1.101 + NS_DECL_ISUPPORTS 1.102 + NS_DECL_NSIOBSERVER 1.103 + 1.104 + nsPrefObserver() { } 1.105 + }; 1.106 + friend class nsPrefObserver; 1.107 + 1.108 + // 1.109 + // URL segment encoder : performs charset conversion and URL escaping. 1.110 + // 1.111 + class nsSegmentEncoder 1.112 + { 1.113 + public: 1.114 + nsSegmentEncoder(const char *charset); 1.115 + 1.116 + // Encode the given segment if necessary, and return the length of 1.117 + // the encoded segment. The encoded segment is appended to |buf| 1.118 + // if and only if encoding is required. 1.119 + int32_t EncodeSegmentCount(const char *str, 1.120 + const URLSegment &segment, 1.121 + int16_t mask, 1.122 + nsAFlatCString &buf, 1.123 + bool& appended, 1.124 + uint32_t extraLen = 0); 1.125 + 1.126 + // Encode the given string if necessary, and return a reference to 1.127 + // the encoded string. Returns a reference to |buf| if encoding 1.128 + // is required. Otherwise, a reference to |str| is returned. 1.129 + const nsACString &EncodeSegment(const nsASingleFragmentCString &str, 1.130 + int16_t mask, 1.131 + nsAFlatCString &buf); 1.132 + private: 1.133 + bool InitUnicodeEncoder(); 1.134 + 1.135 + const char* mCharset; // Caller should keep this alive for 1.136 + // the life of the segment encoder 1.137 + nsCOMPtr<nsIUnicodeEncoder> mEncoder; 1.138 + }; 1.139 + friend class nsSegmentEncoder; 1.140 + 1.141 +protected: 1.142 + // enum used in a few places to specify how .ref attribute should be handled 1.143 + enum RefHandlingEnum { 1.144 + eIgnoreRef, 1.145 + eHonorRef 1.146 + }; 1.147 + 1.148 + // Helper to share code between Equals and EqualsExceptRef 1.149 + // NOTE: *not* virtual, because no one needs to override this so far... 1.150 + nsresult EqualsInternal(nsIURI* unknownOther, 1.151 + RefHandlingEnum refHandlingMode, 1.152 + bool* result); 1.153 + 1.154 + virtual nsStandardURL* StartClone(); 1.155 + 1.156 + // Helper to share code between Clone methods. 1.157 + nsresult CloneInternal(RefHandlingEnum aRefHandlingMode, 1.158 + nsIURI** aClone); 1.159 + 1.160 + // Helper for subclass implementation of GetFile(). Subclasses that map 1.161 + // URIs to files in a special way should implement this method. It should 1.162 + // ensure that our mFile is initialized, if it's possible. 1.163 + // returns NS_ERROR_NO_INTERFACE if the url does not map to a file 1.164 + virtual nsresult EnsureFile(); 1.165 + 1.166 +private: 1.167 + int32_t Port() { return mPort == -1 ? mDefaultPort : mPort; } 1.168 + 1.169 + void Clear(); 1.170 + void InvalidateCache(bool invalidateCachedFile = true); 1.171 + 1.172 + bool EscapeIPv6(const char *host, nsCString &result); 1.173 + bool NormalizeIDN(const nsCSubstring &host, nsCString &result); 1.174 + void CoalescePath(netCoalesceFlags coalesceFlag, char *path); 1.175 + 1.176 + uint32_t AppendSegmentToBuf(char *, uint32_t, const char *, URLSegment &, const nsCString *esc=nullptr, bool useEsc = false); 1.177 + uint32_t AppendToBuf(char *, uint32_t, const char *, uint32_t); 1.178 + 1.179 + nsresult BuildNormalizedSpec(const char *spec); 1.180 + 1.181 + bool SegmentIs(const URLSegment &s1, const char *val, bool ignoreCase = false); 1.182 + bool SegmentIs(const char* spec, const URLSegment &s1, const char *val, bool ignoreCase = false); 1.183 + bool SegmentIs(const URLSegment &s1, const char *val, const URLSegment &s2, bool ignoreCase = false); 1.184 + 1.185 + int32_t ReplaceSegment(uint32_t pos, uint32_t len, const char *val, uint32_t valLen); 1.186 + int32_t ReplaceSegment(uint32_t pos, uint32_t len, const nsACString &val); 1.187 + 1.188 + nsresult ParseURL(const char *spec, int32_t specLen); 1.189 + nsresult ParsePath(const char *spec, uint32_t pathPos, int32_t pathLen = -1); 1.190 + 1.191 + char *AppendToSubstring(uint32_t pos, int32_t len, const char *tail); 1.192 + 1.193 + // dependent substring helpers 1.194 + const nsDependentCSubstring Segment(uint32_t pos, int32_t len); // see below 1.195 + const nsDependentCSubstring Segment(const URLSegment &s) { return Segment(s.mPos, s.mLen); } 1.196 + 1.197 + // dependent substring getters 1.198 + const nsDependentCSubstring Prepath(); // see below 1.199 + const nsDependentCSubstring Scheme() { return Segment(mScheme); } 1.200 + const nsDependentCSubstring Userpass(bool includeDelim = false); // see below 1.201 + const nsDependentCSubstring Username() { return Segment(mUsername); } 1.202 + const nsDependentCSubstring Password() { return Segment(mPassword); } 1.203 + const nsDependentCSubstring Hostport(); // see below 1.204 + const nsDependentCSubstring Host(); // see below 1.205 + const nsDependentCSubstring Path() { return Segment(mPath); } 1.206 + const nsDependentCSubstring Filepath() { return Segment(mFilepath); } 1.207 + const nsDependentCSubstring Directory() { return Segment(mDirectory); } 1.208 + const nsDependentCSubstring Filename(); // see below 1.209 + const nsDependentCSubstring Basename() { return Segment(mBasename); } 1.210 + const nsDependentCSubstring Extension() { return Segment(mExtension); } 1.211 + const nsDependentCSubstring Query() { return Segment(mQuery); } 1.212 + const nsDependentCSubstring Ref() { return Segment(mRef); } 1.213 + 1.214 + // shift the URLSegments to the right by diff 1.215 + void ShiftFromAuthority(int32_t diff) { mAuthority.mPos += diff; ShiftFromUsername(diff); } 1.216 + void ShiftFromUsername(int32_t diff) { mUsername.mPos += diff; ShiftFromPassword(diff); } 1.217 + void ShiftFromPassword(int32_t diff) { mPassword.mPos += diff; ShiftFromHost(diff); } 1.218 + void ShiftFromHost(int32_t diff) { mHost.mPos += diff; ShiftFromPath(diff); } 1.219 + void ShiftFromPath(int32_t diff) { mPath.mPos += diff; ShiftFromFilepath(diff); } 1.220 + void ShiftFromFilepath(int32_t diff) { mFilepath.mPos += diff; ShiftFromDirectory(diff); } 1.221 + void ShiftFromDirectory(int32_t diff) { mDirectory.mPos += diff; ShiftFromBasename(diff); } 1.222 + void ShiftFromBasename(int32_t diff) { mBasename.mPos += diff; ShiftFromExtension(diff); } 1.223 + void ShiftFromExtension(int32_t diff) { mExtension.mPos += diff; ShiftFromQuery(diff); } 1.224 + void ShiftFromQuery(int32_t diff) { mQuery.mPos += diff; ShiftFromRef(diff); } 1.225 + void ShiftFromRef(int32_t diff) { mRef.mPos += diff; } 1.226 + 1.227 + // fastload helper functions 1.228 + nsresult ReadSegment(nsIBinaryInputStream *, URLSegment &); 1.229 + nsresult WriteSegment(nsIBinaryOutputStream *, const URLSegment &); 1.230 + 1.231 + static void PrefsChanged(nsIPrefBranch *prefs, const char *pref); 1.232 + 1.233 + void FindHostLimit(nsACString::const_iterator& aStart, 1.234 + nsACString::const_iterator& aEnd); 1.235 + 1.236 + // mSpec contains the normalized version of the URL spec (UTF-8 encoded). 1.237 + nsCString mSpec; 1.238 + int32_t mDefaultPort; 1.239 + int32_t mPort; 1.240 + 1.241 + // url parts (relative to mSpec) 1.242 + URLSegment mScheme; 1.243 + URLSegment mAuthority; 1.244 + URLSegment mUsername; 1.245 + URLSegment mPassword; 1.246 + URLSegment mHost; 1.247 + URLSegment mPath; 1.248 + URLSegment mFilepath; 1.249 + URLSegment mDirectory; 1.250 + URLSegment mBasename; 1.251 + URLSegment mExtension; 1.252 + URLSegment mQuery; 1.253 + URLSegment mRef; 1.254 + 1.255 + nsCString mOriginCharset; 1.256 + nsCOMPtr<nsIURLParser> mParser; 1.257 + 1.258 + // mFile is protected so subclasses can access it directly 1.259 +protected: 1.260 + nsCOMPtr<nsIFile> mFile; // cached result for nsIFileURL::GetFile 1.261 + 1.262 +private: 1.263 + char *mHostA; // cached result for nsIURI::GetHostA 1.264 + 1.265 + enum { 1.266 + eEncoding_Unknown, 1.267 + eEncoding_ASCII, 1.268 + eEncoding_UTF8 1.269 + }; 1.270 + 1.271 + uint32_t mHostEncoding : 2; // eEncoding_xxx 1.272 + uint32_t mSpecEncoding : 2; // eEncoding_xxx 1.273 + uint32_t mURLType : 2; // nsIStandardURL::URLTYPE_xxx 1.274 + uint32_t mMutable : 1; // nsIStandardURL::mutable 1.275 + uint32_t mSupportsFileURL : 1; // QI to nsIFileURL? 1.276 + 1.277 + // global objects. don't use COMPtr as its destructor will cause a 1.278 + // coredump if we leak it. 1.279 + static nsIIDNService *gIDN; 1.280 + static char gHostLimitDigits[]; 1.281 + static nsICharsetConverterManager *gCharsetMgr; 1.282 + static bool gInitialized; 1.283 + static bool gEscapeUTF8; 1.284 + static bool gAlwaysEncodeInUTF8; 1.285 + static bool gEncodeQueryInUTF8; 1.286 + 1.287 +public: 1.288 +#ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN 1.289 + PRCList mDebugCList; 1.290 + void PrintSpec() const { printf(" %s\n", mSpec.get()); } 1.291 +#endif 1.292 +}; 1.293 + 1.294 +#define NS_THIS_STANDARDURL_IMPL_CID \ 1.295 +{ /* b8e3e97b-1ccd-4b45-af5a-79596770f5d7 */ \ 1.296 + 0xb8e3e97b, \ 1.297 + 0x1ccd, \ 1.298 + 0x4b45, \ 1.299 + {0xaf, 0x5a, 0x79, 0x59, 0x67, 0x70, 0xf5, 0xd7} \ 1.300 +} 1.301 + 1.302 +//----------------------------------------------------------------------------- 1.303 +// Dependent substring getters 1.304 +//----------------------------------------------------------------------------- 1.305 + 1.306 +inline const nsDependentCSubstring 1.307 +nsStandardURL::Segment(uint32_t pos, int32_t len) 1.308 +{ 1.309 + if (len < 0) { 1.310 + pos = 0; 1.311 + len = 0; 1.312 + } 1.313 + return Substring(mSpec, pos, uint32_t(len)); 1.314 +} 1.315 + 1.316 +inline const nsDependentCSubstring 1.317 +nsStandardURL::Prepath() 1.318 +{ 1.319 + uint32_t len = 0; 1.320 + if (mAuthority.mLen >= 0) 1.321 + len = mAuthority.mPos + mAuthority.mLen; 1.322 + return Substring(mSpec, 0, len); 1.323 +} 1.324 + 1.325 +inline const nsDependentCSubstring 1.326 +nsStandardURL::Userpass(bool includeDelim) 1.327 +{ 1.328 + uint32_t pos=0, len=0; 1.329 + // if there is no username, then there can be no password 1.330 + if (mUsername.mLen > 0) { 1.331 + pos = mUsername.mPos; 1.332 + len = mUsername.mLen; 1.333 + if (mPassword.mLen >= 0) 1.334 + len += (mPassword.mLen + 1); 1.335 + if (includeDelim) 1.336 + len++; 1.337 + } 1.338 + return Substring(mSpec, pos, len); 1.339 +} 1.340 + 1.341 +inline const nsDependentCSubstring 1.342 +nsStandardURL::Hostport() 1.343 +{ 1.344 + uint32_t pos=0, len=0; 1.345 + if (mAuthority.mLen > 0) { 1.346 + pos = mHost.mPos; 1.347 + len = mAuthority.mPos + mAuthority.mLen - pos; 1.348 + } 1.349 + return Substring(mSpec, pos, len); 1.350 +} 1.351 + 1.352 +inline const nsDependentCSubstring 1.353 +nsStandardURL::Host() 1.354 +{ 1.355 + uint32_t pos=0, len=0; 1.356 + if (mHost.mLen > 0) { 1.357 + pos = mHost.mPos; 1.358 + len = mHost.mLen; 1.359 + if (mSpec.CharAt(pos) == '[' && mSpec.CharAt(pos + len - 1) == ']') { 1.360 + pos++; 1.361 + len -= 2; 1.362 + } 1.363 + } 1.364 + return Substring(mSpec, pos, len); 1.365 +} 1.366 + 1.367 +inline const nsDependentCSubstring 1.368 +nsStandardURL::Filename() 1.369 +{ 1.370 + uint32_t pos=0, len=0; 1.371 + // if there is no basename, then there can be no extension 1.372 + if (mBasename.mLen > 0) { 1.373 + pos = mBasename.mPos; 1.374 + len = mBasename.mLen; 1.375 + if (mExtension.mLen >= 0) 1.376 + len += (mExtension.mLen + 1); 1.377 + } 1.378 + return Substring(mSpec, pos, len); 1.379 +} 1.380 + 1.381 +#endif // nsStandardURL_h__