netwerk/base/src/nsStandardURL.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/netwerk/base/src/nsStandardURL.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,378 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef nsStandardURL_h__
    1.10 +#define nsStandardURL_h__
    1.11 +
    1.12 +#include "nsString.h"
    1.13 +#include "nsISerializable.h"
    1.14 +#include "nsIFileURL.h"
    1.15 +#include "nsIStandardURL.h"
    1.16 +#include "nsIUnicodeEncoder.h"
    1.17 +#include "nsIObserver.h"
    1.18 +#include "nsCOMPtr.h"
    1.19 +#include "nsURLHelper.h"
    1.20 +#include "nsIClassInfo.h"
    1.21 +#include "nsISizeOf.h"
    1.22 +#include "prclist.h"
    1.23 +#include "mozilla/Attributes.h"
    1.24 +#include "mozilla/MemoryReporting.h"
    1.25 +#include "nsIIPCSerializableURI.h"
    1.26 +
    1.27 +#ifdef NS_BUILD_REFCNT_LOGGING
    1.28 +#define DEBUG_DUMP_URLS_AT_SHUTDOWN
    1.29 +#endif
    1.30 +
    1.31 +class nsIBinaryInputStream;
    1.32 +class nsIBinaryOutputStream;
    1.33 +class nsIIDNService;
    1.34 +class nsICharsetConverterManager;
    1.35 +class nsIPrefBranch;
    1.36 +class nsIFile;
    1.37 +class nsIURLParser;
    1.38 +
    1.39 +//-----------------------------------------------------------------------------
    1.40 +// standard URL implementation
    1.41 +//-----------------------------------------------------------------------------
    1.42 +
    1.43 +class nsStandardURL : public nsIFileURL
    1.44 +                    , public nsIStandardURL
    1.45 +                    , public nsISerializable
    1.46 +                    , public nsIClassInfo
    1.47 +                    , public nsISizeOf
    1.48 +                    , public nsIIPCSerializableURI
    1.49 +{
    1.50 +public:
    1.51 +    NS_DECL_ISUPPORTS
    1.52 +    NS_DECL_NSIURI
    1.53 +    NS_DECL_NSIURL
    1.54 +    NS_DECL_NSIFILEURL
    1.55 +    NS_DECL_NSISTANDARDURL
    1.56 +    NS_DECL_NSISERIALIZABLE
    1.57 +    NS_DECL_NSICLASSINFO
    1.58 +    NS_DECL_NSIMUTABLE
    1.59 +    NS_DECL_NSIIPCSERIALIZABLEURI
    1.60 +
    1.61 +    // nsISizeOf
    1.62 +    virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
    1.63 +    virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
    1.64 +
    1.65 +    nsStandardURL(bool aSupportsFileURL = false);
    1.66 +    virtual ~nsStandardURL();
    1.67 +
    1.68 +    static void InitGlobalObjects();
    1.69 +    static void ShutdownGlobalObjects();
    1.70 +
    1.71 +public: /* internal -- HPUX compiler can't handle this being private */
    1.72 +    //
    1.73 +    // location and length of an url segment relative to mSpec
    1.74 +    //
    1.75 +    struct URLSegment
    1.76 +    {
    1.77 +        uint32_t mPos;
    1.78 +        int32_t  mLen;
    1.79 +
    1.80 +        URLSegment() : mPos(0), mLen(-1) {}
    1.81 +        URLSegment(uint32_t pos, int32_t len) : mPos(pos), mLen(len) {}
    1.82 +        void Reset() { mPos = 0; mLen = -1; }
    1.83 +        // Merge another segment following this one to it if they're contiguous
    1.84 +        // Assumes we have something like "foo;bar" where this object is 'foo' and right
    1.85 +        // is 'bar'.
    1.86 +        void Merge(const nsCString &spec, const char separator, const URLSegment &right) {
    1.87 +            if (mLen >= 0 && 
    1.88 +                *(spec.get() + mPos + mLen) == separator &&
    1.89 +                mPos + mLen + 1 == right.mPos) {
    1.90 +                mLen += 1 + right.mLen;
    1.91 +            }
    1.92 +        }
    1.93 +    };
    1.94 +
    1.95 +    //
    1.96 +    // Pref observer
    1.97 +    //
    1.98 +    class nsPrefObserver MOZ_FINAL : public nsIObserver
    1.99 +    {
   1.100 +    public:
   1.101 +        NS_DECL_ISUPPORTS
   1.102 +        NS_DECL_NSIOBSERVER
   1.103 +
   1.104 +        nsPrefObserver() { }
   1.105 +    };
   1.106 +    friend class nsPrefObserver;
   1.107 +
   1.108 +    //
   1.109 +    // URL segment encoder : performs charset conversion and URL escaping.
   1.110 +    //
   1.111 +    class nsSegmentEncoder
   1.112 +    {
   1.113 +    public:
   1.114 +        nsSegmentEncoder(const char *charset);
   1.115 +
   1.116 +        // Encode the given segment if necessary, and return the length of
   1.117 +        // the encoded segment.  The encoded segment is appended to |buf|
   1.118 +        // if and only if encoding is required.
   1.119 +        int32_t EncodeSegmentCount(const char *str,
   1.120 +                                   const URLSegment &segment,
   1.121 +                                   int16_t mask,
   1.122 +                                   nsAFlatCString &buf,
   1.123 +                                   bool& appended,
   1.124 +                                   uint32_t extraLen = 0);
   1.125 +         
   1.126 +        // Encode the given string if necessary, and return a reference to
   1.127 +        // the encoded string.  Returns a reference to |buf| if encoding
   1.128 +        // is required.  Otherwise, a reference to |str| is returned.
   1.129 +        const nsACString &EncodeSegment(const nsASingleFragmentCString &str,
   1.130 +                                        int16_t mask,
   1.131 +                                        nsAFlatCString &buf);
   1.132 +    private:
   1.133 +        bool InitUnicodeEncoder();
   1.134 +        
   1.135 +        const char* mCharset;  // Caller should keep this alive for
   1.136 +                               // the life of the segment encoder
   1.137 +        nsCOMPtr<nsIUnicodeEncoder> mEncoder;
   1.138 +    };
   1.139 +    friend class nsSegmentEncoder;
   1.140 +
   1.141 +protected:
   1.142 +    // enum used in a few places to specify how .ref attribute should be handled
   1.143 +    enum RefHandlingEnum {
   1.144 +        eIgnoreRef,
   1.145 +        eHonorRef
   1.146 +    };
   1.147 +
   1.148 +    // Helper to share code between Equals and EqualsExceptRef
   1.149 +    // NOTE: *not* virtual, because no one needs to override this so far...
   1.150 +    nsresult EqualsInternal(nsIURI* unknownOther,
   1.151 +                            RefHandlingEnum refHandlingMode,
   1.152 +                            bool* result);
   1.153 +
   1.154 +    virtual nsStandardURL* StartClone();
   1.155 +
   1.156 +    // Helper to share code between Clone methods.
   1.157 +    nsresult CloneInternal(RefHandlingEnum aRefHandlingMode,
   1.158 +                           nsIURI** aClone);
   1.159 +
   1.160 +    // Helper for subclass implementation of GetFile().  Subclasses that map
   1.161 +    // URIs to files in a special way should implement this method.  It should
   1.162 +    // ensure that our mFile is initialized, if it's possible.
   1.163 +    // returns NS_ERROR_NO_INTERFACE if the url does not map to a file
   1.164 +    virtual nsresult EnsureFile();
   1.165 +
   1.166 +private:
   1.167 +    int32_t  Port() { return mPort == -1 ? mDefaultPort : mPort; }
   1.168 +
   1.169 +    void     Clear();
   1.170 +    void     InvalidateCache(bool invalidateCachedFile = true);
   1.171 +
   1.172 +    bool     EscapeIPv6(const char *host, nsCString &result);
   1.173 +    bool     NormalizeIDN(const nsCSubstring &host, nsCString &result);
   1.174 +    void     CoalescePath(netCoalesceFlags coalesceFlag, char *path);
   1.175 +
   1.176 +    uint32_t AppendSegmentToBuf(char *, uint32_t, const char *, URLSegment &, const nsCString *esc=nullptr, bool useEsc = false);
   1.177 +    uint32_t AppendToBuf(char *, uint32_t, const char *, uint32_t);
   1.178 +
   1.179 +    nsresult BuildNormalizedSpec(const char *spec);
   1.180 +
   1.181 +    bool     SegmentIs(const URLSegment &s1, const char *val, bool ignoreCase = false);
   1.182 +    bool     SegmentIs(const char* spec, const URLSegment &s1, const char *val, bool ignoreCase = false);
   1.183 +    bool     SegmentIs(const URLSegment &s1, const char *val, const URLSegment &s2, bool ignoreCase = false);
   1.184 +
   1.185 +    int32_t  ReplaceSegment(uint32_t pos, uint32_t len, const char *val, uint32_t valLen);
   1.186 +    int32_t  ReplaceSegment(uint32_t pos, uint32_t len, const nsACString &val);
   1.187 +
   1.188 +    nsresult ParseURL(const char *spec, int32_t specLen);
   1.189 +    nsresult ParsePath(const char *spec, uint32_t pathPos, int32_t pathLen = -1);
   1.190 +
   1.191 +    char    *AppendToSubstring(uint32_t pos, int32_t len, const char *tail);
   1.192 +
   1.193 +    // dependent substring helpers
   1.194 +    const nsDependentCSubstring Segment(uint32_t pos, int32_t len); // see below
   1.195 +    const nsDependentCSubstring Segment(const URLSegment &s) { return Segment(s.mPos, s.mLen); }
   1.196 +
   1.197 +    // dependent substring getters
   1.198 +    const nsDependentCSubstring Prepath();  // see below
   1.199 +    const nsDependentCSubstring Scheme()    { return Segment(mScheme); }
   1.200 +    const nsDependentCSubstring Userpass(bool includeDelim = false); // see below
   1.201 +    const nsDependentCSubstring Username()  { return Segment(mUsername); }
   1.202 +    const nsDependentCSubstring Password()  { return Segment(mPassword); }
   1.203 +    const nsDependentCSubstring Hostport(); // see below
   1.204 +    const nsDependentCSubstring Host();     // see below
   1.205 +    const nsDependentCSubstring Path()      { return Segment(mPath); }
   1.206 +    const nsDependentCSubstring Filepath()  { return Segment(mFilepath); }
   1.207 +    const nsDependentCSubstring Directory() { return Segment(mDirectory); }
   1.208 +    const nsDependentCSubstring Filename(); // see below
   1.209 +    const nsDependentCSubstring Basename()  { return Segment(mBasename); }
   1.210 +    const nsDependentCSubstring Extension() { return Segment(mExtension); }
   1.211 +    const nsDependentCSubstring Query()     { return Segment(mQuery); }
   1.212 +    const nsDependentCSubstring Ref()       { return Segment(mRef); }
   1.213 +
   1.214 +    // shift the URLSegments to the right by diff
   1.215 +    void ShiftFromAuthority(int32_t diff) { mAuthority.mPos += diff; ShiftFromUsername(diff); }
   1.216 +    void ShiftFromUsername(int32_t diff)  { mUsername.mPos += diff; ShiftFromPassword(diff); }
   1.217 +    void ShiftFromPassword(int32_t diff)  { mPassword.mPos += diff; ShiftFromHost(diff); }
   1.218 +    void ShiftFromHost(int32_t diff)      { mHost.mPos += diff; ShiftFromPath(diff); }
   1.219 +    void ShiftFromPath(int32_t diff)      { mPath.mPos += diff; ShiftFromFilepath(diff); }
   1.220 +    void ShiftFromFilepath(int32_t diff)  { mFilepath.mPos += diff; ShiftFromDirectory(diff); }
   1.221 +    void ShiftFromDirectory(int32_t diff) { mDirectory.mPos += diff; ShiftFromBasename(diff); }
   1.222 +    void ShiftFromBasename(int32_t diff)  { mBasename.mPos += diff; ShiftFromExtension(diff); }
   1.223 +    void ShiftFromExtension(int32_t diff) { mExtension.mPos += diff; ShiftFromQuery(diff); }
   1.224 +    void ShiftFromQuery(int32_t diff)     { mQuery.mPos += diff; ShiftFromRef(diff); }
   1.225 +    void ShiftFromRef(int32_t diff)       { mRef.mPos += diff; }
   1.226 +
   1.227 +    // fastload helper functions
   1.228 +    nsresult ReadSegment(nsIBinaryInputStream *, URLSegment &);
   1.229 +    nsresult WriteSegment(nsIBinaryOutputStream *, const URLSegment &);
   1.230 +
   1.231 +    static void PrefsChanged(nsIPrefBranch *prefs, const char *pref);
   1.232 +
   1.233 +    void FindHostLimit(nsACString::const_iterator& aStart,
   1.234 +                       nsACString::const_iterator& aEnd);
   1.235 +
   1.236 +    // mSpec contains the normalized version of the URL spec (UTF-8 encoded).
   1.237 +    nsCString mSpec;
   1.238 +    int32_t   mDefaultPort;
   1.239 +    int32_t   mPort;
   1.240 +
   1.241 +    // url parts (relative to mSpec)
   1.242 +    URLSegment mScheme;
   1.243 +    URLSegment mAuthority;
   1.244 +    URLSegment mUsername;
   1.245 +    URLSegment mPassword;
   1.246 +    URLSegment mHost;
   1.247 +    URLSegment mPath;
   1.248 +    URLSegment mFilepath;
   1.249 +    URLSegment mDirectory;
   1.250 +    URLSegment mBasename;
   1.251 +    URLSegment mExtension;
   1.252 +    URLSegment mQuery;
   1.253 +    URLSegment mRef;
   1.254 +
   1.255 +    nsCString              mOriginCharset;
   1.256 +    nsCOMPtr<nsIURLParser> mParser;
   1.257 +
   1.258 +    // mFile is protected so subclasses can access it directly
   1.259 +protected:
   1.260 +    nsCOMPtr<nsIFile>      mFile;  // cached result for nsIFileURL::GetFile
   1.261 +    
   1.262 +private:
   1.263 +    char                  *mHostA; // cached result for nsIURI::GetHostA
   1.264 +
   1.265 +    enum {
   1.266 +        eEncoding_Unknown,
   1.267 +        eEncoding_ASCII,
   1.268 +        eEncoding_UTF8
   1.269 +    };
   1.270 +
   1.271 +    uint32_t mHostEncoding    : 2; // eEncoding_xxx
   1.272 +    uint32_t mSpecEncoding    : 2; // eEncoding_xxx
   1.273 +    uint32_t mURLType         : 2; // nsIStandardURL::URLTYPE_xxx
   1.274 +    uint32_t mMutable         : 1; // nsIStandardURL::mutable
   1.275 +    uint32_t mSupportsFileURL : 1; // QI to nsIFileURL?
   1.276 +
   1.277 +    // global objects.  don't use COMPtr as its destructor will cause a
   1.278 +    // coredump if we leak it.
   1.279 +    static nsIIDNService               *gIDN;
   1.280 +    static char                         gHostLimitDigits[];
   1.281 +    static nsICharsetConverterManager  *gCharsetMgr;
   1.282 +    static bool                         gInitialized;
   1.283 +    static bool                         gEscapeUTF8;
   1.284 +    static bool                         gAlwaysEncodeInUTF8;
   1.285 +    static bool                         gEncodeQueryInUTF8;
   1.286 +
   1.287 +public:
   1.288 +#ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN
   1.289 +    PRCList mDebugCList;
   1.290 +    void PrintSpec() const { printf("  %s\n", mSpec.get()); }
   1.291 +#endif
   1.292 +};
   1.293 +
   1.294 +#define NS_THIS_STANDARDURL_IMPL_CID                 \
   1.295 +{ /* b8e3e97b-1ccd-4b45-af5a-79596770f5d7 */         \
   1.296 +    0xb8e3e97b,                                      \
   1.297 +    0x1ccd,                                          \
   1.298 +    0x4b45,                                          \
   1.299 +    {0xaf, 0x5a, 0x79, 0x59, 0x67, 0x70, 0xf5, 0xd7} \
   1.300 +}
   1.301 +
   1.302 +//-----------------------------------------------------------------------------
   1.303 +// Dependent substring getters
   1.304 +//-----------------------------------------------------------------------------
   1.305 +
   1.306 +inline const nsDependentCSubstring
   1.307 +nsStandardURL::Segment(uint32_t pos, int32_t len)
   1.308 +{
   1.309 +    if (len < 0) {
   1.310 +        pos = 0;
   1.311 +        len = 0;
   1.312 +    }
   1.313 +    return Substring(mSpec, pos, uint32_t(len));
   1.314 +}
   1.315 +
   1.316 +inline const nsDependentCSubstring
   1.317 +nsStandardURL::Prepath()
   1.318 +{
   1.319 +    uint32_t len = 0;
   1.320 +    if (mAuthority.mLen >= 0)
   1.321 +        len = mAuthority.mPos + mAuthority.mLen;
   1.322 +    return Substring(mSpec, 0, len);
   1.323 +}
   1.324 +
   1.325 +inline const nsDependentCSubstring
   1.326 +nsStandardURL::Userpass(bool includeDelim)
   1.327 +{
   1.328 +    uint32_t pos=0, len=0;
   1.329 +    // if there is no username, then there can be no password
   1.330 +    if (mUsername.mLen > 0) {
   1.331 +        pos = mUsername.mPos;
   1.332 +        len = mUsername.mLen;
   1.333 +        if (mPassword.mLen >= 0)
   1.334 +            len += (mPassword.mLen + 1);
   1.335 +        if (includeDelim)
   1.336 +            len++;
   1.337 +    }
   1.338 +    return Substring(mSpec, pos, len);
   1.339 +}
   1.340 +
   1.341 +inline const nsDependentCSubstring
   1.342 +nsStandardURL::Hostport()
   1.343 +{
   1.344 +    uint32_t pos=0, len=0;
   1.345 +    if (mAuthority.mLen > 0) {
   1.346 +        pos = mHost.mPos;
   1.347 +        len = mAuthority.mPos + mAuthority.mLen - pos;
   1.348 +    }
   1.349 +    return Substring(mSpec, pos, len);
   1.350 +}
   1.351 +
   1.352 +inline const nsDependentCSubstring
   1.353 +nsStandardURL::Host()
   1.354 +{
   1.355 +    uint32_t pos=0, len=0;
   1.356 +    if (mHost.mLen > 0) {
   1.357 +        pos = mHost.mPos;
   1.358 +        len = mHost.mLen;
   1.359 +        if (mSpec.CharAt(pos) == '[' && mSpec.CharAt(pos + len - 1) == ']') {
   1.360 +            pos++;
   1.361 +            len -= 2;
   1.362 +        }
   1.363 +    }
   1.364 +    return Substring(mSpec, pos, len);
   1.365 +}
   1.366 +
   1.367 +inline const nsDependentCSubstring
   1.368 +nsStandardURL::Filename()
   1.369 +{
   1.370 +    uint32_t pos=0, len=0;
   1.371 +    // if there is no basename, then there can be no extension
   1.372 +    if (mBasename.mLen > 0) {
   1.373 +        pos = mBasename.mPos;
   1.374 +        len = mBasename.mLen;
   1.375 +        if (mExtension.mLen >= 0)
   1.376 +            len += (mExtension.mLen + 1);
   1.377 +    }
   1.378 +    return Substring(mSpec, pos, len);
   1.379 +}
   1.380 +
   1.381 +#endif // nsStandardURL_h__

mercurial