|
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/. */ |
|
5 |
|
6 #ifndef nsStandardURL_h__ |
|
7 #define nsStandardURL_h__ |
|
8 |
|
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" |
|
23 |
|
24 #ifdef NS_BUILD_REFCNT_LOGGING |
|
25 #define DEBUG_DUMP_URLS_AT_SHUTDOWN |
|
26 #endif |
|
27 |
|
28 class nsIBinaryInputStream; |
|
29 class nsIBinaryOutputStream; |
|
30 class nsIIDNService; |
|
31 class nsICharsetConverterManager; |
|
32 class nsIPrefBranch; |
|
33 class nsIFile; |
|
34 class nsIURLParser; |
|
35 |
|
36 //----------------------------------------------------------------------------- |
|
37 // standard URL implementation |
|
38 //----------------------------------------------------------------------------- |
|
39 |
|
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 |
|
57 |
|
58 // nsISizeOf |
|
59 virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; |
|
60 virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; |
|
61 |
|
62 nsStandardURL(bool aSupportsFileURL = false); |
|
63 virtual ~nsStandardURL(); |
|
64 |
|
65 static void InitGlobalObjects(); |
|
66 static void ShutdownGlobalObjects(); |
|
67 |
|
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; |
|
76 |
|
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 }; |
|
91 |
|
92 // |
|
93 // Pref observer |
|
94 // |
|
95 class nsPrefObserver MOZ_FINAL : public nsIObserver |
|
96 { |
|
97 public: |
|
98 NS_DECL_ISUPPORTS |
|
99 NS_DECL_NSIOBSERVER |
|
100 |
|
101 nsPrefObserver() { } |
|
102 }; |
|
103 friend class nsPrefObserver; |
|
104 |
|
105 // |
|
106 // URL segment encoder : performs charset conversion and URL escaping. |
|
107 // |
|
108 class nsSegmentEncoder |
|
109 { |
|
110 public: |
|
111 nsSegmentEncoder(const char *charset); |
|
112 |
|
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); |
|
122 |
|
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(); |
|
131 |
|
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; |
|
137 |
|
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 }; |
|
144 |
|
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); |
|
150 |
|
151 virtual nsStandardURL* StartClone(); |
|
152 |
|
153 // Helper to share code between Clone methods. |
|
154 nsresult CloneInternal(RefHandlingEnum aRefHandlingMode, |
|
155 nsIURI** aClone); |
|
156 |
|
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(); |
|
162 |
|
163 private: |
|
164 int32_t Port() { return mPort == -1 ? mDefaultPort : mPort; } |
|
165 |
|
166 void Clear(); |
|
167 void InvalidateCache(bool invalidateCachedFile = true); |
|
168 |
|
169 bool EscapeIPv6(const char *host, nsCString &result); |
|
170 bool NormalizeIDN(const nsCSubstring &host, nsCString &result); |
|
171 void CoalescePath(netCoalesceFlags coalesceFlag, char *path); |
|
172 |
|
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); |
|
175 |
|
176 nsresult BuildNormalizedSpec(const char *spec); |
|
177 |
|
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); |
|
181 |
|
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); |
|
184 |
|
185 nsresult ParseURL(const char *spec, int32_t specLen); |
|
186 nsresult ParsePath(const char *spec, uint32_t pathPos, int32_t pathLen = -1); |
|
187 |
|
188 char *AppendToSubstring(uint32_t pos, int32_t len, const char *tail); |
|
189 |
|
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); } |
|
193 |
|
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); } |
|
210 |
|
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; } |
|
223 |
|
224 // fastload helper functions |
|
225 nsresult ReadSegment(nsIBinaryInputStream *, URLSegment &); |
|
226 nsresult WriteSegment(nsIBinaryOutputStream *, const URLSegment &); |
|
227 |
|
228 static void PrefsChanged(nsIPrefBranch *prefs, const char *pref); |
|
229 |
|
230 void FindHostLimit(nsACString::const_iterator& aStart, |
|
231 nsACString::const_iterator& aEnd); |
|
232 |
|
233 // mSpec contains the normalized version of the URL spec (UTF-8 encoded). |
|
234 nsCString mSpec; |
|
235 int32_t mDefaultPort; |
|
236 int32_t mPort; |
|
237 |
|
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; |
|
251 |
|
252 nsCString mOriginCharset; |
|
253 nsCOMPtr<nsIURLParser> mParser; |
|
254 |
|
255 // mFile is protected so subclasses can access it directly |
|
256 protected: |
|
257 nsCOMPtr<nsIFile> mFile; // cached result for nsIFileURL::GetFile |
|
258 |
|
259 private: |
|
260 char *mHostA; // cached result for nsIURI::GetHostA |
|
261 |
|
262 enum { |
|
263 eEncoding_Unknown, |
|
264 eEncoding_ASCII, |
|
265 eEncoding_UTF8 |
|
266 }; |
|
267 |
|
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? |
|
273 |
|
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; |
|
283 |
|
284 public: |
|
285 #ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN |
|
286 PRCList mDebugCList; |
|
287 void PrintSpec() const { printf(" %s\n", mSpec.get()); } |
|
288 #endif |
|
289 }; |
|
290 |
|
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 } |
|
298 |
|
299 //----------------------------------------------------------------------------- |
|
300 // Dependent substring getters |
|
301 //----------------------------------------------------------------------------- |
|
302 |
|
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 } |
|
312 |
|
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 } |
|
321 |
|
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 } |
|
337 |
|
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 } |
|
348 |
|
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 } |
|
363 |
|
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 } |
|
377 |
|
378 #endif // nsStandardURL_h__ |