netwerk/base/src/nsStandardURL.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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__

mercurial