nsStandardURL.h 14 KB

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