From d6a205f1ecdceba6a4574d84a47a645fb49609d7 Mon Sep 17 00:00:00 2001 From: "warren%netscape.com" Date: Fri, 14 Jan 2000 08:50:03 +0000 Subject: [PATCH] Changes from andreas.otte@primus-online.de for numerous URL parsing bugs. r=warren --- content/html/style/src/nsCSSLoader.cpp | 2 +- layout/html/style/src/nsCSSLoader.cpp | 2 +- layout/style/nsCSSLoader.cpp | 2 +- mailnews/base/util/nsMsgMailNewsUrl.cpp | 40 +- mailnews/compose/src/nsSmtpUrl.cpp | 30 + modules/libjar/nsJARURI.cpp | 36 + netwerk/base/public/Makefile.in | 1 + netwerk/base/public/makefile.win | 5 +- netwerk/base/public/nsIIOService.idl | 26 + netwerk/base/public/nsIURI.idl | 11 + netwerk/base/src/Makefile.in | 10 +- netwerk/base/src/makefile.win | 9 + netwerk/base/src/nsIOService.cpp | 12 + netwerk/base/src/nsIOService.h | 1 + netwerk/base/src/nsSimpleURI.cpp | 40 +- netwerk/base/src/nsStdURL.cpp | 1309 ++++++----------- netwerk/base/src/nsStdURL.h | 222 ++- netwerk/build/nsNetModule.cpp | 18 +- netwerk/macbuild/netwerk.mcp | Bin 63272 -> 63272 bytes netwerk/macbuild/netwerkIDL.mcp | Bin 45908 -> 45908 bytes .../file/src/nsFileProtocolHandler.cpp | 26 +- .../protocol/ftp/src/nsFtpProtocolHandler.cpp | 26 +- netwerk/protocol/http/src/nsHTTPHandler.cpp | 19 +- netwerk/protocol/jar/src/nsJARURI.cpp | 36 + netwerk/protocol/res/src/nsResChannel.cpp | 2 +- rdf/base/src/nsRDFXMLDataSource.cpp | 2 +- 26 files changed, 904 insertions(+), 983 deletions(-) diff --git a/content/html/style/src/nsCSSLoader.cpp b/content/html/style/src/nsCSSLoader.cpp index 68dd1d5de00..60ae879146f 100644 --- a/content/html/style/src/nsCSSLoader.cpp +++ b/content/html/style/src/nsCSSLoader.cpp @@ -66,7 +66,7 @@ public: NS_ADDREF(mURL); mHashValue = 0; - char* urlStr; + char* urlStr = nsnull; mURL->GetSpec(&urlStr); if (urlStr) { mHashValue = nsCRT::HashValue(urlStr); diff --git a/layout/html/style/src/nsCSSLoader.cpp b/layout/html/style/src/nsCSSLoader.cpp index 68dd1d5de00..60ae879146f 100644 --- a/layout/html/style/src/nsCSSLoader.cpp +++ b/layout/html/style/src/nsCSSLoader.cpp @@ -66,7 +66,7 @@ public: NS_ADDREF(mURL); mHashValue = 0; - char* urlStr; + char* urlStr = nsnull; mURL->GetSpec(&urlStr); if (urlStr) { mHashValue = nsCRT::HashValue(urlStr); diff --git a/layout/style/nsCSSLoader.cpp b/layout/style/nsCSSLoader.cpp index 68dd1d5de00..60ae879146f 100644 --- a/layout/style/nsCSSLoader.cpp +++ b/layout/style/nsCSSLoader.cpp @@ -66,7 +66,7 @@ public: NS_ADDREF(mURL); mHashValue = 0; - char* urlStr; + char* urlStr = nsnull; mURL->GetSpec(&urlStr); if (urlStr) { mHashValue = nsCRT::HashValue(urlStr); diff --git a/mailnews/base/util/nsMsgMailNewsUrl.cpp b/mailnews/base/util/nsMsgMailNewsUrl.cpp index 4fb907eb642..77ec4bf684a 100644 --- a/mailnews/base/util/nsMsgMailNewsUrl.cpp +++ b/mailnews/base/util/nsMsgMailNewsUrl.cpp @@ -309,7 +309,6 @@ NS_IMETHODIMP nsMsgMailNewsUrl::SetScheme(const char * aScheme) return m_baseURL->SetScheme(aScheme); } - NS_IMETHODIMP nsMsgMailNewsUrl::GetPreHost(char * *aPreHost) { return m_baseURL->GetPreHost(aPreHost); @@ -320,6 +319,26 @@ NS_IMETHODIMP nsMsgMailNewsUrl::SetPreHost(const char * aPreHost) return m_baseURL->SetPreHost(aPreHost); } +NS_IMETHODIMP nsMsgMailNewsUrl::GetUsername(char * *aUsername) +{ + return m_baseURL->GetUsername(aUsername); +} + +NS_IMETHODIMP nsMsgMailNewsUrl::SetUsername(const char * aUsername) +{ + return m_baseURL->SetUsername(aUsername); +} + +NS_IMETHODIMP nsMsgMailNewsUrl::GetPassword(char * *aPassword) +{ + return m_baseURL->GetPassword(aPassword); +} + +NS_IMETHODIMP nsMsgMailNewsUrl::SetPassword(const char * aPassword) +{ + return m_baseURL->SetPassword(aPassword); +} + NS_IMETHODIMP nsMsgMailNewsUrl::GetHost(char * *aHost) { return m_baseURL->GetHost(aHost); @@ -350,12 +369,21 @@ NS_IMETHODIMP nsMsgMailNewsUrl::SetPath(const char * aPath) return m_baseURL->SetPath(aPath); } +NS_IMETHODIMP nsMsgMailNewsUrl::GetURLParser(nsIURLParser * *aURLParser) +{ + return m_baseURL->GetURLParser(aURLParser); +} + +NS_IMETHODIMP nsMsgMailNewsUrl::SetURLParser(nsIURLParser* aURLParser) +{ + return m_baseURL->SetURLParser(aURLParser); +} + NS_IMETHODIMP nsMsgMailNewsUrl::Equals(nsIURI *other, PRBool *_retval) { return m_baseURL->Equals(other, _retval); } - NS_IMETHODIMP nsMsgMailNewsUrl::Clone(nsIURI **_retval) { return m_baseURL->Clone(_retval); @@ -389,22 +417,22 @@ NS_IMETHODIMP nsMsgMailNewsUrl::GetFileName(char * *aFileName) NS_IMETHODIMP nsMsgMailNewsUrl::GetFileBaseName(char * *aFileBaseName) { - return NS_ERROR_NOT_IMPLEMENTED; + return m_baseURL->GetFileBaseName(aFileBaseName); } NS_IMETHODIMP nsMsgMailNewsUrl::SetFileBaseName(const char * aFileBaseName) { - return NS_ERROR_NOT_IMPLEMENTED; + return m_baseURL->SetFileBaseName(aFileBaseName); } NS_IMETHODIMP nsMsgMailNewsUrl::GetFileExtension(char * *aFileExtension) { - return NS_ERROR_NOT_IMPLEMENTED; + return m_baseURL->GetFileExtension(aFileExtension); } NS_IMETHODIMP nsMsgMailNewsUrl::SetFileExtension(const char * aFileExtension) { - return NS_ERROR_NOT_IMPLEMENTED; + return m_baseURL->SetFileExtension(aFileExtension); } NS_IMETHODIMP nsMsgMailNewsUrl::SetFileName(const char * aFileName) diff --git a/mailnews/compose/src/nsSmtpUrl.cpp b/mailnews/compose/src/nsSmtpUrl.cpp index cbfa7a9764e..2e30ff99eda 100644 --- a/mailnews/compose/src/nsSmtpUrl.cpp +++ b/mailnews/compose/src/nsSmtpUrl.cpp @@ -318,6 +318,26 @@ NS_IMETHODIMP nsMailtoUrl::SetPreHost(const char * aPreHost) return m_baseURL->SetPreHost(aPreHost); } +NS_IMETHODIMP nsMailtoUrl::GetUsername(char * *aUsername) +{ + return m_baseURL->GetUsername(aUsername); +} + +NS_IMETHODIMP nsMailtoUrl::SetUsername(const char * aUsername) +{ + return m_baseURL->SetUsername(aUsername); +} + +NS_IMETHODIMP nsMailtoUrl::GetPassword(char * *aPassword) +{ + return m_baseURL->GetPassword(aPassword); +} + +NS_IMETHODIMP nsMailtoUrl::SetPassword(const char * aPassword) +{ + return m_baseURL->SetPassword(aPassword); +} + NS_IMETHODIMP nsMailtoUrl::GetHost(char * *aHost) { return m_baseURL->GetHost(aHost); @@ -348,6 +368,16 @@ NS_IMETHODIMP nsMailtoUrl::SetPath(const char * aPath) return m_baseURL->SetPath(aPath); } +NS_IMETHODIMP nsMailtoUrl::GetURLParser(nsIURLParser * *aURLParser) +{ + return m_baseURL->GetURLParser(aURLParser); +} + +NS_IMETHODIMP nsMailtoUrl::SetURLParser(nsIURLParser * aURLParser) +{ + return m_baseURL->SetURLParser(aURLParser); +} + NS_IMETHODIMP nsMailtoUrl::Equals(nsIURI *other, PRBool *_retval) { return m_baseURL->Equals(other, _retval); diff --git a/modules/libjar/nsJARURI.cpp b/modules/libjar/nsJARURI.cpp index 74804bb673c..77e8a5ad7b1 100644 --- a/modules/libjar/nsJARURI.cpp +++ b/modules/libjar/nsJARURI.cpp @@ -157,6 +157,30 @@ nsJARURI::SetPreHost(const char * aPreHost) return NS_ERROR_FAILURE; } +NS_IMETHODIMP +nsJARURI::GetUsername(char * *aUsername) +{ + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsJARURI::SetUsername(const char * aUsername) +{ + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsJARURI::GetPassword(char * *aPassword) +{ + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsJARURI::SetPassword(const char * aPassword) +{ + return NS_ERROR_FAILURE; +} + NS_IMETHODIMP nsJARURI::GetHost(char * *aHost) { @@ -193,6 +217,18 @@ nsJARURI::SetPath(const char * aPath) return NS_ERROR_FAILURE; } +NS_IMETHODIMP +nsJARURI::GetURLParser(nsIURLParser * *aURLParser) +{ + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsJARURI::SetURLParser(nsIURLParser * aURLParser) +{ + return NS_ERROR_FAILURE; +} + NS_IMETHODIMP nsJARURI::Equals(nsIURI *other, PRBool *_retval) { diff --git a/netwerk/base/public/Makefile.in b/netwerk/base/public/Makefile.in index b443e5cac72..bbefd8f16af 100644 --- a/netwerk/base/public/Makefile.in +++ b/netwerk/base/public/Makefile.in @@ -51,6 +51,7 @@ XPIDLSRCS = \ nsIUnicharStreamLoader.idl \ nsINetPrompt.idl \ nsISocketTransport.idl \ + nsIURLParser.idl \ $(NULL) EXPORTS = \ diff --git a/netwerk/base/public/makefile.win b/netwerk/base/public/makefile.win index bc8505c0aeb..5e4b5650072 100644 --- a/netwerk/base/public/makefile.win +++ b/netwerk/base/public/makefile.win @@ -50,8 +50,9 @@ XPIDLSRCS = \ .\nsIStatusCodeEventSink.idl \ .\nsIFileSystem.idl \ .\nsIUnicharStreamLoader.idl \ - .\nsINetPrompt.idl \ - .\nsISocketTransport.idl \ + .\nsINetPrompt.idl \ + .\nsISocketTransport.idl \ + .\nsIURLParser.idl \ $(NULL) include <$(DEPTH)/config/rules.mak> diff --git a/netwerk/base/public/nsIIOService.idl b/netwerk/base/public/nsIIOService.idl index fe100fd84cc..99fb1557986 100644 --- a/netwerk/base/public/nsIIOService.idl +++ b/netwerk/base/public/nsIIOService.idl @@ -39,6 +39,20 @@ interface nsILoadGroupObserver; [scriptable, uuid(1daf19f0-8ea7-11d3-93ad-00104ba0fd40)] interface nsIIOService : nsISupports { + /** + * constants for the Escape mask in the call to URLEscape + */ + const short url_Scheme = (1<<0); + const short url_Username = (1<<1); + const short url_Password = (1<<2); + const short url_Host = (1<<3); + const short url_Directory = (1<<4); + const short url_FileBaseName = (1<<5); + const short url_FileExtension = (1<<6); + const short url_Param = (1<<7); + const short url_Query = (1<<8); + const short url_Ref = (1<<9); + /** * Returns a protocol handler for a given URI scheme. */ @@ -160,6 +174,18 @@ interface nsIIOService : nsISupports * causing the dialer to come up). */ attribute boolean offline; + + /** + * escapes the string str with mask + */ + void URLEscape (in string str, + in short mask, + out string result); + /** + * unescapes str + */ + void URLUnescape(in string str, + out string result); }; %{C++ diff --git a/netwerk/base/public/nsIURI.idl b/netwerk/base/public/nsIURI.idl index 8efcef5ad38..8d44bef0f88 100644 --- a/netwerk/base/public/nsIURI.idl +++ b/netwerk/base/public/nsIURI.idl @@ -21,6 +21,7 @@ */ #include "nsISupports.idl" +#include "nsIURLParser.idl" /** * URIs are essentially structured names for things -- anything. @@ -79,6 +80,10 @@ interface nsIURI : nsISupports */ attribute string preHost; + attribute string username; + + attribute string password; + /** * The Host is the internet domain name to which this URI refers. * Note that it could be an IP address as well. @@ -103,6 +108,11 @@ interface nsIURI : nsISupports */ attribute string path; + /** + * This is a handle to the Parser used to parse the URI + */ + attribute nsIURLParser URLParser; + /** * Note that this comparison is only on char* level. Use * the scheme specific URI to do a more thorough check. For example, @@ -137,6 +147,7 @@ interface nsIURI : nsISupports * This method subsumes the deprecated method nsIIOService::MakeAbsolute. */ string resolve(in string relativePath); + }; %{C++ diff --git a/netwerk/base/src/Makefile.in b/netwerk/base/src/Makefile.in index 0b295bfdcc0..5f7ebd2f820 100644 --- a/netwerk/base/src/Makefile.in +++ b/netwerk/base/src/Makefile.in @@ -29,7 +29,16 @@ include $(DEPTH)/config/autoconf.mk MODULE = necko LIBRARY_NAME = neckobase_s +EXPORTS = \ + nsAuthURLParser.h \ + nsNoAuthURLParser.h \ + $(NULL) + CPPSRCS = \ + nsURLHelper.cpp \ + nsStdURLParser.cpp \ + nsAuthURLParser.cpp \ + nsNoAuthURLParser.cpp \ nsAsyncStreamListener.cpp \ nsSyncStreamListener.cpp \ nsIOService.cpp \ @@ -53,4 +62,3 @@ override NO_SHARED_LIB=1 override NO_STATIC_LIB= include $(topsrcdir)/config/rules.mk - diff --git a/netwerk/base/src/makefile.win b/netwerk/base/src/makefile.win index 0a4d65763ea..bf58a5c757f 100644 --- a/netwerk/base/src/makefile.win +++ b/netwerk/base/src/makefile.win @@ -27,6 +27,10 @@ LCFLAGS = -DWIN32_LEAN_AND_MEAN -D_IMPL_NS_NET LIBRARY_NAME=neckobase_s CPP_OBJS = \ + .\$(OBJDIR)\nsURLHelper.obj \ + .\$(OBJDIR)\nsStdURLParser.obj \ + .\$(OBJDIR)\nsAuthURLParser.obj \ + .\$(OBJDIR)\nsNoAuthURLParser.obj \ .\$(OBJDIR)\nsAsyncStreamListener.obj \ .\$(OBJDIR)\nsSyncStreamListener.obj \ .\$(OBJDIR)\nsIOService.obj \ @@ -44,6 +48,11 @@ CPP_OBJS = \ .\$(OBJDIR)\nsUnicharStreamLoader.obj \ $(NULL) +EXPORTS = \ + nsAuthURLParser.h \ + nsNoAuthURLParser.h \ + $(NULL) + INCS = $(INCS) \ -I$(DEPTH)\dist\include \ $(NULL) diff --git a/netwerk/base/src/nsIOService.cpp b/netwerk/base/src/nsIOService.cpp index 0cc5437e6b9..3f927c08e7b 100644 --- a/netwerk/base/src/nsIOService.cpp +++ b/netwerk/base/src/nsIOService.cpp @@ -411,4 +411,16 @@ nsIOService::SetOffline(PRBool offline) return NS_OK; } +NS_IMETHODIMP +nsIOService::URLEscape(const char* str, PRInt16 mask, char **result) +{ + return nsURLEscape((char*)str,mask,result); +} + +NS_IMETHODIMP +nsIOService::URLUnescape(const char* str, char **result) +{ + return nsURLUnescape((char*)str,result); +} + //////////////////////////////////////////////////////////////////////////////// diff --git a/netwerk/base/src/nsIOService.h b/netwerk/base/src/nsIOService.h index cd4a1585fbf..a6742fc7797 100644 --- a/netwerk/base/src/nsIOService.h +++ b/netwerk/base/src/nsIOService.h @@ -25,6 +25,7 @@ #include "nsIIOService.h" #include "nsString2.h" +#include "nsURLHelper.h" class nsIOService : public nsIIOService { diff --git a/netwerk/base/src/nsSimpleURI.cpp b/netwerk/base/src/nsSimpleURI.cpp index cb4b69b21de..d0022358662 100644 --- a/netwerk/base/src/nsSimpleURI.cpp +++ b/netwerk/base/src/nsSimpleURI.cpp @@ -27,6 +27,7 @@ #include "nsString.h" #include "prmem.h" #include "prprf.h" +#include "nsURLHelper.h" static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID); static NS_DEFINE_CID(kThisSimpleURIImplementationCID, @@ -142,6 +143,30 @@ nsSimpleURI::SetPreHost(const char* preHost) return NS_ERROR_FAILURE; } +NS_IMETHODIMP +nsSimpleURI::GetUsername(char* *result) +{ + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsSimpleURI::SetUsername(const char* userName) +{ + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsSimpleURI::GetPassword(char* *result) +{ + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsSimpleURI::SetPassword(const char* password) +{ + return NS_ERROR_FAILURE; +} + NS_IMETHODIMP nsSimpleURI::GetHost(char* *result) { @@ -181,6 +206,18 @@ nsSimpleURI::SetPath(const char* path) return NS_OK; } +NS_IMETHODIMP +nsSimpleURI::GetURLParser(nsIURLParser* *result) +{ + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsSimpleURI::SetURLParser(nsIURLParser* URLParser) +{ + return NS_ERROR_FAILURE; +} + NS_IMETHODIMP nsSimpleURI::Equals(nsIURI* other, PRBool *result) { @@ -229,8 +266,7 @@ nsSimpleURI::SetRelativePath(const char *i_RelativePath) NS_IMETHODIMP nsSimpleURI::Resolve(const char *relativePath, char **result) { - NS_ASSERTION(PR_FALSE, "This is meaningless in hack context!"); - return NS_ERROR_NOT_IMPLEMENTED; + return DupString(result,(char*)relativePath); } //////////////////////////////////////////////////////////////////////////////// diff --git a/netwerk/base/src/nsStdURL.cpp b/netwerk/base/src/nsStdURL.cpp index 53a3ff5dcbf..620b3a24669 100644 --- a/netwerk/base/src/nsStdURL.cpp +++ b/netwerk/base/src/nsStdURL.cpp @@ -20,7 +20,10 @@ * Contributor(s): */ +#include "nsIIOService.h" +#include "nsURLHelper.h" #include "nsStdURL.h" +#include "nsStdURLParser.h" #include "nscore.h" #include "nsCRT.h" #include "nsString.h" @@ -28,165 +31,115 @@ #include "prprf.h" #include "nsXPIDLString.h" #include "nsCOMPtr.h" +#include "nsIServiceManager.h" static NS_DEFINE_CID(kStdURLCID, NS_STANDARDURL_CID); static NS_DEFINE_CID(kThisStdURLImplementationCID, NS_THIS_STANDARDURL_IMPLEMENTATION_CID); +static NS_DEFINE_CID(kStdURLParserCID, NS_STANDARDURLPARSER_CID); -//---------------------------------------- - -// Helper function to extract the port # from a string -// PR_sscanf handles spaces and non-digits correctly -static PRInt32 ExtractPortFrom(char* src) +nsStdURL::nsStdURL() + : mScheme(nsnull), + mUsername(nsnull), + mPassword(nsnull), + mHost(nsnull), + mPort(-1), + mDirectory(nsnull), + mFileBaseName(nsnull), + mFileExtension(nsnull), + mParam(nsnull), + mQuery(nsnull), + mRef(nsnull), + mURLParser(nsnull) { - PRInt32 returnValue = -1; - return (0 < PR_sscanf(src, "%d", &returnValue)) ? returnValue : -1; + NS_INIT_REFCNT(); + /* Create the standard URLParser */ + nsComponentManager::CreateInstance(kStdURLParserCID, + nsnull, NS_GET_IID(nsIURLParser), + (void**)&mURLParser); + } -// Replace all /./ with a / -// Also changes all \ to / -// But only till #?; -static void ReplaceMess(char* io_Path) -{ - /* Stolen from the old netlib's mkparse.c. - * - * modifies a url of the form /foo/../foo1 -> /foo1 - * and /foo/./foo1 -> /foo/foo1 - * and /foo/foo1/.. -> /foo/ - */ - char *fwdPtr = io_Path; - char *urlPtr = io_Path; - - for(; (*fwdPtr != '\0') && - (*fwdPtr != ';') && - (*fwdPtr != '?') && - (*fwdPtr != '#'); ++fwdPtr) - { - if (*fwdPtr == '\\') - *fwdPtr = '/'; - if (*fwdPtr == '/' && *(fwdPtr+1) == '.' && - (*(fwdPtr+2) == '/' || *(fwdPtr+2) == '\\')) - { - // remove . followed by slash or a backslash - fwdPtr += 1; - } - else if(*fwdPtr == '/' && *(fwdPtr+1) == '.' && *(fwdPtr+2) == '.' && - (*(fwdPtr+3) == '/' || - *(fwdPtr+3) == '\0' || - *(fwdPtr+3) == ';' || // This will take care of likes of - *(fwdPtr+3) == '?' || // foo/bar/..#sometag - *(fwdPtr+3) == '#' || - *(fwdPtr+3) == '\\')) - { - // remove foo/.. - // reverse the urlPtr to the previous slash - if(urlPtr != io_Path) - urlPtr--; // we must be going back at least by one - for(;*urlPtr != '/' && urlPtr != io_Path; urlPtr--) - ; // null body - - // forward the fwd_prt past the ../ - fwdPtr += 2; - // special case if we have reached the end to preserve the last / - if (*fwdPtr == '.' && *(fwdPtr+1) == '\0') - urlPtr +=1; - } - else - { - // copy the url incrementaly - *urlPtr++ = *fwdPtr; - } - } - // Copy remaining stuff past the #?; - for (; *fwdPtr != '\0'; ++fwdPtr) - { - *urlPtr++ = *fwdPtr; - } - *urlPtr = '\0'; // terminate the url - - /* - * Now lets remove trailing . case - * /foo/foo1/. -> /foo/foo1/ - */ - - if ((urlPtr > (io_Path+1)) && (*(urlPtr-1) == '.') && (*(urlPtr-2) == '/')) - *(urlPtr-1) = '\0'; -} - - - -//---------------------------------------- - -class nsParsePath -{ -public: - nsParsePath(nsStdURL* i_URL): mURL(i_URL) {} - virtual ~nsParsePath() {mURL->ParsePath();} -private: - nsStdURL* mURL; -}; - nsStdURL::nsStdURL(const char* i_Spec, nsISupports* outer) : mScheme(nsnull), - mPreHost(nsnull), + mUsername(nsnull), + mPassword(nsnull), mHost(nsnull), mPort(-1), - mPath(nsnull), mDirectory(nsnull), - mFileName(nsnull), + mFileBaseName(nsnull), + mFileExtension(nsnull), mParam(nsnull), mQuery(nsnull), - mRef(nsnull) + mRef(nsnull), + mURLParser(nsnull) { - // Skip leading spaces + NS_INIT_REFCNT(); + + // Skip leading spaces and control-characters char* fwdPtr= (char*) i_Spec; - while (fwdPtr && (*fwdPtr != '\0') && (*fwdPtr == ' ')) + while (fwdPtr && (*fwdPtr > '\0') && (*fwdPtr <= ' ')) fwdPtr++; - // Remove trailing spaces + // Remove trailing spaces and control-characters if (fwdPtr) { char* bckPtr= (char*)fwdPtr + PL_strlen(fwdPtr) -1; - if (*bckPtr == ' ') { - while ((bckPtr-fwdPtr) >= 0 && (*bckPtr == ' ')) { + if (*bckPtr > '\0' && *bckPtr <= ' ') { + while ((bckPtr-fwdPtr) >= 0 && (*bckPtr <= ' ')) { bckPtr--; } *(bckPtr+1) = '\0'; } } - mSpec = fwdPtr ? nsCRT::strdup(fwdPtr) : nsnull; + + /* Create the standard URLParser */ + nsComponentManager::CreateInstance(kStdURLParserCID, + nsnull, NS_GET_IID(nsIURLParser), + (void**)&mURLParser); + NS_INIT_AGGREGATED(outer); - if (fwdPtr) - Parse(); + if (fwdPtr && mURLParser) + Parse((char*)fwdPtr); } nsStdURL::nsStdURL(const nsStdURL& otherURL) : mPort(otherURL.mPort) { - mSpec = otherURL.mSpec ? nsCRT::strdup(otherURL.mSpec) : nsnull; + NS_INIT_REFCNT(); + mScheme = otherURL.mScheme ? nsCRT::strdup(otherURL.mScheme) : nsnull; - mPreHost = otherURL.mPreHost ? nsCRT::strdup(otherURL.mPreHost) : nsnull; + mUsername = otherURL.mUsername ? nsCRT::strdup(otherURL.mUsername) : nsnull; + mPassword = otherURL.mPassword ? nsCRT::strdup(otherURL.mPassword) : nsnull; mHost = otherURL.mHost ? nsCRT::strdup(otherURL.mHost) : nsnull; - mPath = otherURL.mPath ? nsCRT::strdup(otherURL.mPath) : nsnull; mDirectory = otherURL.mDirectory ? nsCRT::strdup(otherURL.mDirectory) : nsnull; - mFileName = otherURL.mFileName ? nsCRT::strdup(otherURL.mFileName) : nsnull; + mFileBaseName = otherURL.mFileBaseName ? nsCRT::strdup(otherURL.mFileBaseName) : nsnull; + mFileExtension = otherURL.mFileExtension ? nsCRT::strdup(otherURL.mFileExtension) : nsnull; mParam = otherURL.mParam ? nsCRT::strdup(otherURL.mParam) : nsnull; mQuery = otherURL.mQuery ? nsCRT::strdup(otherURL.mQuery) : nsnull; mRef= otherURL.mRef ? nsCRT::strdup(otherURL.mRef) : nsnull; + + NS_IF_ADDREF(otherURL.mURLParser); + mURLParser = otherURL.mURLParser; + NS_INIT_AGGREGATED(nsnull); // Todo! How? } nsStdURL& nsStdURL::operator=(const nsStdURL& otherURL) { - mSpec = otherURL.mSpec ? nsCRT::strdup(otherURL.mSpec) : nsnull; mScheme = otherURL.mScheme ? nsCRT::strdup(otherURL.mScheme) : nsnull; - mPreHost = otherURL.mPreHost ? nsCRT::strdup(otherURL.mPreHost) : nsnull; + mUsername = otherURL.mUsername ? nsCRT::strdup(otherURL.mUsername) : nsnull; + mPassword = otherURL.mPassword ? nsCRT::strdup(otherURL.mPassword) : nsnull; mHost = otherURL.mHost ? nsCRT::strdup(otherURL.mHost) : nsnull; - mPath = otherURL.mPath ? nsCRT::strdup(otherURL.mPath) : nsnull; mDirectory = otherURL.mDirectory ? nsCRT::strdup(otherURL.mDirectory) : nsnull; - mFileName = otherURL.mFileName ? nsCRT::strdup(otherURL.mFileName) : nsnull; + mFileBaseName = otherURL.mFileBaseName ? nsCRT::strdup(otherURL.mFileBaseName) : nsnull; + mFileExtension = otherURL.mFileExtension ? nsCRT::strdup(otherURL.mFileExtension) : nsnull; mParam = otherURL.mParam ? nsCRT::strdup(otherURL.mParam) : nsnull; mQuery = otherURL.mQuery ? nsCRT::strdup(otherURL.mQuery) : nsnull; mRef= otherURL.mRef ? nsCRT::strdup(otherURL.mRef) : nsnull; + + NS_IF_ADDREF(otherURL.mURLParser); + mURLParser = otherURL.mURLParser; + NS_INIT_AGGREGATED(nsnull); // Todo! How? return *this; } @@ -202,15 +155,16 @@ nsStdURL::operator==(const nsStdURL& otherURL) const nsStdURL::~nsStdURL() { CRTFREEIF(mScheme); - CRTFREEIF(mPreHost); + CRTFREEIF(mUsername); + CRTFREEIF(mPassword); CRTFREEIF(mHost); - CRTFREEIF(mPath); - CRTFREEIF(mRef); + CRTFREEIF(mDirectory); + CRTFREEIF(mFileBaseName); + CRTFREEIF(mFileExtension); CRTFREEIF(mParam); CRTFREEIF(mQuery); - CRTFREEIF(mSpec); - CRTFREEIF(mDirectory); - CRTFREEIF(mFileName); + CRTFREEIF(mRef); + NS_IF_RELEASE(mURLParser); } NS_IMPL_AGGREGATED(nsStdURL); @@ -242,9 +196,12 @@ nsStdURL::Equals(nsIURI *i_OtherURI, PRBool *o_Equals) PRBool eq = PR_FALSE; if (i_OtherURI) { nsXPIDLCString spec; + nsXPIDLCString spec2; nsresult rv = i_OtherURI->GetSpec(getter_Copies(spec)); if (NS_FAILED(rv)) return rv; - eq = nsAutoString(spec).Equals(this->mSpec); + rv = this->GetSpec(getter_Copies(spec2)); + if (NS_FAILED(rv)) return rv; + eq = nsAutoString(spec).Equals(spec2); } *o_Equals = eq; return NS_OK; @@ -263,433 +220,146 @@ nsStdURL::Clone(nsIURI **o_URI) return rv; } -nsresult -nsStdURL::Parse(void) +nsresult +nsStdURL::GetURLParser(nsIURLParser* *aURLParser) { + *aURLParser = mURLParser; + NS_IF_ADDREF(*aURLParser); + return NS_OK; +} - NS_PRECONDITION( (nsnull != mSpec), "Parse called on empty url!"); - if (!mSpec) - return NS_ERROR_MALFORMED_URI; - - // Parse the path into its individual elements - // when we are done from here. - nsParsePath pp(this); - - // Leading spaces are now removed by SetSpec. - int len = PL_strlen(mSpec); - static const char delimiters[] = "/:@?"; //this order is optimized. - char* brk = PL_strpbrk(mSpec, delimiters); - char* lastbrk = brk; - if (!brk) // everything is a host - { - ExtractString(mSpec, &mHost, len); - return NS_OK; - } - - switch (*brk) - { - case '/' : - case '?' : - // If the URL starts with a slash then everything is a path - if (brk == mSpec) - { - ExtractString(mSpec, &mPath, len); - return NS_OK; - } - else // The first part is host, so its host/path - { - ExtractString(mSpec, &mHost, (brk - mSpec)); - ExtractString(brk, &mPath, (len - (brk - mSpec))); - return NS_OK; - } - break; - case ':' : - if (*(brk+1) == '/') - { - ExtractString(mSpec, &mScheme, (brk - mSpec)); - - if (*(brk+2) == '/') // e.g. http:// - // If the first colon is followed by // then its definitely a spec - { - lastbrk = brk+3; - brk = PL_strpbrk(lastbrk, delimiters); - if (!brk) // everything else is a host, as in http://host - { - ExtractString(lastbrk, &mHost, len - (lastbrk - mSpec)); - return NS_OK; - } - switch (*brk) - { - case '/' : // standard case- http://host/path - case '?' : // missing path cases - ExtractString(lastbrk, &mHost, (brk - lastbrk)); - ExtractString(brk, &mPath, (len - (brk - mSpec))); - - return NS_OK; - break; - case ':' : // http://user:... or http://host:... - { - // It could be http://user:pass@host/path - // or http://host:port/path we find that by checking further... - char* nextbrk = PL_strpbrk(brk+1, delimiters); - if (!nextbrk) // http://host:port - { - ExtractString(lastbrk, &mHost, (brk-lastbrk)); - mPort = ExtractPortFrom(brk+1); - if (mPort <= 0) - return NS_ERROR_MALFORMED_URI; - else - return NS_OK; - } - - switch (*nextbrk) - { - case '/': // http://host:port/path - case '?': // http://host:port?path - ExtractString(lastbrk, &mHost, - (brk-lastbrk)); - mPort = ExtractPortFrom(brk+1); - if (mPort <= 0) - return NS_ERROR_MALFORMED_URI; - ExtractString(nextbrk, &mPath, - len - (nextbrk-mSpec)); - return NS_OK; - break; - case '@': // http://user:pass@host... - ExtractString(lastbrk, &mPreHost, - (nextbrk - lastbrk)); - - brk = PL_strpbrk(nextbrk+1, delimiters); - if (!brk) // its just http://user:pass@host - { - ExtractString(nextbrk+1, &mHost, - len - (nextbrk+1 - mSpec)); - return NS_OK; - } - - ExtractString(nextbrk+1, &mHost, - brk - (nextbrk+1)); - - switch (*brk) - { - case '/': // http://user:pass@host/path - case '?': - ExtractString(brk, &mPath, - len - (brk - mSpec)); - return NS_OK; - break; - case ':': // http://user:pass@host:port... - lastbrk = brk+1; - brk = PL_strpbrk(lastbrk, "/?"); - if (brk) // http://user:pass@host:port/path - { - mPort = ExtractPortFrom(lastbrk); - if (mPort <= 0) - return NS_ERROR_MALFORMED_URI; - ExtractString(brk, &mPath, - len - (brk-mSpec)); - return NS_OK; - } - else // http://user:pass@host:port - { - mPort = ExtractPortFrom(lastbrk); - if (mPort <= 0) - return NS_ERROR_MALFORMED_URI; - return NS_OK; - } - break; - default: NS_POSTCONDITION(0, "This just can't be!"); - break; - } - break; - case ':': // three colons! - return NS_ERROR_MALFORMED_URI; - break; - default: NS_POSTCONDITION(0, "This just can't be!"); - break; - } - } - break; - case '@' : // http://user@host... - { - ExtractString(lastbrk, &mPreHost, - (brk-lastbrk)); - lastbrk = brk+1; - brk = PL_strpbrk(lastbrk, delimiters); - if (!brk) // its just http://user@host - { - ExtractString(lastbrk, &mHost, - len - (lastbrk - mSpec)); - return NS_OK; - } - ExtractString(lastbrk, &mHost, - (brk - lastbrk)); - switch (*brk) - { - case ':' : // http://user@host:port... - lastbrk = brk+1; - brk = PL_strpbrk(lastbrk, "/?"); - if (brk) // http://user@host:port/path - { - mPort = ExtractPortFrom(lastbrk); - if (mPort <= 0) - return NS_ERROR_MALFORMED_URI; - ExtractString(brk, &mPath, - len - (brk-mSpec)); - return NS_OK; - } - else // http://user@host:port - { - mPort = ExtractPortFrom(lastbrk); - if (mPort <= 0) - return NS_ERROR_MALFORMED_URI; - return NS_OK; - } - break; - case '/' : // http://user@host/path - case '?' : // http://user@host?path - ExtractString(brk, &mPath, - len - (brk - mSpec)); - return NS_OK; - break; - case '@' : - return NS_ERROR_MALFORMED_URI; - default : NS_POSTCONDITION(0, - "This just can't be!"); - break; - } - } - break; - default: NS_POSTCONDITION(0, "This just can't be!"); - break; - } - } - else // This is a no // path alone case like file:/path, - // there is never a prehost/host in this case. - { - ExtractString(brk+1, &mPath, len - (brk-mSpec+1)); - return NS_OK; - } - } - else // scheme:host or host:port... - { - lastbrk = brk+1; - - if ((*lastbrk >= '0') && (*lastbrk <= '9')) //host:port... - { - ExtractString(mSpec, &mHost, (brk - mSpec)); - brk = PL_strpbrk(lastbrk, delimiters); - if (!brk) // Everything else is just the port - { - mPort = ExtractPortFrom(lastbrk); - if (mPort <= 0) - return NS_ERROR_MALFORMED_URI; - return NS_OK; - } - switch (*brk) - { - case '/' : // The path, so its host:port/path - case '?' : // The path, so its host:port?path - mPort = ExtractPortFrom(lastbrk); - if (mPort <= 0) - return NS_ERROR_MALFORMED_URI; - ExtractString(brk, &mPath, len - (brk-mSpec)); - return NS_OK; - break; - case ':' : - return NS_ERROR_MALFORMED_URI; - break; - case '@' : - // This is a special case of user:pass@host... so - // Cleanout our earliar knowledge of host - CRTFREEIF(mHost); - - ExtractString(mSpec, &mPreHost, (brk-mSpec)); - lastbrk = brk+1; - brk = PL_strpbrk(lastbrk, ":/?"); - // its user:pass@host so everthing else is just the host - if (!brk) - { - ExtractString(lastbrk, &mHost, len - (lastbrk-mSpec)); - return NS_OK; - } - ExtractString(lastbrk, &mHost, (brk-lastbrk)); - if (*brk == ':') // user:pass@host:port... - { - lastbrk = brk+1; - brk = PL_strpbrk(lastbrk, "/?"); - if (brk) // user:pass@host:port/path - { - mPort = ExtractPortFrom(lastbrk); - if (mPort <= 0) - return NS_ERROR_MALFORMED_URI; - ExtractString(brk, &mPath, len - (brk-mSpec)); - return NS_OK; - } - else // user:pass@host:port - { - mPort = ExtractPortFrom(lastbrk); - if (mPort <= 0) - return NS_ERROR_MALFORMED_URI; - return NS_OK; - } - } - else // (*brk == '/') || (*brk == '?') - // so user:pass@host/path - { - ExtractString(brk, &mPath, len - (brk - mSpec)); - return NS_OK; - } - break; - default: NS_POSTCONDITION(0, "This just can't be!"); - break; - } - } - else // scheme:host... - { - ExtractString(mSpec, &mScheme, (brk - mSpec)); - brk = PL_strpbrk(lastbrk, delimiters); - if (!brk) // its just scheme:host - { - ExtractString(lastbrk, &mHost, len - (lastbrk-mSpec)); - return NS_OK; - } - switch (*brk) - { - case '/' : // The path, so its scheme:host/path - case '?' : // The path, so its scheme:host?path - ExtractString(lastbrk, &mHost, (brk-lastbrk)); - ExtractString(brk, &mPath, len - (brk - mSpec)); - return NS_OK; - break; - case '@' : // scheme:user@host... - ExtractString(lastbrk, &mPreHost, (brk-lastbrk)); - lastbrk = brk+1; - brk = PL_strpbrk(lastbrk, delimiters); - if (!brk) // scheme:user@host only - { - ExtractString(lastbrk, &mHost, len - (lastbrk-mSpec)); - return NS_OK; - } - ExtractString(lastbrk, &mHost, (brk - lastbrk)); - switch (*brk) - { - case ':' : // scheme:user@host:port... - lastbrk = brk+1; - brk = PL_strpbrk(lastbrk, "/?"); - if (brk) // user:pass@host:port/path - { - mPort = ExtractPortFrom(lastbrk); - if (mPort <= 0) - return NS_ERROR_MALFORMED_URI; - ExtractString(brk, &mPath, len - (brk-mSpec)); - return NS_OK; - } - else // user:pass@host:port - { - mPort = ExtractPortFrom(lastbrk); - if (mPort <= 0) - return NS_ERROR_MALFORMED_URI; - return NS_OK; - } - break; - case '/' : - case '?' : - ExtractString(brk, &mPath, len - (brk-mSpec)); - return NS_OK; - break; - case '@' : // bad case - return NS_ERROR_MALFORMED_URI; - break; - default: NS_POSTCONDITION(0, "This just can't be!"); - break; - } - break; - case ':' : // scheme:user:pass@host...or scheme:host:port... - /* TODO - if you find @ in the remaining string - then // scheme:user:pass@host... - { - - - } - else // scheme:host:port - { - ExtractString(lastbrk, &mHost, (brk-lastbrk)); - } - */ - break; - default: NS_POSTCONDITION(0, "This just can't be!"); - break; - } - } - } - break; - case '@' : - //Everything before the @ is the prehost stuff - ExtractString(mSpec, &mPreHost, brk-mSpec); - lastbrk = brk+1; - brk = PL_strpbrk(lastbrk, ":/"); - if (!brk) // its user@host so everything else is just the host - { - ExtractString(lastbrk, &mHost, (len - (lastbrk-mSpec))); - return NS_OK; - } - ExtractString(lastbrk, &mHost, (brk-lastbrk)); - if (*brk == ':') // user@host:port... - { - lastbrk = brk+1; - brk = PL_strpbrk(lastbrk, "/?"); - if (brk) // user@host:port/path - { - mPort = ExtractPortFrom(lastbrk); - if (mPort <= 0) - return NS_ERROR_MALFORMED_URI; - ExtractString(brk, &mPath, len - (brk-mSpec)); - return NS_OK; - } - else // user@host:port - { - mPort = ExtractPortFrom(lastbrk); - if (mPort <= 0) - return NS_ERROR_MALFORMED_URI; - return NS_OK; - } - } - else // (*brk == '/') so user@host/path - { - ExtractString(brk, &mPath, len - (brk - mSpec)); - return NS_OK; - } - break; - default: - NS_ASSERTION(0, "This just can't be!"); - break; - } - +nsresult +nsStdURL::SetURLParser(nsIURLParser* aURLParser) +{ + NS_IF_RELEASE(mURLParser); + mURLParser = aURLParser; return NS_OK; } nsresult -nsStdURL::ReconstructSpec() +nsStdURL::Parse(const char* i_Spec) { - if (mSpec) nsCRT::free(mSpec); + // Main parser + NS_PRECONDITION( (nsnull != i_Spec), "Parse called on empty url!"); + if (!i_Spec) + return NS_ERROR_MALFORMED_URI; + NS_PRECONDITION( (nsnull != mURLParser), "Parse called without parser!"); + if (!mURLParser) + return NS_ERROR_NULL_POINTER; + + // Parse the spec + char* ePath = nsnull; + nsresult rv = mURLParser->ParseAtScheme(i_Spec, &mScheme, &mUsername, + &mPassword, &mHost, &mPort, + &ePath); + if (NS_SUCCEEDED(rv)) { + // Now parse the path + rv = mURLParser->ParseAtDirectory(ePath, &mDirectory, &mFileBaseName, + &mFileExtension, &mParam, + &mQuery, &mRef); + } + CRTFREEIF(ePath); + return rv; +} + +nsresult +nsStdURL::GetString(char** result, char* fromEscapedStr, Format toFormat) +{ + // Given str "foo%20bar", gets "foo bar" if UNESCAPED + nsresult rv = NS_OK; + if (toFormat == UNESCAPED) { + rv = nsURLUnescape(fromEscapedStr, result); + } else + rv = DupString(result, fromEscapedStr); + return rv; +} + +nsresult +nsStdURL::AppendString(nsCString& buffer, char * fromUnescapedStr, + Format toFormat, PRInt16 mask) +{ + // Given str "foo bar", appends "foo%20bar" to buffer if ESCAPED + nsresult rv = NS_OK; + + if (!fromUnescapedStr) + return NS_ERROR_FAILURE; + + char* temp = nsnull; + if (toFormat == ESCAPED) { + rv = nsURLEscape(fromUnescapedStr, mask, &temp); + if (NS_SUCCEEDED(rv)) + buffer += temp; + } else { + buffer += fromUnescapedStr; + } + + CRTFREEIF(temp); + return rv; +} + +nsresult +nsStdURL::AppendPreHost(nsCString& buffer, char* i_Username, + char* i_Password, Format toFormat) +{ + nsresult rv = NS_OK; + if (i_Username) + { + rv = AppendString(buffer,i_Username,ESCAPED, + nsIIOService::url_Username); + if (NS_FAILED(rv)) + return rv; + if (i_Password) + { + buffer += ':'; + rv = AppendString(buffer,i_Password,ESCAPED, + nsIIOService::url_Password); + if (NS_FAILED(rv)) + return rv; + } + buffer += '@'; + } + return rv; +} + +nsresult +nsStdURL::AppendFileName(nsCString& buffer, char* i_FileBaseName, + char* i_FileExtension, Format toFormat) +{ + nsresult rv = NS_OK; + if (i_FileBaseName) + { + rv = AppendString(buffer,i_FileBaseName,ESCAPED, + nsIIOService::url_FileBaseName); + if (NS_FAILED(rv)) + return rv; + } + if (i_FileExtension) + { + buffer += '.'; + rv = AppendString(buffer,i_FileExtension,ESCAPED, + nsIIOService::url_FileExtension); + } + return rv; +} + +nsresult +nsStdURL::GetSpec(char **o_Spec) +{ + nsresult rv = NS_OK; nsCAutoString finalSpec; // guaranteed to be singlebyte. finalSpec.SetCapacity(64); if (mScheme) { - finalSpec = mScheme; + rv = AppendString(finalSpec,mScheme,ESCAPED,nsIIOService::url_Scheme); finalSpec += "://"; } - if (mPreHost) - { - finalSpec += mPreHost; - finalSpec += '@'; - } + + rv = AppendPreHost(finalSpec,mUsername,mPassword,ESCAPED); + if (mHost) { - finalSpec += mHost; + rv = AppendString(finalSpec,mHost,ESCAPED,nsIIOService::url_Host); if (-1 != mPort) { char* portBuffer = PR_smprintf(":%d", mPort); @@ -700,12 +370,21 @@ nsStdURL::ReconstructSpec() portBuffer = 0; } } - if (mPath) - { - finalSpec += mPath; + char* ePath = nsnull; + rv = GetPath(&ePath); + if NS_FAILED(rv) { + CRTFREEIF(ePath); + return rv; } - mSpec = finalSpec.ToNewCString(); - return (mSpec ? NS_OK : NS_ERROR_OUT_OF_MEMORY); + + if (ePath) + { + finalSpec += ePath; + } + *o_Spec = finalSpec.ToNewCString(); + CRTFREEIF(ePath); + + return (*o_Spec ? NS_OK : NS_ERROR_OUT_OF_MEMORY); } NS_METHOD @@ -724,40 +403,31 @@ nsStdURL::Create(nsISupports *aOuter, return NS_ERROR_OUT_OF_MEMORY; nsresult rv = url->AggregatedQueryInterface(aIID, aResult); - if (NS_FAILED(rv)) { - delete url; - return rv; - } - + if (NS_FAILED(rv)) { + delete url; + return rv; + } + return rv; } -nsresult -nsStdURL::ExtractString(char* i_Src, char* *o_Dest, PRUint32 length) +NS_METHOD +nsStdURL::GetPreHost(char **o_PreHost) { - NS_PRECONDITION( (nsnull != i_Src), "Exract called on empty string!"); - CRTFREEIF(*o_Dest); - if (0 == length) - return NS_OK; - *o_Dest = PL_strndup(i_Src, length); - return (*o_Dest ? NS_OK : NS_ERROR_OUT_OF_MEMORY); -} - -nsresult -nsStdURL::DupString(char* *o_Dest, const char* i_Src) -{ - if (!o_Dest) + if (!o_PreHost) return NS_ERROR_NULL_POINTER; - if (i_Src) - { - *o_Dest = nsCRT::strdup(i_Src); - return (*o_Dest == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; - } - else - { - *o_Dest = nsnull; - return NS_OK; - } + + nsCAutoString temp; + + nsresult rv = AppendPreHost(temp,mUsername,mPassword,ESCAPED); + + if (NS_FAILED(rv)) + return rv; + + *o_PreHost = temp.ToNewCString(); + if (!*o_PreHost) + return NS_ERROR_OUT_OF_MEMORY; + return NS_OK; } NS_IMETHODIMP @@ -781,10 +451,11 @@ nsStdURL::SetDirectory(const char* i_Directory) dir += "/"; } + CRTFREEIF(mDirectory); mDirectory = dir.ToNewCString(); if (!mDirectory) return NS_ERROR_OUT_OF_MEMORY; - return ReconstructPath(); + return NS_OK; } NS_IMETHODIMP @@ -793,54 +464,50 @@ nsStdURL::SetFileName(const char* i_FileName) if (!i_FileName) return NS_ERROR_NULL_POINTER; - //Cleanout param, query and ref - CRTFREEIF(mParam); - CRTFREEIF(mQuery); - CRTFREEIF(mRef); + NS_PRECONDITION( (nsnull != mURLParser), "Parse called without parser!"); + if (!mURLParser) + return NS_ERROR_NULL_POINTER; //If it starts with a / then everything is the path. if ('/' == *i_FileName) { return SetPath(i_FileName); } - CRTFREEIF(mFileName); - nsresult status = DupString(&mFileName, i_FileName); - - // XXX This is ineffecient - ReconstructPath(); - ParsePath(); - + // Otherwise concatenate Directory and Filename and the call SetPath + nsCAutoString dir; + nsresult status = AppendString(dir,mDirectory,ESCAPED, + nsIIOService::url_Directory); + dir += i_FileName; + char *eNewPath = dir.ToNewCString(); + if (!eNewPath) + return NS_ERROR_OUT_OF_MEMORY; + status = SetPath(eNewPath); + CRTFREEIF(eNewPath); return status; } -NS_IMETHODIMP -nsStdURL::SetRef(const char* i_Ref) -{ - /* - no check for i_Ref = nsnull becuz you can remove # by using it that way - So SetRef(nsnull) removed any existing ref values whereas - SetRef("") will ensure that there is a # at the end. These apply to - ? and ; as well. - */ - nsresult status = DupString(&mRef, - (i_Ref && (*i_Ref == '#')) ? (i_Ref+1) : i_Ref); - return (NS_FAILED(status) ? status : ReconstructPath()); -} - NS_IMETHODIMP nsStdURL::SetParam(const char* i_Param) { - nsresult status = DupString(&mParam, - (i_Param && (*i_Param == ';')) ? (i_Param+1) : i_Param); - return (NS_FAILED(status) ? status : ReconstructPath()); + CRTFREEIF(mParam); + return DupString(&mParam, (i_Param && (*i_Param == ';')) ? + (i_Param+1) : i_Param); } NS_IMETHODIMP nsStdURL::SetQuery(const char* i_Query) { - nsresult status = DupString(&mQuery, - (i_Query && (*i_Query == '?')) ? (i_Query+1) : i_Query); - return (NS_FAILED(status) ? status : ReconstructPath()); + CRTFREEIF(mQuery); + return DupString(&mQuery, (i_Query && (*i_Query == '?')) ? + (i_Query+1) : i_Query); +} + +NS_IMETHODIMP +nsStdURL::SetRef(const char* i_Ref) +{ + CRTFREEIF(mRef); + return DupString(&mRef, (i_Ref && (*i_Ref == '#')) ? + (i_Ref+1) : i_Ref); } NS_IMETHODIMP @@ -851,10 +518,16 @@ nsStdURL::SetRelativePath(const char* i_Relative) char* ref; char* query; char* file; + char* i_Path; + char* ePath = nsnull; if (!i_Relative) return NS_ERROR_NULL_POINTER; + NS_PRECONDITION( (nsnull != mURLParser), "Parse called without parser!"); + if (!mURLParser) + return NS_ERROR_NULL_POINTER; + // Make sure that if there is a : its before other delimiters // If not then its an absolute case static const char delimiters[] = "/;?#:"; @@ -865,32 +538,56 @@ nsStdURL::SetRelativePath(const char* i_Relative) return rv; } - switch (*i_Relative) + if (*i_Relative == '/' && *(i_Relative+1) != '\0' && + *(i_Relative+1) == '/') { + CRTFREEIF(mUsername); + CRTFREEIF(mPassword); + CRTFREEIF(mHost); + mPort = -1; + rv = mURLParser->ParseAtPreHost((char*)i_Relative, &mUsername, + &mPassword, &mHost, &mPort, &ePath); + if (NS_FAILED(rv)) + return rv; + i_Path = ePath; + } else { + i_Path = (char*)i_Relative; + } + + char* eFileName = nsnull; + + switch (*i_Path) { case '/': - return SetPath((char*) i_Relative); + rv = SetPath((char*) i_Path); + CRTFREEIF(ePath); + return rv; case ';': - // Append to Filename add then call SetFilePath - options = mFileName; - options += (char*)i_Relative; - file = (char*)options.GetBuffer(); + // Append to Filename add then call SetFileName + rv = GetFileName(&eFileName); + options = eFileName; + CRTFREEIF(eFileName); + options += (char*)i_Path; + file = options.ToNewCString(); rv = SetFileName(file); + CRTFREEIF(ePath); return rv; case '?': // check for ref part - ref = PL_strrchr(i_Relative, '#'); + ref = PL_strrchr(i_Path, '#'); if (!ref) { CRTFREEIF(mRef); - return SetQuery((char*)i_Relative); + rv = SetQuery((char*)i_Path); + CRTFREEIF(ePath); + return rv; } else { DupString(&query,nsnull); - ExtractString((char*)i_Relative, &query, - (PL_strlen(i_Relative)-(ref-i_Relative))); - + ExtractString((char*)i_Path, &query, + (PL_strlen(i_Path)-(ref-i_Path))); + CRTFREEIF(ePath); rv = SetQuery(query); - nsCRT::free(query); + CRTFREEIF(query); if (NS_FAILED(rv)) return rv; rv = SetRef(ref); return rv; @@ -898,17 +595,21 @@ nsStdURL::SetRelativePath(const char* i_Relative) break; case '#': - return SetRef((char*)i_Relative); + rv = SetRef((char*)i_Path); + CRTFREEIF(ePath); + return rv; default: - return SetFileName((char*)i_Relative); + rv = SetFileName((char*)i_Path); + CRTFREEIF(ePath); + return rv; } } NS_IMETHODIMP nsStdURL::Resolve(const char *relativePath, char **result) { - nsresult rv; + nsresult rv = NS_OK; if (!relativePath) return NS_ERROR_NULL_POINTER; @@ -923,26 +624,51 @@ nsStdURL::Resolve(const char *relativePath, char **result) if (path) { path = PL_strstr((char*)(path+3),"/"); if (path) - ReplaceMess(path); + CoaleseDirs(path); } return rv; } nsCAutoString finalSpec; // guaranteed to be singlebyte. + // This is another case of an almost absolute URL + if (*relativePath == '/' && *(relativePath+1) != '\0' && + *(relativePath+1) == '/') { + + if (mScheme) + { + rv = AppendString(finalSpec,mScheme,ESCAPED, + nsIIOService::url_Scheme); + finalSpec += ":"; + } + + finalSpec += relativePath; + *result = finalSpec.ToNewCString(); + if (*result) { + char* path = PL_strstr(*result,"://"); + if (path) { + path = PL_strstr((char*)(path+3),"/"); + if (path) + CoaleseDirs(path); + } + return NS_OK; + } else + return NS_ERROR_OUT_OF_MEMORY; + } + + const char *start = relativePath; + if (mScheme) { - finalSpec = mScheme; + rv = AppendString(finalSpec,mScheme,ESCAPED,nsIIOService::url_Scheme); finalSpec += "://"; } - if (mPreHost) - { - finalSpec += mPreHost; - finalSpec += '@'; - } + + rv = AppendPreHost(finalSpec,mUsername,mPassword,ESCAPED); + if (mHost) { - finalSpec += mHost; + rv = AppendString(finalSpec,mHost,ESCAPED,nsIIOService::url_Host); if (-1 != mPort) { char* portBuffer = PR_smprintf(":%d", mPort); @@ -954,52 +680,65 @@ nsStdURL::Resolve(const char *relativePath, char **result) } } - switch (*relativePath) - { + if (start) { + switch (*start) + { case '/': - finalSpec += (char*)relativePath; + finalSpec += (char*)start; break; case ';': - finalSpec += mDirectory; - finalSpec += mFileName; - finalSpec += (char*)relativePath; + rv = AppendString(finalSpec,mDirectory,ESCAPED, + nsIIOService::url_Directory); + rv = AppendFileName(finalSpec,mFileBaseName,mFileExtension, + ESCAPED); + finalSpec += (char*)start; break; case '?': - finalSpec += mDirectory; - finalSpec += mFileName; + rv = AppendString(finalSpec,mDirectory,ESCAPED, + nsIIOService::url_Directory); + rv = AppendFileName(finalSpec,mFileBaseName,mFileExtension, + ESCAPED); if (mParam) { finalSpec += ';'; - finalSpec += mParam; + rv = AppendString(finalSpec,mParam,ESCAPED, + nsIIOService::url_Param); } - finalSpec += (char*)relativePath; + finalSpec += (char*)start; break; case '#': - finalSpec += mDirectory; - finalSpec += mFileName; + rv = AppendString(finalSpec,mDirectory,ESCAPED, + nsIIOService::url_Directory); + rv = AppendFileName(finalSpec,mFileBaseName,mFileExtension, + ESCAPED); if (mParam) { finalSpec += ';'; - finalSpec += mParam; + rv = AppendString(finalSpec,mParam,ESCAPED, + nsIIOService::url_Param); } if (mQuery) { finalSpec += '?'; - finalSpec += mQuery; + rv = AppendString(finalSpec,mQuery,ESCAPED, + nsIIOService::url_Query); } - finalSpec += (char*)relativePath; + finalSpec += (char*)start; break; default: - finalSpec += mDirectory; - finalSpec += (char*)relativePath; + rv = AppendString(finalSpec,mDirectory,ESCAPED, + nsIIOService::url_Directory); + finalSpec += (char*)start; + } } *result = finalSpec.ToNewCString(); + if (*result) { char* path = PL_strstr(*result,"://"); if (path) { path = PL_strstr((char*)(path+3),"/"); if (path) - ReplaceMess(path); + CoaleseDirs(path); } return NS_OK; } else @@ -1007,275 +746,171 @@ nsStdURL::Resolve(const char *relativePath, char **result) } nsresult -nsStdURL::ReconstructPath(void) +nsStdURL::GetPath(char** o_Path) { - if (mPath) nsCRT::free(mPath); - //Take all the elements of the path and construct it nsCAutoString path; + nsresult rv = NS_OK; path.SetCapacity(64); if (mDirectory) { - path = mDirectory; - } - if (mFileName) - { - path += mFileName; + rv = AppendString(path,mDirectory,ESCAPED,nsIIOService::url_Directory); + if (NS_FAILED(rv)) + return rv; } + + rv = AppendFileName(path,mFileBaseName,mFileExtension, ESCAPED); + if (NS_FAILED(rv)) + return rv; + if (mParam) { path += ';'; - path += mParam; + rv = AppendString(path,mParam,ESCAPED,nsIIOService::url_Param); + if (NS_FAILED(rv)) + return rv; } if (mQuery) { path += '?'; - path += mQuery; + rv = AppendString(path,mQuery,ESCAPED,nsIIOService::url_Query); + if (NS_FAILED(rv)) + return rv; } if (mRef) { path += '#'; - path += mRef; + rv = AppendString(path,mRef,ESCAPED,nsIIOService::url_Ref); + if (NS_FAILED(rv)) + return rv; } - mPath = path.ToNewCString(); - - return (mPath ? ReconstructSpec() : NS_ERROR_OUT_OF_MEMORY); + *o_Path = path.ToNewCString(); + return (*o_Path ? NS_OK : NS_ERROR_OUT_OF_MEMORY); } -/** Extract the elements like directory/filename, query, or ref from - * the path. - */ nsresult -nsStdURL::ParsePath(void) +nsStdURL::GetDirectory(char** o_Directory) { - CRTFREEIF(mDirectory); - CRTFREEIF(mFileName); - CRTFREEIF(mParam); - CRTFREEIF(mQuery); - CRTFREEIF(mRef); - - if (!mPath) - { - DupString(&mDirectory, "/"); - return (mDirectory ? ReconstructPath() : NS_ERROR_OUT_OF_MEMORY); - } - - char* dirfile = nsnull; - char* options = nsnull; - - int len = PL_strlen(mPath); - - /* Factor out the optionpart with ;?# */ - static const char delimiters[] = ";?#"; // for param, query and ref - char* brk = PL_strpbrk(mPath, delimiters); - - if (!brk) // Everything is just path and filename - { - DupString(&dirfile, mPath); - } - else - { - int dirfileLen = brk - mPath; - ExtractString(mPath, &dirfile, dirfileLen); - len -= dirfileLen; - ExtractString(mPath + dirfileLen, &options, len); - brk = options; - } - - /* now that we have broken up the path treat every part differently */ - /* first dir+file */ - - char* file; - - int dlen = PL_strlen(dirfile); - if (dlen == 0) - { - DupString(&mDirectory, "/"); - file = dirfile; - } else { - ReplaceMess(dirfile); - // check new length - dlen = PL_strlen(dirfile); - - // First find the last slash - file = PL_strrchr(dirfile, '/'); - if (!file) - { - DupString(&mDirectory, "/"); - file = dirfile; - } - - // If its not the same as the first slash then extract directory - if (file != dirfile) - { - ExtractString(dirfile, &mDirectory, (file - dirfile)+1); - } else { - DupString(&mDirectory, "/"); - } - } - - /* Extract Filename */ - if (dlen > 0) { - // Look again if there was a slash - char* slash = PL_strrchr(dirfile, '/'); - if (slash) { - ExtractString(file+1, &mFileName, dlen-(file-dirfile-1)); - } else { - // Use the full String as Filename - ExtractString(dirfile, &mFileName, dlen); - } - } - -#if 0 - // Now take a look at the options. "#" has precedence over "?" - // which has precedence over ";" - if (options) { - // Look for "#" first. Everything following it is in the ref - brk = PL_strchr(options, '#'); - if (brk) { - *brk = 0; - int pieceLen = len - (brk + 1 - options); - ExtractString(brk+1, &mRef, pieceLen); - len -= pieceLen + 1; - } - - // Now look for "?" - brk = PL_strchr(options, '?'); - if (brk) { - *brk = 0; - int pieceLen = len - (brk + 1 - options); - ExtractString(brk+1, &mQuery, pieceLen); - len -= pieceLen + 1; - } - - // Now look for ';' - brk = PL_strchr(options, ';'); - if (brk) { - int pieceLen = len - (brk + 1 - options); - ExtractString(brk+1, &mParam, pieceLen); - len -= pieceLen + 1; - } - } - -#endif - while (brk) - { - int pieceLen; - char* lastbrk = brk; - brk = PL_strpbrk(lastbrk+1, delimiters); - switch (*lastbrk) - { - case ';': // handles cases of ;foo?bar#baz correctly - pieceLen = (brk ? (brk-lastbrk-1) : len); - ExtractString(lastbrk+1, &mParam, pieceLen); - len -= pieceLen; - break; - case '?': // Only # takes higher precedence than this - // so changing brk to only check for # - brk = PL_strpbrk(lastbrk+1 , "#"); - pieceLen = (brk ? (brk-lastbrk-1) : len); - ExtractString(lastbrk+1, &mQuery, pieceLen); - len -= pieceLen; - break; - case '#': - // Since this has the highest precedence everything following it - // is a ref. So... - pieceLen = len; - ExtractString(lastbrk+1, &mRef, pieceLen); - len -= pieceLen; - break; - default: - NS_ASSERTION(0, "This just can't be!"); - break; - } - } - - nsCRT::free(dirfile); - nsCRT::free(options); - - ReconstructPath(); - return NS_OK; + nsCAutoString directory; + nsresult rv = NS_OK; + rv = AppendString(directory,mDirectory,ESCAPED, + nsIIOService::url_Directory); + if (NS_FAILED(rv)) + return rv; + *o_Directory = directory.ToNewCString(); + return (*o_Directory ? NS_OK : NS_ERROR_OUT_OF_MEMORY); } NS_METHOD nsStdURL::SetSpec(const char* i_Spec) { - // Skip leading spaces + // Skip leading spaces and control-characters char* fwdPtr= (char*) i_Spec; - while (fwdPtr && (*fwdPtr != '\0') && (*fwdPtr == ' ')) + while (fwdPtr && (*fwdPtr > '\0') && (*fwdPtr <= ' ')) fwdPtr++; - // Remove trailing spaces + // Remove trailing spaces and control-characters if (fwdPtr) { char* bckPtr= (char*)fwdPtr + PL_strlen(fwdPtr) -1; - if (*bckPtr == ' ') { - while ((bckPtr-fwdPtr) >= 0 && (*bckPtr == ' ')) { + if (*bckPtr > '\0' && *bckPtr <= ' ') { + while ((bckPtr-fwdPtr) >= 0 && (*bckPtr <= ' ')) { bckPtr--; } *(bckPtr+1) = '\0'; } } - CRTFREEIF(mSpec); - nsresult status = DupString(&mSpec, fwdPtr); // If spec is being rewritten clean up everything- CRTFREEIF(mScheme); - CRTFREEIF(mPreHost); + CRTFREEIF(mUsername); + CRTFREEIF(mPassword); CRTFREEIF(mHost); mPort = -1; - CRTFREEIF(mPath); CRTFREEIF(mDirectory); - CRTFREEIF(mFileName); + CRTFREEIF(mFileBaseName); + CRTFREEIF(mFileExtension); CRTFREEIF(mParam); CRTFREEIF(mQuery); CRTFREEIF(mRef); - return (NS_FAILED(status) ? status : Parse()); + return Parse(fwdPtr); +} + +NS_METHOD +nsStdURL::SetPreHost(const char* i_PreHost) +{ + NS_PRECONDITION( (nsnull != mURLParser), "Parse called without parser!"); + if (!mURLParser) + return NS_ERROR_NULL_POINTER; + + CRTFREEIF(mUsername); + CRTFREEIF(mPassword); + + return mURLParser->ParsePreHost(i_PreHost,&mUsername,&mPassword); } NS_METHOD nsStdURL::SetPath(const char* i_Path) { - if (mPath) nsCRT::free(mPath); - nsresult status = DupString(&mPath, i_Path); - ParsePath(); - ReconstructSpec(); - return status; + NS_PRECONDITION( (nsnull != mURLParser), "Parse called without parser!"); + if (!mURLParser) + return NS_ERROR_NULL_POINTER; + + CRTFREEIF(mDirectory); + CRTFREEIF(mFileBaseName); + CRTFREEIF(mFileExtension); + CRTFREEIF(mParam); + CRTFREEIF(mQuery); + CRTFREEIF(mRef); + + return mURLParser->ParseAtDirectory((char*)i_Path, &mDirectory, + &mFileBaseName, + &mFileExtension, &mParam, + &mQuery, &mRef); } - + NS_METHOD nsStdURL::GetFilePath(char **o_DirFile) { if (!o_DirFile) return NS_ERROR_NULL_POINTER; - - nsAutoString temp; + + nsresult rv = NS_OK; + nsCAutoString temp; if (mDirectory) { - temp = mDirectory; - } - if (mFileName) - { - temp += mFileName; + rv = AppendString(temp,mDirectory,ESCAPED,nsIIOService::url_Directory); } + + rv = AppendFileName(temp,mFileBaseName,mFileExtension,ESCAPED); + if (NS_FAILED(rv)) + return rv; + *o_DirFile = temp.ToNewCString(); if (!*o_DirFile) return NS_ERROR_OUT_OF_MEMORY; return NS_OK; } +NS_METHOD +nsStdURL::GetFileName(char **o_FileName) +{ + if (!o_FileName) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_OK; + nsCAutoString temp; + + rv = AppendFileName(temp,mFileBaseName,mFileExtension,ESCAPED); + if (NS_FAILED(rv)) + return rv; + + *o_FileName = temp.ToNewCString(); + if (!*o_FileName) + return NS_ERROR_OUT_OF_MEMORY; + return NS_OK; +} + NS_METHOD nsStdURL::SetFilePath(const char *filePath) { - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_METHOD -nsStdURL::GetFileBaseName(char **o_name) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_METHOD -nsStdURL::SetFileBaseName(const char *name) -{ - return NS_ERROR_NOT_IMPLEMENTED; + return SetPath(filePath); } diff --git a/netwerk/base/src/nsStdURL.h b/netwerk/base/src/nsStdURL.h index 6d878d18db7..e83abf24cab 100644 --- a/netwerk/base/src/nsStdURL.h +++ b/netwerk/base/src/nsStdURL.h @@ -24,6 +24,8 @@ #define nsStdURL_h__ #include "nsIURL.h" +#include "nsIURLParser.h" +#include "nsURLHelper.h" #include "nsAgg.h" #include "nsCRT.h" #include "nsString.h" // REMOVE Later!! @@ -39,9 +41,10 @@ class nsStdURL : public nsIURL { public: - //////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// // nsStdURL methods: + nsStdURL(); nsStdURL(const char* i_Spec, nsISupports* outer=nsnull); nsStdURL(const nsStdURL& i_URL); virtual ~nsStdURL(); @@ -54,156 +57,67 @@ public: NS_DECL_AGGREGATED - //////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// // nsIURI methods: NS_DECL_NSIURI - //////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// // nsIURL methods: NS_DECL_NSIURL - /* todo move this to protected later */ - nsresult ParsePath(void); - protected: - nsresult Parse(void); - nsresult ReconstructPath(void); - nsresult ReconstructSpec(void); + enum Format { ESCAPED, UNESCAPED }; + nsresult Parse(const char* i_Spec); + nsresult AppendString(nsCString& buffer, char* fromUnescapedStr, + Format toFormat, PRInt16 mask); + nsresult GetString(char** result, char* fromEscapedStr, + Format toFormat); + nsresult AppendPreHost(nsCString& buffer, char* i_Username, + char* i_Password, Format toFormat); + nsresult AppendFileName(nsCString& buffer, char* i_FileBaseName, + char* i_FileExtension, Format toFormat); - // Some handy functions - nsresult DupString(char* *o_Dest, const char* i_Src); - nsresult ExtractString(char* i_Src, char* *o_Dest, PRUint32 length); protected: char* mScheme; - char* mPreHost; + char* mUsername; + char* mPassword; char* mHost; PRInt32 mPort; - char* mPath; char* mDirectory; - char* mFileName; + char* mFileBaseName; + char* mFileExtension; char* mParam; char* mQuery; char* mRef; - char* mSpec; + nsIURLParser* mURLParser; }; -inline NS_METHOD -nsStdURL::GetSpec(char* *o_Spec) -{ - return DupString(o_Spec, mSpec); -} - inline NS_METHOD nsStdURL::GetScheme(char* *o_Scheme) { - return DupString(o_Scheme, mScheme); + return GetString(o_Scheme, mScheme, UNESCAPED); } inline NS_METHOD -nsStdURL::GetPreHost(char* *o_PreHost) +nsStdURL::GetUsername(char* *o_Username) { - return DupString(o_PreHost, mPreHost); + return GetString(o_Username, mUsername, UNESCAPED); +} + +inline NS_METHOD +nsStdURL::GetPassword(char* *o_Password) +{ + return GetString(o_Password, mPassword, UNESCAPED); } inline NS_METHOD nsStdURL::GetHost(char* *o_Host) { - return DupString(o_Host, mHost); -} - -inline NS_METHOD -nsStdURL::GetPath(char* *o_Path) -{ - return DupString(o_Path, mPath); -} - -inline NS_METHOD -nsStdURL::GetDirectory(char* *o_Directory) -{ - return DupString(o_Directory, mDirectory); -} - -inline NS_METHOD -nsStdURL::GetFileName(char* *o_FileName) -{ - return DupString(o_FileName, mFileName); -} - -inline NS_METHOD -nsStdURL::GetFileExtension(char* *o_FileExtension) -{ - if (!o_FileExtension) - return NS_ERROR_NULL_POINTER; - - char *dot = mFileName; - if (dot) { - // find the last dot - while (*dot) dot++; - while ( (dot != mFileName) && (*dot != '.') ) dot--; // goto the dot. - if (*dot == '.') { - nsCAutoString ext(dot+1); - *o_FileExtension = ext.ToNewCString(); - if (!*o_FileExtension) return NS_ERROR_OUT_OF_MEMORY; - } else { - *o_FileExtension = nsnull; - } - } - return NS_OK; -} - -inline NS_METHOD -nsStdURL::SetFileExtension(const char* FileExtension) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -inline NS_METHOD -nsStdURL::GetRef(char* *o_Ref) -{ - return DupString(o_Ref, mRef); -} - -inline NS_METHOD -nsStdURL::GetParam(char **o_Param) -{ - return DupString(o_Param, mParam); -} - -inline NS_METHOD -nsStdURL::GetQuery(char* *o_Query) -{ - return DupString(o_Query, mQuery); -} - -inline NS_METHOD -nsStdURL::SetScheme(const char* i_Scheme) -{ - if (mScheme) nsCRT::free(mScheme); - nsresult status = DupString(&mScheme, i_Scheme); - ReconstructSpec(); - return status; -} - -inline NS_METHOD -nsStdURL::SetPreHost(const char* i_PreHost) -{ - if (mPreHost) nsCRT::free(mPreHost); - nsresult status = DupString(&mPreHost, i_PreHost); - ReconstructSpec(); - return status; -} - -inline NS_METHOD -nsStdURL::SetHost(const char* i_Host) -{ - if (mHost) nsCRT::free(mHost); - nsresult status = DupString(&mHost, i_Host); - ReconstructSpec(); - return status; + return GetString(o_Host, mHost, UNESCAPED); } inline NS_METHOD @@ -217,12 +131,84 @@ nsStdURL::GetPort(PRInt32 *aPort) return NS_ERROR_NULL_POINTER; } +inline NS_METHOD +nsStdURL::GetFileBaseName(char* *o_FileBaseName) +{ + return GetString(o_FileBaseName, mFileBaseName, UNESCAPED); +} + +inline NS_METHOD +nsStdURL::GetFileExtension(char* *o_FileExtension) +{ + return GetString(o_FileExtension, mFileExtension, UNESCAPED); +} + +inline NS_METHOD +nsStdURL::GetParam(char **o_Param) +{ + return GetString(o_Param, mParam, UNESCAPED); +} + +inline NS_METHOD +nsStdURL::GetQuery(char* *o_Query) +{ + return GetString(o_Query, mQuery, UNESCAPED); +} + +inline NS_METHOD +nsStdURL::GetRef(char* *o_Ref) +{ + return GetString(o_Ref, mRef, UNESCAPED); +} + +inline NS_METHOD +nsStdURL::SetScheme(const char* i_Scheme) +{ + CRTFREEIF(mScheme); + return DupString(&mScheme, i_Scheme); +} + +inline NS_METHOD +nsStdURL::SetUsername(const char* i_Username) +{ + CRTFREEIF(mUsername); + return DupString(&mUsername, i_Username); +} + +inline NS_METHOD +nsStdURL::SetPassword(const char* i_Password) +{ + CRTFREEIF(mPassword); + return DupString(&mPassword, i_Password); +} + +inline NS_METHOD +nsStdURL::SetHost(const char* i_Host) +{ + CRTFREEIF(mHost); + return DupString(&mHost, i_Host); +} + inline NS_METHOD nsStdURL::SetPort(PRInt32 aPort) { mPort = aPort; - ReconstructSpec(); return NS_OK; } +inline NS_METHOD +nsStdURL::SetFileBaseName(const char* i_FileBaseName) +{ + CRTFREEIF(mFileBaseName); + return DupString(&mFileBaseName, i_FileBaseName); +} + +inline NS_METHOD +nsStdURL::SetFileExtension(const char* i_FileExtension) +{ + CRTFREEIF(mFileExtension); + return DupString(&mFileExtension, i_FileExtension); +} + #endif // nsStdURL_h__ + diff --git a/netwerk/build/nsNetModule.cpp b/netwerk/build/nsNetModule.cpp index c9a54da87d8..e696404e67a 100644 --- a/netwerk/build/nsNetModule.cpp +++ b/netwerk/build/nsNetModule.cpp @@ -30,6 +30,9 @@ #include "nsSocketTransportService.h" #include "nsSocketProviderService.h" #include "nscore.h" +#include "nsStdURLParser.h" +#include "nsAuthURLParser.h" +#include "nsNoAuthURLParser.h" #include "nsStdURL.h" #include "nsSimpleURI.h" #include "nsDnsService.h" @@ -98,7 +101,20 @@ static nsModuleComponentInfo gNetModuleInfo[] = { { "Load Group", NS_LOADGROUP_CID, "component://netscape/network/load-group", - nsLoadGroup::Create } + nsLoadGroup::Create }, + { "StdURLParser", + NS_STANDARDURLPARSER_CID, + "component://netscape/network/standard-urlparser", + nsStdURLParser::Create }, + { "AuthURLParser", + NS_AUTHORITYURLPARSER_CID, + "component://netscape/network/authority-urlparser", + nsAuthURLParser::Create }, + { "NoAuthURLParser", + NS_NOAUTHORITYURLPARSER_CID, + "component://netscape/network/no-authority-urlparser", + nsNoAuthURLParser::Create }, }; NS_IMPL_NSGETMODULE("net", gNetModuleInfo) + diff --git a/netwerk/macbuild/netwerk.mcp b/netwerk/macbuild/netwerk.mcp index 47b05d09feae0a01659f3f78a5361a9dea1a722f..0f9821f9b4b4e86206b29807b1c0b0eaf44c5d3e 100644 GIT binary patch delta 699 zcmZ4Sj(Np9<_)`rLuD8k7-WH14v6J}SOJ6?fdmkn0;wnB-7Fw-f!!mo*s-)EBQ(e-AhD=8wMZ|ypnxH-*e@TO zXmCjixWWwP^B%1cl8HTz@f6c9JV$44b@J&YLlO@^3kF!3dyzmOvZ`#M(d{ zIoVpiWb%Ib0s)}wjeyt~h)salbh5reF)xZ=H}6;QV$)(>2-Fr1#6ZBh6-a=L1OnF6 zKq3;%WMI7qq@yM}`c3YA!n?Uoy`F^wXrvKPFnn^sD+Lh87|4l$aZG@mNEinkh9Hgv zP?Q;nxu7)1mL<|9|Nl>1xw-a<5Yxl}*2#DDq}Z28NB;kRwR7`D*WZkje;9~?1Q-~^ zCIJN)nKp|Vd#eZl1K0?Nje*z%9N2~7a?FfElP5%ZPktTcu~|9#Pn@8zo2QQ}P*xmD z8%@^OrOv20*<+WzqA^rV0ZN-dX^*MmffCZK^ zD=egxSz*DX%nA>q$qU|nXKdI!OzbXa-ZC(_WNl_t{LMJ|hk+PK;Q#*vFM$G#Oq<1wy;UaviBjF%7S74c zC^C6MlsC6510UEvIR>W5*P?tk8%Mv1CdBN)gjGNb8b7b87bsx7r(AkS7FM9Wtv0(Fz h_u|ZqOD1plB+ke%`NSt@M*Yb=pN)YM4xe8z0|1@da2@~v diff --git a/netwerk/macbuild/netwerkIDL.mcp b/netwerk/macbuild/netwerkIDL.mcp index 9a077f6823c68c1542958a8345a273f4dd6d5705..20dfd90c851a94b661142d8555428cd13c2e5d6b 100644 GIT binary patch delta 627 zcmYMy%`XE%6aeryyGxh06ruFH(uRw~i30}`m6T0N>#K24X(S}-tLq>ky*jwmoH&s< zNJO&9IB{`wXyW1@a1l-%9HNO^r{msmqdAl>S4^PU&lVXiKoqhlaF??VRi#cbx z&asw{PbZCu#jX6(7QbB$iH!SEHcDV4~FrjRJ2Olik za-BHkgYg+7!6%bpO(rT1r^S78Z&sHbTtwU0k=rOhGLe|7rjq(c<3qr}^RV)D1&_FHOL^hHxvYBilTgf)kO}3LAq=yWUVN(7ZjK5yI_n0|z pbse|&+=UUO4Jmt%LSF4@D0n$OmSe{DZjY)f`b46 delta 564 zcmYk(&r1S96bJA(yIcOKElqMOMOV-Y%D+H@I`mu6L@J6X@KT_-kyo)lz{@fxp^K*u zQ7ufj&QXV;i^rftAYH-^9l{8ED^F_S?PumY!<$*Q(UclZ$y!&{AOPqLUs$@>R@*Lq zmk)?j?L{`zKK@ZuL@sbEnagv0H}uG7!f`XLi0$x!Vy4gSWuA*3a-nJLZK&&O} z%u$P61C(FIvG&dQd&+MIoz71JgD=K6lPSKDiI@v};we+!GShYYk`>6LQdzrI?+Grg zCKs{4o0P~fsggtFAUQxXQYM|Gi*%4m*9t%%1^uL#940;F2Clone(&url); if (NS_FAILED(rv)) return rv; rv = url->SetRelativePath(aSpec); } else { - rv = nsComponentManager::CreateInstance(kStandardURLCID, nsnull, - NS_GET_IID(nsIURI), - (void**)&url); + rv = nsComponentManager::CreateInstance(kNoAuthUrlParserCID, + nsnull, NS_GET_IID(nsIURLParser), + (void**)&urlparser); if (NS_FAILED(rv)) return rv; + rv = nsComponentManager::CreateInstance(kStandardUrlCID, + nsnull, NS_GET_IID(nsIURI), + (void**)&url); + if (NS_FAILED(rv)) { + NS_RELEASE(urlparser); + return rv; + } + rv = url->SetURLParser(urlparser); + if (NS_FAILED(rv)) { + NS_RELEASE(urlparser); + NS_RELEASE(url); + return rv; + } rv = url->SetSpec((char*)aSpec); } diff --git a/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp b/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp index e2e5f94c117..c5f77386f64 100644 --- a/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp +++ b/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp @@ -23,6 +23,7 @@ #include "nsFtpProtocolHandler.h" #include "nsFTPChannel.h" #include "nsIURL.h" +#include "nsAuthURLParser.h" #include "nsCRT.h" #include "nsIComponentManager.h" #include "nsIInterfaceRequestor.h" @@ -46,7 +47,8 @@ PRLogModuleInfo* gFTPLog = nsnull; #endif /* PR_LOGGING */ -static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID); +static NS_DEFINE_CID(kStandardUrlCID, NS_STANDARDURL_CID); +static NS_DEFINE_CID(kAuthUrlParserCID, NS_AUTHORITYURLPARSER_CID); //////////////////////////////////////////////////////////////////////////////// @@ -130,17 +132,31 @@ nsFtpProtocolHandler::NewURI(const char *aSpec, nsIURI *aBaseURI, nsresult rv; PR_LOG(gFTPLog, PR_LOG_ALWAYS, ("FTP attempt at %s ", aSpec)); - nsIURI* url; + nsIURI* url = nsnull; + nsIURLParser* urlparser = nsnull; if (aBaseURI) { rv = aBaseURI->Clone(&url); if (NS_FAILED(rv)) return rv; rv = url->SetRelativePath(aSpec); } else { - rv = nsComponentManager::CreateInstance(kStandardURLCID, nsnull, - NS_GET_IID(nsIURI), - (void**)&url); + rv = nsComponentManager::CreateInstance(kAuthUrlParserCID, + nsnull, NS_GET_IID(nsIURLParser), + (void**)&urlparser); if (NS_FAILED(rv)) return rv; + rv = nsComponentManager::CreateInstance(kStandardUrlCID, + nsnull, NS_GET_IID(nsIURI), + (void**)&url); + if (NS_FAILED(rv)) { + NS_RELEASE(urlparser); + return rv; + } + rv = url->SetURLParser(urlparser); + if (NS_FAILED(rv)) { + NS_RELEASE(urlparser); + NS_RELEASE(url); + return rv; + } rv = url->SetSpec((char*)aSpec); } if (NS_FAILED(rv)) { diff --git a/netwerk/protocol/http/src/nsHTTPHandler.cpp b/netwerk/protocol/http/src/nsHTTPHandler.cpp index 365aaf2cb20..c7e07df6dfa 100644 --- a/netwerk/protocol/http/src/nsHTTPHandler.cpp +++ b/netwerk/protocol/http/src/nsHTTPHandler.cpp @@ -39,6 +39,8 @@ #include "nsHTTPEncodeStream.h" #include "nsHTTPAtoms.h" #include "nsFileSpec.h" +#include "nsAuthURLParser.h" + #include "nsIPref.h" // preferences stuff #ifdef DEBUG_gagan #include "nsUnixColorPrintf.h" @@ -63,6 +65,7 @@ PRLogModuleInfo* gHTTPLog = nsnull; #define MAX_NUMBER_OF_OPEN_TRANSPORTS 8 static NS_DEFINE_CID(kStandardUrlCID, NS_STANDARDURL_CID); +static NS_DEFINE_CID(kAuthUrlParserCID, NS_AUTHORITYURLPARSER_CID); static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID); static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); @@ -264,6 +267,7 @@ nsHTTPHandler::NewURI(const char *aSpec, nsIURI *aBaseURI, nsresult rv; nsIURI* url = nsnull; + nsIURLParser* urlparser = nsnull; if (aBaseURI) { rv = aBaseURI->Clone(&url); @@ -272,10 +276,23 @@ nsHTTPHandler::NewURI(const char *aSpec, nsIURI *aBaseURI, } else { + rv = nsComponentManager::CreateInstance(kAuthUrlParserCID, + nsnull, NS_GET_IID(nsIURLParser), + (void**)&urlparser); + if (NS_FAILED(rv)) return rv; rv = nsComponentManager::CreateInstance(kStandardUrlCID, nsnull, NS_GET_IID(nsIURI), (void**)&url); - if (NS_FAILED(rv)) return rv; + if (NS_FAILED(rv)) { + NS_RELEASE(urlparser); + return rv; + } + rv = url->SetURLParser(urlparser); + if (NS_FAILED(rv)) { + NS_RELEASE(urlparser); + NS_RELEASE(url); + return rv; + } rv = url->SetSpec((char*)aSpec); } if (NS_FAILED(rv)) { diff --git a/netwerk/protocol/jar/src/nsJARURI.cpp b/netwerk/protocol/jar/src/nsJARURI.cpp index 74804bb673c..77e8a5ad7b1 100644 --- a/netwerk/protocol/jar/src/nsJARURI.cpp +++ b/netwerk/protocol/jar/src/nsJARURI.cpp @@ -157,6 +157,30 @@ nsJARURI::SetPreHost(const char * aPreHost) return NS_ERROR_FAILURE; } +NS_IMETHODIMP +nsJARURI::GetUsername(char * *aUsername) +{ + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsJARURI::SetUsername(const char * aUsername) +{ + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsJARURI::GetPassword(char * *aPassword) +{ + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsJARURI::SetPassword(const char * aPassword) +{ + return NS_ERROR_FAILURE; +} + NS_IMETHODIMP nsJARURI::GetHost(char * *aHost) { @@ -193,6 +217,18 @@ nsJARURI::SetPath(const char * aPath) return NS_ERROR_FAILURE; } +NS_IMETHODIMP +nsJARURI::GetURLParser(nsIURLParser * *aURLParser) +{ + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsJARURI::SetURLParser(nsIURLParser * aURLParser) +{ + return NS_ERROR_FAILURE; +} + NS_IMETHODIMP nsJARURI::Equals(nsIURI *other, PRBool *_retval) { diff --git a/netwerk/protocol/res/src/nsResChannel.cpp b/netwerk/protocol/res/src/nsResChannel.cpp index ac0fa42318f..08c36078346 100644 --- a/netwerk/protocol/res/src/nsResChannel.cpp +++ b/netwerk/protocol/res/src/nsResChannel.cpp @@ -121,7 +121,7 @@ nsResChannel::Substitutions::Init() NS_ASSERTION(mSubstitutions == nsnull, "failed to call destructor"); - char* root; + char* root = nsnull; rv = channel->mResourceURI->GetHost(&root); if (NS_SUCCEEDED(rv)) { rv = channel->mHandler->GetSubstitutions(root, &mSubstitutions); diff --git a/rdf/base/src/nsRDFXMLDataSource.cpp b/rdf/base/src/nsRDFXMLDataSource.cpp index 6cd05c14881..e685e8845c9 100644 --- a/rdf/base/src/nsRDFXMLDataSource.cpp +++ b/rdf/base/src/nsRDFXMLDataSource.cpp @@ -637,7 +637,7 @@ static const char kResourceURIPrefix[] = "resource:"; // XXX this is a hack: any "file:" URI is considered writable. All // others are considered read-only. - char* realURL; + char* realURL = nsnull; mURL->GetSpec(&realURL); if ((PL_strncmp(realURL, kFileURIPrefix, sizeof(kFileURIPrefix) - 1) != 0) && (PL_strncmp(realURL, kResourceURIPrefix, sizeof(kResourceURIPrefix) - 1) != 0)) {