summaryrefslogtreecommitdiffstats
path: root/netwerk/base/nsStandardURL.h
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/base/nsStandardURL.h')
-rw-r--r--netwerk/base/nsStandardURL.h405
1 files changed, 405 insertions, 0 deletions
diff --git a/netwerk/base/nsStandardURL.h b/netwerk/base/nsStandardURL.h
new file mode 100644
index 000000000..90f7f7db2
--- /dev/null
+++ b/netwerk/base/nsStandardURL.h
@@ -0,0 +1,405 @@
+/* -*- 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_NSIURIWITHQUERY
+ 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();
+
+public: /* internal -- HPUX compiler can't handle this being private */
+ //
+ // 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);
+
+ // 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__