Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef nsStandardURL_h__
7 #define nsStandardURL_h__
9 #include "nsString.h"
10 #include "nsISerializable.h"
11 #include "nsIFileURL.h"
12 #include "nsIStandardURL.h"
13 #include "nsIUnicodeEncoder.h"
14 #include "nsIObserver.h"
15 #include "nsCOMPtr.h"
16 #include "nsURLHelper.h"
17 #include "nsIClassInfo.h"
18 #include "nsISizeOf.h"
19 #include "prclist.h"
20 #include "mozilla/Attributes.h"
21 #include "mozilla/MemoryReporting.h"
22 #include "nsIIPCSerializableURI.h"
24 #ifdef NS_BUILD_REFCNT_LOGGING
25 #define DEBUG_DUMP_URLS_AT_SHUTDOWN
26 #endif
28 class nsIBinaryInputStream;
29 class nsIBinaryOutputStream;
30 class nsIIDNService;
31 class nsICharsetConverterManager;
32 class nsIPrefBranch;
33 class nsIFile;
34 class nsIURLParser;
36 //-----------------------------------------------------------------------------
37 // standard URL implementation
38 //-----------------------------------------------------------------------------
40 class nsStandardURL : public nsIFileURL
41 , public nsIStandardURL
42 , public nsISerializable
43 , public nsIClassInfo
44 , public nsISizeOf
45 , public nsIIPCSerializableURI
46 {
47 public:
48 NS_DECL_ISUPPORTS
49 NS_DECL_NSIURI
50 NS_DECL_NSIURL
51 NS_DECL_NSIFILEURL
52 NS_DECL_NSISTANDARDURL
53 NS_DECL_NSISERIALIZABLE
54 NS_DECL_NSICLASSINFO
55 NS_DECL_NSIMUTABLE
56 NS_DECL_NSIIPCSERIALIZABLEURI
58 // nsISizeOf
59 virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
60 virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
62 nsStandardURL(bool aSupportsFileURL = false);
63 virtual ~nsStandardURL();
65 static void InitGlobalObjects();
66 static void ShutdownGlobalObjects();
68 public: /* internal -- HPUX compiler can't handle this being private */
69 //
70 // location and length of an url segment relative to mSpec
71 //
72 struct URLSegment
73 {
74 uint32_t mPos;
75 int32_t mLen;
77 URLSegment() : mPos(0), mLen(-1) {}
78 URLSegment(uint32_t pos, int32_t len) : mPos(pos), mLen(len) {}
79 void Reset() { mPos = 0; mLen = -1; }
80 // Merge another segment following this one to it if they're contiguous
81 // Assumes we have something like "foo;bar" where this object is 'foo' and right
82 // is 'bar'.
83 void Merge(const nsCString &spec, const char separator, const URLSegment &right) {
84 if (mLen >= 0 &&
85 *(spec.get() + mPos + mLen) == separator &&
86 mPos + mLen + 1 == right.mPos) {
87 mLen += 1 + right.mLen;
88 }
89 }
90 };
92 //
93 // Pref observer
94 //
95 class nsPrefObserver MOZ_FINAL : public nsIObserver
96 {
97 public:
98 NS_DECL_ISUPPORTS
99 NS_DECL_NSIOBSERVER
101 nsPrefObserver() { }
102 };
103 friend class nsPrefObserver;
105 //
106 // URL segment encoder : performs charset conversion and URL escaping.
107 //
108 class nsSegmentEncoder
109 {
110 public:
111 nsSegmentEncoder(const char *charset);
113 // Encode the given segment if necessary, and return the length of
114 // the encoded segment. The encoded segment is appended to |buf|
115 // if and only if encoding is required.
116 int32_t EncodeSegmentCount(const char *str,
117 const URLSegment &segment,
118 int16_t mask,
119 nsAFlatCString &buf,
120 bool& appended,
121 uint32_t extraLen = 0);
123 // Encode the given string if necessary, and return a reference to
124 // the encoded string. Returns a reference to |buf| if encoding
125 // is required. Otherwise, a reference to |str| is returned.
126 const nsACString &EncodeSegment(const nsASingleFragmentCString &str,
127 int16_t mask,
128 nsAFlatCString &buf);
129 private:
130 bool InitUnicodeEncoder();
132 const char* mCharset; // Caller should keep this alive for
133 // the life of the segment encoder
134 nsCOMPtr<nsIUnicodeEncoder> mEncoder;
135 };
136 friend class nsSegmentEncoder;
138 protected:
139 // enum used in a few places to specify how .ref attribute should be handled
140 enum RefHandlingEnum {
141 eIgnoreRef,
142 eHonorRef
143 };
145 // Helper to share code between Equals and EqualsExceptRef
146 // NOTE: *not* virtual, because no one needs to override this so far...
147 nsresult EqualsInternal(nsIURI* unknownOther,
148 RefHandlingEnum refHandlingMode,
149 bool* result);
151 virtual nsStandardURL* StartClone();
153 // Helper to share code between Clone methods.
154 nsresult CloneInternal(RefHandlingEnum aRefHandlingMode,
155 nsIURI** aClone);
157 // Helper for subclass implementation of GetFile(). Subclasses that map
158 // URIs to files in a special way should implement this method. It should
159 // ensure that our mFile is initialized, if it's possible.
160 // returns NS_ERROR_NO_INTERFACE if the url does not map to a file
161 virtual nsresult EnsureFile();
163 private:
164 int32_t Port() { return mPort == -1 ? mDefaultPort : mPort; }
166 void Clear();
167 void InvalidateCache(bool invalidateCachedFile = true);
169 bool EscapeIPv6(const char *host, nsCString &result);
170 bool NormalizeIDN(const nsCSubstring &host, nsCString &result);
171 void CoalescePath(netCoalesceFlags coalesceFlag, char *path);
173 uint32_t AppendSegmentToBuf(char *, uint32_t, const char *, URLSegment &, const nsCString *esc=nullptr, bool useEsc = false);
174 uint32_t AppendToBuf(char *, uint32_t, const char *, uint32_t);
176 nsresult BuildNormalizedSpec(const char *spec);
178 bool SegmentIs(const URLSegment &s1, const char *val, bool ignoreCase = false);
179 bool SegmentIs(const char* spec, const URLSegment &s1, const char *val, bool ignoreCase = false);
180 bool SegmentIs(const URLSegment &s1, const char *val, const URLSegment &s2, bool ignoreCase = false);
182 int32_t ReplaceSegment(uint32_t pos, uint32_t len, const char *val, uint32_t valLen);
183 int32_t ReplaceSegment(uint32_t pos, uint32_t len, const nsACString &val);
185 nsresult ParseURL(const char *spec, int32_t specLen);
186 nsresult ParsePath(const char *spec, uint32_t pathPos, int32_t pathLen = -1);
188 char *AppendToSubstring(uint32_t pos, int32_t len, const char *tail);
190 // dependent substring helpers
191 const nsDependentCSubstring Segment(uint32_t pos, int32_t len); // see below
192 const nsDependentCSubstring Segment(const URLSegment &s) { return Segment(s.mPos, s.mLen); }
194 // dependent substring getters
195 const nsDependentCSubstring Prepath(); // see below
196 const nsDependentCSubstring Scheme() { return Segment(mScheme); }
197 const nsDependentCSubstring Userpass(bool includeDelim = false); // see below
198 const nsDependentCSubstring Username() { return Segment(mUsername); }
199 const nsDependentCSubstring Password() { return Segment(mPassword); }
200 const nsDependentCSubstring Hostport(); // see below
201 const nsDependentCSubstring Host(); // see below
202 const nsDependentCSubstring Path() { return Segment(mPath); }
203 const nsDependentCSubstring Filepath() { return Segment(mFilepath); }
204 const nsDependentCSubstring Directory() { return Segment(mDirectory); }
205 const nsDependentCSubstring Filename(); // see below
206 const nsDependentCSubstring Basename() { return Segment(mBasename); }
207 const nsDependentCSubstring Extension() { return Segment(mExtension); }
208 const nsDependentCSubstring Query() { return Segment(mQuery); }
209 const nsDependentCSubstring Ref() { return Segment(mRef); }
211 // shift the URLSegments to the right by diff
212 void ShiftFromAuthority(int32_t diff) { mAuthority.mPos += diff; ShiftFromUsername(diff); }
213 void ShiftFromUsername(int32_t diff) { mUsername.mPos += diff; ShiftFromPassword(diff); }
214 void ShiftFromPassword(int32_t diff) { mPassword.mPos += diff; ShiftFromHost(diff); }
215 void ShiftFromHost(int32_t diff) { mHost.mPos += diff; ShiftFromPath(diff); }
216 void ShiftFromPath(int32_t diff) { mPath.mPos += diff; ShiftFromFilepath(diff); }
217 void ShiftFromFilepath(int32_t diff) { mFilepath.mPos += diff; ShiftFromDirectory(diff); }
218 void ShiftFromDirectory(int32_t diff) { mDirectory.mPos += diff; ShiftFromBasename(diff); }
219 void ShiftFromBasename(int32_t diff) { mBasename.mPos += diff; ShiftFromExtension(diff); }
220 void ShiftFromExtension(int32_t diff) { mExtension.mPos += diff; ShiftFromQuery(diff); }
221 void ShiftFromQuery(int32_t diff) { mQuery.mPos += diff; ShiftFromRef(diff); }
222 void ShiftFromRef(int32_t diff) { mRef.mPos += diff; }
224 // fastload helper functions
225 nsresult ReadSegment(nsIBinaryInputStream *, URLSegment &);
226 nsresult WriteSegment(nsIBinaryOutputStream *, const URLSegment &);
228 static void PrefsChanged(nsIPrefBranch *prefs, const char *pref);
230 void FindHostLimit(nsACString::const_iterator& aStart,
231 nsACString::const_iterator& aEnd);
233 // mSpec contains the normalized version of the URL spec (UTF-8 encoded).
234 nsCString mSpec;
235 int32_t mDefaultPort;
236 int32_t mPort;
238 // url parts (relative to mSpec)
239 URLSegment mScheme;
240 URLSegment mAuthority;
241 URLSegment mUsername;
242 URLSegment mPassword;
243 URLSegment mHost;
244 URLSegment mPath;
245 URLSegment mFilepath;
246 URLSegment mDirectory;
247 URLSegment mBasename;
248 URLSegment mExtension;
249 URLSegment mQuery;
250 URLSegment mRef;
252 nsCString mOriginCharset;
253 nsCOMPtr<nsIURLParser> mParser;
255 // mFile is protected so subclasses can access it directly
256 protected:
257 nsCOMPtr<nsIFile> mFile; // cached result for nsIFileURL::GetFile
259 private:
260 char *mHostA; // cached result for nsIURI::GetHostA
262 enum {
263 eEncoding_Unknown,
264 eEncoding_ASCII,
265 eEncoding_UTF8
266 };
268 uint32_t mHostEncoding : 2; // eEncoding_xxx
269 uint32_t mSpecEncoding : 2; // eEncoding_xxx
270 uint32_t mURLType : 2; // nsIStandardURL::URLTYPE_xxx
271 uint32_t mMutable : 1; // nsIStandardURL::mutable
272 uint32_t mSupportsFileURL : 1; // QI to nsIFileURL?
274 // global objects. don't use COMPtr as its destructor will cause a
275 // coredump if we leak it.
276 static nsIIDNService *gIDN;
277 static char gHostLimitDigits[];
278 static nsICharsetConverterManager *gCharsetMgr;
279 static bool gInitialized;
280 static bool gEscapeUTF8;
281 static bool gAlwaysEncodeInUTF8;
282 static bool gEncodeQueryInUTF8;
284 public:
285 #ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN
286 PRCList mDebugCList;
287 void PrintSpec() const { printf(" %s\n", mSpec.get()); }
288 #endif
289 };
291 #define NS_THIS_STANDARDURL_IMPL_CID \
292 { /* b8e3e97b-1ccd-4b45-af5a-79596770f5d7 */ \
293 0xb8e3e97b, \
294 0x1ccd, \
295 0x4b45, \
296 {0xaf, 0x5a, 0x79, 0x59, 0x67, 0x70, 0xf5, 0xd7} \
297 }
299 //-----------------------------------------------------------------------------
300 // Dependent substring getters
301 //-----------------------------------------------------------------------------
303 inline const nsDependentCSubstring
304 nsStandardURL::Segment(uint32_t pos, int32_t len)
305 {
306 if (len < 0) {
307 pos = 0;
308 len = 0;
309 }
310 return Substring(mSpec, pos, uint32_t(len));
311 }
313 inline const nsDependentCSubstring
314 nsStandardURL::Prepath()
315 {
316 uint32_t len = 0;
317 if (mAuthority.mLen >= 0)
318 len = mAuthority.mPos + mAuthority.mLen;
319 return Substring(mSpec, 0, len);
320 }
322 inline const nsDependentCSubstring
323 nsStandardURL::Userpass(bool includeDelim)
324 {
325 uint32_t pos=0, len=0;
326 // if there is no username, then there can be no password
327 if (mUsername.mLen > 0) {
328 pos = mUsername.mPos;
329 len = mUsername.mLen;
330 if (mPassword.mLen >= 0)
331 len += (mPassword.mLen + 1);
332 if (includeDelim)
333 len++;
334 }
335 return Substring(mSpec, pos, len);
336 }
338 inline const nsDependentCSubstring
339 nsStandardURL::Hostport()
340 {
341 uint32_t pos=0, len=0;
342 if (mAuthority.mLen > 0) {
343 pos = mHost.mPos;
344 len = mAuthority.mPos + mAuthority.mLen - pos;
345 }
346 return Substring(mSpec, pos, len);
347 }
349 inline const nsDependentCSubstring
350 nsStandardURL::Host()
351 {
352 uint32_t pos=0, len=0;
353 if (mHost.mLen > 0) {
354 pos = mHost.mPos;
355 len = mHost.mLen;
356 if (mSpec.CharAt(pos) == '[' && mSpec.CharAt(pos + len - 1) == ']') {
357 pos++;
358 len -= 2;
359 }
360 }
361 return Substring(mSpec, pos, len);
362 }
364 inline const nsDependentCSubstring
365 nsStandardURL::Filename()
366 {
367 uint32_t pos=0, len=0;
368 // if there is no basename, then there can be no extension
369 if (mBasename.mLen > 0) {
370 pos = mBasename.mPos;
371 len = mBasename.mLen;
372 if (mExtension.mLen >= 0)
373 len += (mExtension.mLen + 1);
374 }
375 return Substring(mSpec, pos, len);
376 }
378 #endif // nsStandardURL_h__