tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsStandardURL.h (20629B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      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 
      6 #ifndef nsStandardURL_h__
      7 #define nsStandardURL_h__
      8 
      9 #include <bitset>
     10 
     11 #include "nsString.h"
     12 #include "nsISerializable.h"
     13 #include "nsIFileURL.h"
     14 #include "nsIStandardURL.h"
     15 #include "mozilla/Encoding.h"
     16 #include "nsCOMPtr.h"
     17 #include "nsURLHelper.h"
     18 #include "mozilla/Atomics.h"
     19 #include "mozilla/LinkedList.h"
     20 #include "nsISensitiveInfoHiddenURI.h"
     21 #include "nsIURIMutator.h"
     22 
     23 #ifdef NS_BUILD_REFCNT_LOGGING
     24 #  define DEBUG_DUMP_URLS_AT_SHUTDOWN
     25 #endif
     26 
     27 class nsIBinaryInputStream;
     28 class nsIBinaryOutputStream;
     29 class nsIIDNService;
     30 class nsIPrefBranch;
     31 class nsIFile;
     32 class nsIURLParser;
     33 
     34 namespace mozilla {
     35 class Encoding;
     36 namespace net {
     37 
     38 template <typename T>
     39 class URLSegmentNumber {
     40  T mData{0};
     41  bool mParity{false};
     42 
     43 public:
     44  URLSegmentNumber() = default;
     45  explicit URLSegmentNumber(T data) : mData(data) {
     46    mParity = CalculateParity();
     47  }
     48  bool operator==(URLSegmentNumber value) const { return mData == value.mData; }
     49  bool operator!=(URLSegmentNumber value) const { return mData != value.mData; }
     50  bool operator>(URLSegmentNumber value) const { return mData > value.mData; }
     51  URLSegmentNumber operator+(int32_t value) const {
     52    return URLSegmentNumber(mData + value);
     53  }
     54  URLSegmentNumber operator+(uint32_t value) const {
     55    return URLSegmentNumber(mData + value);
     56  }
     57  URLSegmentNumber operator-(int32_t value) const {
     58    return URLSegmentNumber(mData - value);
     59  }
     60  URLSegmentNumber operator-(uint32_t value) const {
     61    return URLSegmentNumber(mData - value);
     62  }
     63  URLSegmentNumber operator+=(URLSegmentNumber value) {
     64    mData += value.mData;
     65    mParity = CalculateParity();
     66    return *this;
     67  }
     68  URLSegmentNumber operator+=(T value) {
     69    mData += value;
     70    mParity = CalculateParity();
     71    return *this;
     72  }
     73  URLSegmentNumber operator-=(URLSegmentNumber value) {
     74    mData -= value.mData;
     75    mParity = CalculateParity();
     76    return *this;
     77  }
     78  URLSegmentNumber operator-=(T value) {
     79    mData -= value;
     80    mParity = CalculateParity();
     81    return *this;
     82  }
     83  operator T() const { return mData; }
     84  URLSegmentNumber& operator=(T value) {
     85    mData = value;
     86    mParity = CalculateParity();
     87    return *this;
     88  }
     89  URLSegmentNumber& operator++() {
     90    ++mData;
     91    mParity = CalculateParity();
     92    return *this;
     93  }
     94  URLSegmentNumber operator++(int) {
     95    URLSegmentNumber value = *this;
     96    *this += 1;
     97    return value;
     98  }
     99  bool CalculateParity() const {
    100    std::bitset<32> bits((uint32_t)mData);
    101    return bits.count() % 2 == 0 ? false : true;
    102  }
    103  bool Parity() const { return mParity; }
    104 };
    105 
    106 //-----------------------------------------------------------------------------
    107 // standard URL implementation
    108 //-----------------------------------------------------------------------------
    109 
    110 class nsStandardURL : public nsIFileURL,
    111                      public nsIStandardURL,
    112                      public nsISerializable,
    113                      public nsISensitiveInfoHiddenURI
    114 #ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN
    115    ,
    116                      public LinkedListElement<nsStandardURL>
    117 #endif
    118 {
    119 protected:
    120  virtual ~nsStandardURL();
    121  explicit nsStandardURL(bool aSupportsFileURL = false, bool aTrackURL = true);
    122 
    123 public:
    124  NS_DECL_THREADSAFE_ISUPPORTS
    125  NS_DECL_NSIURI
    126  NS_DECL_NSIURL
    127  NS_DECL_NSIFILEURL
    128  NS_DECL_NSISTANDARDURL
    129  NS_DECL_NSISERIALIZABLE
    130  NS_DECL_NSISENSITIVEINFOHIDDENURI
    131 
    132  static void InitGlobalObjects();
    133  static void ShutdownGlobalObjects();
    134 
    135  //
    136  // location and length of an url segment relative to mSpec
    137  //
    138  struct URLSegment {
    139 #ifdef EARLY_BETA_OR_EARLIER
    140    URLSegmentNumber<uint32_t> mPos{0};
    141    URLSegmentNumber<int32_t> mLen{-1};
    142 #else
    143    uint32_t mPos{0};
    144    int32_t mLen{-1};
    145 #endif
    146 
    147    URLSegment() = default;
    148    URLSegment(uint32_t pos, int32_t len) : mPos(pos), mLen(len) {}
    149    URLSegment(const URLSegment& aCopy) = default;
    150    void Reset() {
    151      mPos = 0;
    152      mLen = -1;
    153    }
    154    // Merge another segment following this one to it if they're contiguous
    155    // Assumes we have something like "foo;bar" where this object is 'foo' and
    156    // right is 'bar'.
    157    void Merge(const nsCString& spec, const char separator,
    158               const URLSegment& right) {
    159      if (mLen >= 0 && *(spec.get() + mPos + mLen) == separator &&
    160          mPos + mLen + 1 == right.mPos) {
    161        mLen += 1 + right.mLen;
    162      }
    163    }
    164  };
    165 
    166 public:
    167  //
    168  // URL segment encoder : performs charset conversion and URL escaping.
    169  //
    170  class nsSegmentEncoder {
    171   public:
    172    explicit nsSegmentEncoder(const Encoding* encoding = nullptr);
    173 
    174    // Encode the given segment if necessary, and return the length of
    175    // the encoded segment.  The encoded segment is appended to |aOut|
    176    // if and only if encoding is required.
    177    int32_t EncodeSegmentCount(const char* str, const URLSegment& aSeg,
    178                               int16_t mask, nsCString& aOut, bool& appended,
    179                               uint32_t extraLen = 0);
    180 
    181    // Encode the given string if necessary, and return a reference to
    182    // the encoded string.  Returns a reference to |result| if encoding
    183    // is required.  Otherwise, a reference to |str| is returned.
    184    const nsACString& EncodeSegment(const nsACString& str, int16_t mask,
    185                                    nsCString& result);
    186 
    187   private:
    188    const Encoding* mEncoding;
    189  };
    190  friend class nsSegmentEncoder;
    191 
    192  static nsIIDNService* GetIDNService();
    193 
    194 protected:
    195  // enum used in a few places to specify how .ref attribute should be handled
    196  enum RefHandlingEnum { eIgnoreRef, eHonorRef, eReplaceRef };
    197 
    198  // Helper to share code between Equals and EqualsExceptRef
    199  // NOTE: *not* virtual, because no one needs to override this so far...
    200  nsresult EqualsInternal(nsIURI* unknownOther, RefHandlingEnum refHandlingMode,
    201                          bool* result);
    202 
    203  virtual nsStandardURL* StartClone();
    204 
    205  // Helper to share code between Clone methods.
    206  nsresult CloneInternal(RefHandlingEnum aRefHandlingMode,
    207                         const nsACString& aNewRef, nsIURI** aClone);
    208  // Helper method that copies member variables from the source StandardURL
    209  // if copyCached = true, it will also copy mFile and mDisplayHost
    210  nsresult CopyMembers(nsStandardURL* source, RefHandlingEnum mode,
    211                       const nsACString& newRef, bool copyCached = false);
    212 
    213  // Helper for subclass implementation of GetFile().  Subclasses that map
    214  // URIs to files in a special way should implement this method.  It should
    215  // ensure that our mFile is initialized, if it's possible.
    216  // returns NS_ERROR_NO_INTERFACE if the url does not map to a file
    217  virtual nsresult EnsureFile();
    218 
    219  virtual nsresult Clone(nsIURI** aURI);
    220  virtual nsresult SetSpecInternal(const nsACString& input);
    221  virtual nsresult SetScheme(const nsACString& input);
    222  virtual nsresult SetUserPass(const nsACString& input);
    223  virtual nsresult SetUsername(const nsACString& input);
    224  virtual nsresult SetPassword(const nsACString& input);
    225  virtual nsresult SetHostPort(const nsACString& aValue);
    226  virtual nsresult SetHost(const nsACString& input);
    227  virtual nsresult SetPort(int32_t port);
    228  virtual nsresult SetPathQueryRef(const nsACString& input);
    229  virtual nsresult SetRef(const nsACString& input);
    230  virtual nsresult SetFilePath(const nsACString& input);
    231  virtual nsresult SetQuery(const nsACString& input);
    232  virtual nsresult SetQueryWithEncoding(const nsACString& input,
    233                                        const Encoding* encoding);
    234  bool Deserialize(const mozilla::ipc::URIParams&);
    235  nsresult ReadPrivate(nsIObjectInputStream* stream);
    236 
    237 private:
    238  nsresult Init(uint32_t urlType, int32_t defaultPort, const nsACString& spec,
    239                const char* charset, nsIURI* baseURI);
    240  nsresult SetDefaultPort(int32_t aNewDefaultPort);
    241  nsresult SetFile(nsIFile* file);
    242 
    243  nsresult SetFileNameInternal(const nsACString& input);
    244  nsresult SetFileBaseNameInternal(const nsACString& input);
    245  nsresult SetFileExtensionInternal(const nsACString& input);
    246 
    247  int32_t Port() { return mPort == -1 ? mDefaultPort : mPort; }
    248 
    249  void ReplacePortInSpec(int32_t aNewPort);
    250  void Clear();
    251  void InvalidateCache(bool invalidateCachedFile = true);
    252 
    253  static bool IsValidOfBase(unsigned char c, const uint32_t base);
    254  nsresult NormalizeIDN(const nsACString& aHost, nsACString& aResult);
    255  nsresult CheckIfHostIsAscii();
    256  void CoalescePath(char* path);
    257 
    258  uint32_t AppendSegmentToBuf(char*, uint32_t, const char*,
    259                              const URLSegment& input, URLSegment& output,
    260                              const nsCString* esc = nullptr,
    261                              bool useEsc = false, int32_t* diff = nullptr);
    262  uint32_t AppendToBuf(char*, uint32_t, const char*, uint32_t);
    263 
    264  nsresult BuildNormalizedSpec(const char* spec, const Encoding* encoding);
    265  nsresult SetSpecWithEncoding(const nsACString& input,
    266                               const Encoding* encoding);
    267 
    268  bool SegmentIs(const URLSegment& seg, const char* val,
    269                 bool ignoreCase = false);
    270  bool SegmentIs(const char* spec, const URLSegment& seg, const char* val,
    271                 bool ignoreCase = false);
    272  bool SegmentIs(const URLSegment& seg1, const char* val,
    273                 const URLSegment& seg2, bool ignoreCase = false);
    274 
    275  int32_t ReplaceSegment(uint32_t pos, uint32_t len, const char* val,
    276                         uint32_t valLen);
    277  int32_t ReplaceSegment(uint32_t pos, uint32_t len, const nsACString& val);
    278 
    279  nsresult ParseURL(const char* spec, int32_t specLen);
    280  nsresult ParsePath(const char* spec, uint32_t pathPos, int32_t pathLen = -1);
    281 
    282  char* AppendToSubstring(uint32_t pos, int32_t len, const char* tail);
    283 
    284  // dependent substring helpers
    285  nsDependentCSubstring Segment(uint32_t pos, int32_t len);  // see below
    286  nsDependentCSubstring Segment(const URLSegment& s) {
    287    return Segment(s.mPos, s.mLen);
    288  }
    289 
    290  // dependent substring getters
    291  nsDependentCSubstring Prepath();  // see below
    292  nsDependentCSubstring Scheme() { return Segment(mScheme); }
    293  nsDependentCSubstring Userpass(bool includeDelim = false);  // see below
    294  nsDependentCSubstring Username() { return Segment(mUsername); }
    295  nsDependentCSubstring Password() { return Segment(mPassword); }
    296  nsDependentCSubstring Hostport();  // see below
    297  nsDependentCSubstring Host();      // see below
    298  nsDependentCSubstring Path() { return Segment(mPath); }
    299  nsDependentCSubstring Filepath() { return Segment(mFilepath); }
    300  nsDependentCSubstring Directory() { return Segment(mDirectory); }
    301  nsDependentCSubstring Filename();  // see below
    302  nsDependentCSubstring Basename() { return Segment(mBasename); }
    303  nsDependentCSubstring Extension() { return Segment(mExtension); }
    304  nsDependentCSubstring Query() { return Segment(mQuery); }
    305  nsDependentCSubstring Ref() { return Segment(mRef); }
    306 
    307  // shift the URLSegments to the right by diff
    308  void ShiftFromAuthority(int32_t diff);
    309  void ShiftFromUsername(int32_t diff);
    310  void ShiftFromPassword(int32_t diff);
    311  void ShiftFromHost(int32_t diff);
    312  void ShiftFromPath(int32_t diff);
    313  void ShiftFromFilepath(int32_t diff);
    314  void ShiftFromDirectory(int32_t diff);
    315  void ShiftFromBasename(int32_t diff);
    316  void ShiftFromExtension(int32_t diff);
    317  void ShiftFromQuery(int32_t diff);
    318  void ShiftFromRef(int32_t diff);
    319 
    320  // fastload helper functions
    321  nsresult ReadSegment(nsIBinaryInputStream*, URLSegment&);
    322  nsresult WriteSegment(nsIBinaryOutputStream*, const URLSegment&);
    323 
    324  void FindHostLimit(nsACString::const_iterator& aStart,
    325                     nsACString::const_iterator& aEnd);
    326 
    327  // Asserts that the URL has sane values
    328  void SanityCheck();
    329 
    330  // Checks if the URL has a valid representation.
    331  bool IsValid();
    332 
    333  // This value will only be updated on the main thread once.
    334  static Atomic<bool, Relaxed> gInitialized;
    335 
    336  // mSpec contains the normalized version of the URL spec (UTF-8 encoded).
    337  nsCString mSpec;
    338  int32_t mDefaultPort{-1};
    339  int32_t mPort{-1};
    340 
    341  // url parts (relative to mSpec)
    342  URLSegment mScheme;
    343  URLSegment mAuthority;
    344  URLSegment mUsername;
    345  URLSegment mPassword;
    346  URLSegment mHost;
    347  URLSegment mPath;
    348  URLSegment mFilepath;
    349  URLSegment mDirectory;
    350  URLSegment mBasename;
    351  URLSegment mExtension;
    352  URLSegment mQuery;
    353  URLSegment mRef;
    354 
    355  nsCOMPtr<nsIURLParser> mParser;
    356 
    357  // mFile is protected so subclasses can access it directly
    358 protected:
    359  nsCOMPtr<nsIFile> mFile;  // cached result for nsIFileURL::GetFile
    360 
    361 private:
    362  // cached result for nsIURI::GetDisplayHost
    363  nsCString mDisplayHost;
    364 
    365  enum { eEncoding_Unknown, eEncoding_ASCII, eEncoding_UTF8 };
    366 
    367  uint32_t mURLType : 2;          // nsIStandardURL::URLTYPE_xxx
    368  uint32_t mSupportsFileURL : 1;  // QI to nsIFileURL?
    369  uint32_t mCheckedIfHostA : 1;   // If set to true, it means either that
    370                                  // mDisplayHost has a been initialized, or
    371                                  // that the hostname is not punycode
    372 
    373  // global objects.
    374  static StaticRefPtr<nsIIDNService> gIDN;
    375  static const char gHostLimitDigits[];
    376 
    377 public:
    378 #ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN
    379  void PrintSpec() const { printf("  %s\n", mSpec.get()); }
    380 #endif
    381 
    382 public:
    383  // We make this implementation a template so that we can avoid writing
    384  // the same code for SubstitutingURL (which extends nsStandardURL)
    385  template <class T>
    386  class TemplatedMutator : public nsIURIMutator,
    387                           public BaseURIMutator<T>,
    388                           public nsIStandardURLMutator,
    389                           public nsIURLMutator,
    390                           public nsIFileURLMutator,
    391                           public nsISerializable {
    392    NS_FORWARD_SAFE_NSIURISETTERS_RET(BaseURIMutator<T>::mURI)
    393 
    394    [[nodiscard]] NS_IMETHOD Deserialize(
    395        const mozilla::ipc::URIParams& aParams) override {
    396      return BaseURIMutator<T>::InitFromIPCParams(aParams);
    397    }
    398 
    399    NS_IMETHOD
    400    Write(nsIObjectOutputStream* aOutputStream) override {
    401      MOZ_ASSERT_UNREACHABLE("Use nsIURIMutator.read() instead");
    402      return NS_ERROR_NOT_IMPLEMENTED;
    403    }
    404 
    405    [[nodiscard]] NS_IMETHOD Read(nsIObjectInputStream* aStream) override {
    406      return BaseURIMutator<T>::InitFromInputStream(aStream);
    407    }
    408 
    409    [[nodiscard]] NS_IMETHOD Finalize(nsIURI** aURI) override {
    410      BaseURIMutator<T>::mURI.forget(aURI);
    411      return NS_OK;
    412    }
    413 
    414    [[nodiscard]] NS_IMETHOD SetSpec(const nsACString& aSpec,
    415                                     nsIURIMutator** aMutator) override {
    416      if (aMutator) {
    417        nsCOMPtr<nsIURIMutator> mutator = this;
    418        mutator.forget(aMutator);
    419      }
    420      return BaseURIMutator<T>::InitFromSpec(aSpec);
    421    }
    422 
    423    [[nodiscard]] NS_IMETHOD Init(uint32_t aURLType, int32_t aDefaultPort,
    424                                  const nsACString& aSpec, const char* aCharset,
    425                                  nsIURI* aBaseURI,
    426                                  nsIURIMutator** aMutator) override {
    427      if (aMutator) {
    428        nsCOMPtr<nsIURIMutator> mutator = this;
    429        mutator.forget(aMutator);
    430      }
    431      RefPtr<T> uri;
    432      if (BaseURIMutator<T>::mURI) {
    433        // We don't need a new URI object if we already have one
    434        BaseURIMutator<T>::mURI.swap(uri);
    435      } else {
    436        uri = Create();
    437      }
    438      nsresult rv =
    439          uri->Init(aURLType, aDefaultPort, aSpec, aCharset, aBaseURI);
    440      if (NS_FAILED(rv)) {
    441        return rv;
    442      }
    443      BaseURIMutator<T>::mURI = std::move(uri);
    444      return NS_OK;
    445    }
    446 
    447    [[nodiscard]] NS_IMETHODIMP SetDefaultPort(
    448        int32_t aNewDefaultPort, nsIURIMutator** aMutator) override {
    449      if (!BaseURIMutator<T>::mURI) {
    450        return NS_ERROR_NULL_POINTER;
    451      }
    452      if (aMutator) {
    453        nsCOMPtr<nsIURIMutator> mutator = this;
    454        mutator.forget(aMutator);
    455      }
    456      return BaseURIMutator<T>::mURI->SetDefaultPort(aNewDefaultPort);
    457    }
    458 
    459    [[nodiscard]] NS_IMETHOD SetFileName(const nsACString& aFileName,
    460                                         nsIURIMutator** aMutator) override {
    461      if (!BaseURIMutator<T>::mURI) {
    462        return NS_ERROR_NULL_POINTER;
    463      }
    464      if (aMutator) {
    465        nsCOMPtr<nsIURIMutator> mutator = this;
    466        mutator.forget(aMutator);
    467      }
    468      return BaseURIMutator<T>::mURI->SetFileNameInternal(aFileName);
    469    }
    470 
    471    [[nodiscard]] NS_IMETHOD SetFileBaseName(
    472        const nsACString& aFileBaseName, nsIURIMutator** aMutator) override {
    473      if (!BaseURIMutator<T>::mURI) {
    474        return NS_ERROR_NULL_POINTER;
    475      }
    476      if (aMutator) {
    477        nsCOMPtr<nsIURIMutator> mutator = this;
    478        mutator.forget(aMutator);
    479      }
    480      return BaseURIMutator<T>::mURI->SetFileBaseNameInternal(aFileBaseName);
    481    }
    482 
    483    [[nodiscard]] NS_IMETHOD SetFileExtension(
    484        const nsACString& aFileExtension, nsIURIMutator** aMutator) override {
    485      if (!BaseURIMutator<T>::mURI) {
    486        return NS_ERROR_NULL_POINTER;
    487      }
    488      if (aMutator) {
    489        nsCOMPtr<nsIURIMutator> mutator = this;
    490        mutator.forget(aMutator);
    491      }
    492      return BaseURIMutator<T>::mURI->SetFileExtensionInternal(aFileExtension);
    493    }
    494 
    495    T* Create() override { return new T(mMarkedFileURL); }
    496 
    497    [[nodiscard]] NS_IMETHOD MarkFileURL() override {
    498      mMarkedFileURL = true;
    499      return NS_OK;
    500    }
    501 
    502    [[nodiscard]] NS_IMETHOD SetFile(nsIFile* aFile) override {
    503      RefPtr<T> uri;
    504      if (BaseURIMutator<T>::mURI) {
    505        // We don't need a new URI object if we already have one
    506        BaseURIMutator<T>::mURI.swap(uri);
    507      } else {
    508        uri = new T(/* aSupportsFileURL = */ true);
    509      }
    510 
    511      nsresult rv = uri->SetFile(aFile);
    512      if (NS_FAILED(rv)) {
    513        return rv;
    514      }
    515      BaseURIMutator<T>::mURI.swap(uri);
    516      return NS_OK;
    517    }
    518 
    519    explicit TemplatedMutator() = default;
    520 
    521   private:
    522    virtual ~TemplatedMutator() = default;
    523 
    524    bool mMarkedFileURL = false;
    525 
    526    friend T;
    527  };
    528 
    529  class Mutator final : public TemplatedMutator<nsStandardURL> {
    530    NS_DECL_ISUPPORTS
    531   public:
    532    explicit Mutator() = default;
    533 
    534   private:
    535    virtual ~Mutator() = default;
    536  };
    537 
    538  friend BaseURIMutator<nsStandardURL>;
    539 };
    540 
    541 #define NS_THIS_STANDARDURL_IMPL_CID          \
    542  {/* b8e3e97b-1ccd-4b45-af5a-79596770f5d7 */ \
    543   0xb8e3e97b,                                \
    544   0x1ccd,                                    \
    545   0x4b45,                                    \
    546   {0xaf, 0x5a, 0x79, 0x59, 0x67, 0x70, 0xf5, 0xd7}}
    547 
    548 //-----------------------------------------------------------------------------
    549 // Dependent substring getters
    550 //-----------------------------------------------------------------------------
    551 
    552 inline nsDependentCSubstring nsStandardURL::Segment(uint32_t pos, int32_t len) {
    553  if (len < 0) {
    554    pos = 0;
    555    len = 0;
    556  }
    557  return Substring(mSpec, pos, uint32_t(len));
    558 }
    559 
    560 inline nsDependentCSubstring nsStandardURL::Prepath() {
    561  uint32_t len = 0;
    562  if (mAuthority.mLen >= 0) len = mAuthority.mPos + mAuthority.mLen;
    563  return Substring(mSpec, 0, len);
    564 }
    565 
    566 inline nsDependentCSubstring nsStandardURL::Userpass(bool includeDelim) {
    567  uint32_t pos = 0, len = 0;
    568  if (mUsername.mLen > 0 || mPassword.mLen > 0) {
    569    if (mUsername.mLen > 0) {
    570      pos = mUsername.mPos;
    571      len = mUsername.mLen;
    572      if (mPassword.mLen >= 0) {
    573        len += (mPassword.mLen + 1);
    574      }
    575    } else {
    576      pos = mPassword.mPos - 1;
    577      len = mPassword.mLen + 1;
    578    }
    579 
    580    if (includeDelim) len++;
    581  }
    582  return Substring(mSpec, pos, len);
    583 }
    584 
    585 inline nsDependentCSubstring nsStandardURL::Hostport() {
    586  uint32_t pos = 0, len = 0;
    587  if (mAuthority.mLen > 0) {
    588    pos = mHost.mPos;
    589    len = mAuthority.mPos + mAuthority.mLen - pos;
    590  }
    591  return Substring(mSpec, pos, len);
    592 }
    593 
    594 inline nsDependentCSubstring nsStandardURL::Host() {
    595  uint32_t pos = 0, len = 0;
    596  if (mHost.mLen > 0) {
    597    pos = mHost.mPos;
    598    len = mHost.mLen;
    599    if (mSpec.CharAt(pos) == '[' && mSpec.CharAt(pos + len - 1) == ']') {
    600      pos++;
    601      len -= 2;
    602    }
    603  }
    604  return Substring(mSpec, pos, len);
    605 }
    606 
    607 inline nsDependentCSubstring nsStandardURL::Filename() {
    608  uint32_t pos = 0, len = 0;
    609  // if there is no basename, then there can be no extension
    610  if (mBasename.mLen > 0) {
    611    pos = mBasename.mPos;
    612    len = mBasename.mLen;
    613    if (mExtension.mLen >= 0) len += (mExtension.mLen + 1);
    614  }
    615  return Substring(mSpec, pos, len);
    616 }
    617 
    618 }  // namespace net
    619 }  // namespace mozilla
    620 
    621 #endif  // nsStandardURL_h__