123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 |
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #ifndef nsStandardURL_h__
- #define nsStandardURL_h__
- #include "nsString.h"
- #include "nsISerializable.h"
- #include "nsIFileURL.h"
- #include "nsIStandardURL.h"
- #include "nsIUnicodeEncoder.h"
- #include "nsIObserver.h"
- #include "nsCOMPtr.h"
- #include "nsURLHelper.h"
- #include "nsIClassInfo.h"
- #include "nsISizeOf.h"
- #include "prclist.h"
- #include "mozilla/Attributes.h"
- #include "mozilla/MemoryReporting.h"
- #include "nsIIPCSerializableURI.h"
- #include "nsISensitiveInfoHiddenURI.h"
- #ifdef NS_BUILD_REFCNT_LOGGING
- #define DEBUG_DUMP_URLS_AT_SHUTDOWN
- #endif
- class nsIBinaryInputStream;
- class nsIBinaryOutputStream;
- class nsIIDNService;
- class nsIPrefBranch;
- class nsIFile;
- class nsIURLParser;
- namespace mozilla {
- namespace net {
- //-----------------------------------------------------------------------------
- // standard URL implementation
- //-----------------------------------------------------------------------------
- class nsStandardURL : public nsIFileURL
- , public nsIStandardURL
- , public nsISerializable
- , public nsIClassInfo
- , public nsISizeOf
- , public nsIIPCSerializableURI
- , public nsISensitiveInfoHiddenURI
- {
- protected:
- virtual ~nsStandardURL();
- public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIURI
- NS_DECL_NSIURL
- NS_DECL_NSIFILEURL
- NS_DECL_NSISTANDARDURL
- NS_DECL_NSISERIALIZABLE
- NS_DECL_NSICLASSINFO
- NS_DECL_NSIMUTABLE
- NS_DECL_NSIIPCSERIALIZABLEURI
- NS_DECL_NSISENSITIVEINFOHIDDENURI
- // nsISizeOf
- virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
- virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override;
- explicit nsStandardURL(bool aSupportsFileURL = false, bool aTrackURL = true);
- static void InitGlobalObjects();
- static void ShutdownGlobalObjects();
- //
- // location and length of an url segment relative to mSpec
- //
- struct URLSegment
- {
- uint32_t mPos;
- int32_t mLen;
- URLSegment() : mPos(0), mLen(-1) {}
- URLSegment(uint32_t pos, int32_t len) : mPos(pos), mLen(len) {}
- URLSegment(const URLSegment& aCopy) : mPos(aCopy.mPos), mLen(aCopy.mLen) {}
- void Reset() { mPos = 0; mLen = -1; }
- // Merge another segment following this one to it if they're contiguous
- // Assumes we have something like "foo;bar" where this object is 'foo' and right
- // is 'bar'.
- void Merge(const nsCString &spec, const char separator, const URLSegment &right) {
- if (mLen >= 0 &&
- *(spec.get() + mPos + mLen) == separator &&
- mPos + mLen + 1 == right.mPos) {
- mLen += 1 + right.mLen;
- }
- }
- };
- //
- // Pref observer
- //
- class nsPrefObserver final : public nsIObserver
- {
- ~nsPrefObserver() {}
- public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
- nsPrefObserver() { }
- };
- friend class nsPrefObserver;
- //
- // URL segment encoder : performs charset conversion and URL escaping.
- //
- class nsSegmentEncoder
- {
- public:
- explicit nsSegmentEncoder(const char *charset);
- // Encode the given segment if necessary, and return the length of
- // the encoded segment. The encoded segment is appended to |buf|
- // if and only if encoding is required.
- int32_t EncodeSegmentCount(const char *str,
- const URLSegment &segment,
- int16_t mask,
- nsAFlatCString &buf,
- bool& appended,
- uint32_t extraLen = 0);
-
- // Encode the given string if necessary, and return a reference to
- // the encoded string. Returns a reference to |buf| if encoding
- // is required. Otherwise, a reference to |str| is returned.
- const nsACString &EncodeSegment(const nsASingleFragmentCString &str,
- int16_t mask,
- nsAFlatCString &buf);
- private:
- bool InitUnicodeEncoder();
-
- const char* mCharset; // Caller should keep this alive for
- // the life of the segment encoder
- nsCOMPtr<nsIUnicodeEncoder> mEncoder;
- };
- friend class nsSegmentEncoder;
- protected:
- // enum used in a few places to specify how .ref attribute should be handled
- enum RefHandlingEnum {
- eIgnoreRef,
- eHonorRef,
- eReplaceRef
- };
- // Helper to share code between Equals and EqualsExceptRef
- // NOTE: *not* virtual, because no one needs to override this so far...
- nsresult EqualsInternal(nsIURI* unknownOther,
- RefHandlingEnum refHandlingMode,
- bool* result);
- virtual nsStandardURL* StartClone();
- // Helper to share code between Clone methods.
- nsresult CloneInternal(RefHandlingEnum aRefHandlingMode,
- const nsACString& newRef,
- nsIURI** aClone);
- // Helper method that copies member variables from the source StandardURL
- // if copyCached = true, it will also copy mFile and mHostA
- nsresult CopyMembers(nsStandardURL * source, RefHandlingEnum mode,
- const nsACString& newRef,
- bool copyCached = false);
- // Helper for subclass implementation of GetFile(). Subclasses that map
- // URIs to files in a special way should implement this method. It should
- // ensure that our mFile is initialized, if it's possible.
- // returns NS_ERROR_NO_INTERFACE if the url does not map to a file
- virtual nsresult EnsureFile();
- private:
- int32_t Port() { return mPort == -1 ? mDefaultPort : mPort; }
- void ReplacePortInSpec(int32_t aNewPort);
- void Clear();
- void InvalidateCache(bool invalidateCachedFile = true);
- bool ValidIPv6orHostname(const char *host, uint32_t aLen);
- static bool IsValidOfBase(unsigned char c, const uint32_t base);
- static nsresult ParseIPv4Number(nsCString &input, uint32_t &number);
- static nsresult NormalizeIPv4(const nsCSubstring &host, nsCString &result);
- nsresult NormalizeIDN(const nsCSubstring &host, nsCString &result);
- void CoalescePath(netCoalesceFlags coalesceFlag, char *path);
- uint32_t AppendSegmentToBuf(char *, uint32_t, const char *,
- const URLSegment &input, URLSegment &output,
- const nsCString *esc=nullptr,
- bool useEsc = false, int32_t* diff = nullptr);
- uint32_t AppendToBuf(char *, uint32_t, const char *, uint32_t);
- nsresult BuildNormalizedSpec(const char *spec);
- bool SegmentIs(const URLSegment &s1, const char *val, bool ignoreCase = false);
- bool SegmentIs(const char* spec, const URLSegment &s1, const char *val, bool ignoreCase = false);
- bool SegmentIs(const URLSegment &s1, const char *val, const URLSegment &s2, bool ignoreCase = false);
- int32_t ReplaceSegment(uint32_t pos, uint32_t len, const char *val, uint32_t valLen);
- int32_t ReplaceSegment(uint32_t pos, uint32_t len, const nsACString &val);
- nsresult ParseURL(const char *spec, int32_t specLen);
- nsresult ParsePath(const char *spec, uint32_t pathPos, int32_t pathLen = -1);
- char *AppendToSubstring(uint32_t pos, int32_t len, const char *tail);
- // dependent substring helpers
- const nsDependentCSubstring Segment(uint32_t pos, int32_t len); // see below
- const nsDependentCSubstring Segment(const URLSegment &s) { return Segment(s.mPos, s.mLen); }
- // dependent substring getters
- const nsDependentCSubstring Prepath(); // see below
- const nsDependentCSubstring Scheme() { return Segment(mScheme); }
- const nsDependentCSubstring Userpass(bool includeDelim = false); // see below
- const nsDependentCSubstring Username() { return Segment(mUsername); }
- const nsDependentCSubstring Password() { return Segment(mPassword); }
- const nsDependentCSubstring Hostport(); // see below
- const nsDependentCSubstring Host(); // see below
- const nsDependentCSubstring Path() { return Segment(mPath); }
- const nsDependentCSubstring Filepath() { return Segment(mFilepath); }
- const nsDependentCSubstring Directory() { return Segment(mDirectory); }
- const nsDependentCSubstring Filename(); // see below
- const nsDependentCSubstring Basename() { return Segment(mBasename); }
- const nsDependentCSubstring Extension() { return Segment(mExtension); }
- const nsDependentCSubstring Query() { return Segment(mQuery); }
- const nsDependentCSubstring Ref() { return Segment(mRef); }
- // shift the URLSegments to the right by diff
- void ShiftFromAuthority(int32_t diff);
- void ShiftFromUsername(int32_t diff);
- void ShiftFromPassword(int32_t diff);
- void ShiftFromHost(int32_t diff);
- void ShiftFromPath(int32_t diff);
- void ShiftFromFilepath(int32_t diff);
- void ShiftFromDirectory(int32_t diff);
- void ShiftFromBasename(int32_t diff);
- void ShiftFromExtension(int32_t diff);
- void ShiftFromQuery(int32_t diff);
- void ShiftFromRef(int32_t diff);
- // fastload helper functions
- nsresult ReadSegment(nsIBinaryInputStream *, URLSegment &);
- nsresult WriteSegment(nsIBinaryOutputStream *, const URLSegment &);
- static void PrefsChanged(nsIPrefBranch *prefs, const char *pref);
- void FindHostLimit(nsACString::const_iterator& aStart,
- nsACString::const_iterator& aEnd);
- // Checks if the URL has a valid representation.
- bool IsValid();
- // mSpec contains the normalized version of the URL spec (UTF-8 encoded).
- nsCString mSpec;
- int32_t mDefaultPort;
- int32_t mPort;
- // url parts (relative to mSpec)
- URLSegment mScheme;
- URLSegment mAuthority;
- URLSegment mUsername;
- URLSegment mPassword;
- URLSegment mHost;
- URLSegment mPath;
- URLSegment mFilepath;
- URLSegment mDirectory;
- URLSegment mBasename;
- URLSegment mExtension;
- URLSegment mQuery;
- URLSegment mRef;
- nsCString mOriginCharset;
- nsCOMPtr<nsIURLParser> mParser;
- // mFile is protected so subclasses can access it directly
- protected:
- nsCOMPtr<nsIFile> mFile; // cached result for nsIFileURL::GetFile
-
- private:
- char *mHostA; // cached result for nsIURI::GetHostA
- enum {
- eEncoding_Unknown,
- eEncoding_ASCII,
- eEncoding_UTF8
- };
- uint32_t mHostEncoding : 2; // eEncoding_xxx
- uint32_t mSpecEncoding : 2; // eEncoding_xxx
- uint32_t mURLType : 2; // nsIStandardURL::URLTYPE_xxx
- uint32_t mMutable : 1; // nsIStandardURL::mutable
- uint32_t mSupportsFileURL : 1; // QI to nsIFileURL?
- // global objects. don't use COMPtr as its destructor will cause a
- // coredump if we leak it.
- static nsIIDNService *gIDN;
- static char gHostLimitDigits[];
- static bool gInitialized;
- static bool gEscapeUTF8;
- static bool gAlwaysEncodeInUTF8;
- static bool gEncodeQueryInUTF8;
- public:
- #ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN
- PRCList mDebugCList;
- void PrintSpec() const { printf(" %s\n", mSpec.get()); }
- #endif
- };
- #define NS_THIS_STANDARDURL_IMPL_CID \
- { /* b8e3e97b-1ccd-4b45-af5a-79596770f5d7 */ \
- 0xb8e3e97b, \
- 0x1ccd, \
- 0x4b45, \
- {0xaf, 0x5a, 0x79, 0x59, 0x67, 0x70, 0xf5, 0xd7} \
- }
- //-----------------------------------------------------------------------------
- // Dependent substring getters
- //-----------------------------------------------------------------------------
- inline const nsDependentCSubstring
- nsStandardURL::Segment(uint32_t pos, int32_t len)
- {
- if (len < 0) {
- pos = 0;
- len = 0;
- }
- return Substring(mSpec, pos, uint32_t(len));
- }
- inline const nsDependentCSubstring
- nsStandardURL::Prepath()
- {
- uint32_t len = 0;
- if (mAuthority.mLen >= 0)
- len = mAuthority.mPos + mAuthority.mLen;
- return Substring(mSpec, 0, len);
- }
- inline const nsDependentCSubstring
- nsStandardURL::Userpass(bool includeDelim)
- {
- uint32_t pos=0, len=0;
- // if there is no username, then there can be no password
- if (mUsername.mLen > 0) {
- pos = mUsername.mPos;
- len = mUsername.mLen;
- if (mPassword.mLen >= 0)
- len += (mPassword.mLen + 1);
- if (includeDelim)
- len++;
- }
- return Substring(mSpec, pos, len);
- }
- inline const nsDependentCSubstring
- nsStandardURL::Hostport()
- {
- uint32_t pos=0, len=0;
- if (mAuthority.mLen > 0) {
- pos = mHost.mPos;
- len = mAuthority.mPos + mAuthority.mLen - pos;
- }
- return Substring(mSpec, pos, len);
- }
- inline const nsDependentCSubstring
- nsStandardURL::Host()
- {
- uint32_t pos=0, len=0;
- if (mHost.mLen > 0) {
- pos = mHost.mPos;
- len = mHost.mLen;
- if (mSpec.CharAt(pos) == '[' && mSpec.CharAt(pos + len - 1) == ']') {
- pos++;
- len -= 2;
- }
- }
- return Substring(mSpec, pos, len);
- }
- inline const nsDependentCSubstring
- nsStandardURL::Filename()
- {
- uint32_t pos=0, len=0;
- // if there is no basename, then there can be no extension
- if (mBasename.mLen > 0) {
- pos = mBasename.mPos;
- len = mBasename.mLen;
- if (mExtension.mLen >= 0)
- len += (mExtension.mLen + 1);
- }
- return Substring(mSpec, pos, len);
- }
- } // namespace net
- } // namespace mozilla
- #endif // nsStandardURL_h__
|