From 867f16ef2bd2711645088d0130e08bce49397446 Mon Sep 17 00:00:00 2001 From: "valeski%netscape.com" Date: Thu, 3 Feb 2000 03:44:22 +0000 Subject: [PATCH] URL Parsing and implementation rewrite landing. Andreas Otte was generous enough to contribute these changes git-svn-id: svn://10.0.0.236/trunk@59615 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/docshell/base/nsWebShell.cpp | 19 +- mozilla/mailnews/base/util/nsMsgFolder.cpp | 15 +- .../mailnews/base/util/nsMsgMailNewsUrl.cpp | 30 + mozilla/mailnews/compose/src/nsSmtpUrl.cpp | 29 + .../mailnews/imap/src/nsImapMailFolder.cpp | 2 +- mozilla/mailnews/imap/src/nsImapUrl.cpp | 2 + mozilla/mailnews/local/src/nsParseMailbox.cpp | 22 +- mozilla/modules/libjar/nsJARURI.cpp | 36 + mozilla/netwerk/base/public/MANIFEST_IDL | 1 + mozilla/netwerk/base/public/Makefile.in | 1 + mozilla/netwerk/base/public/makefile.win | 7 +- mozilla/netwerk/base/public/nsIIOService.idl | 14 + mozilla/netwerk/base/public/nsIURI.idl | 11 + mozilla/netwerk/base/src/Makefile.in | 4 + mozilla/netwerk/base/src/makefile.win | 4 + mozilla/netwerk/base/src/nsAuthURLParser.cpp | 23 +- mozilla/netwerk/base/src/nsIOService.cpp | 11 +- mozilla/netwerk/base/src/nsIOService.h | 1 + mozilla/netwerk/base/src/nsSimpleURI.cpp | 40 +- mozilla/netwerk/base/src/nsStdURL.cpp | 1368 ++++++----------- mozilla/netwerk/base/src/nsStdURL.h | 232 ++- mozilla/netwerk/base/src/nsStdURLParser.cpp | 27 +- mozilla/netwerk/base/src/nsURLHelper.cpp | 6 +- mozilla/netwerk/build/nsNetModule.cpp | 17 +- .../file/src/nsFileProtocolHandler.cpp | 24 +- .../protocol/ftp/src/nsFtpProtocolHandler.cpp | 24 +- .../protocol/http/src/nsHTTPHandler.cpp | 18 +- mozilla/netwerk/protocol/jar/src/nsJARURI.cpp | 36 + .../protocol/res/src/nsResProtocolHandler.cpp | 2 +- mozilla/webshell/src/nsWebShell.cpp | 19 +- .../directory/nsDirectoryViewer.cpp | 11 +- 31 files changed, 1022 insertions(+), 1034 deletions(-) diff --git a/mozilla/docshell/base/nsWebShell.cpp b/mozilla/docshell/base/nsWebShell.cpp index c40a71f86b0..ee0f4f3a46c 100644 --- a/mozilla/docshell/base/nsWebShell.cpp +++ b/mozilla/docshell/base/nsWebShell.cpp @@ -20,6 +20,7 @@ * Contributor(s): * Pierre Phaneuf */ + #include "nsDocShell.h" #include "nsIWebShell.h" #include "nsIInterfaceRequestor.h" @@ -1440,18 +1441,29 @@ nsWebShell::GetDocumentLoader(nsIDocumentLoader*& aResult) return (nsnull != mDocLoader) ? NS_OK : NS_ERROR_FAILURE; } -#define FILE_PROTOCOL "file:///" +#define FILE_PROTOCOL "file://" static void convertFileToURL(const nsString &aIn, nsString &aOut) { -#ifdef XP_PC char szFile[1000]; aIn.ToCString(szFile, sizeof(szFile)); +#ifdef XP_PC + // Check for \ in the url-string (PC) if (PL_strchr(szFile, '\\')) { +#else +#if XP_UNIX + // Check if it starts with / or \ (UNIX) + if (*(szFile) == '/' || *(szFile) == '\\') { +#else + if (0) { + // Do nothing (All others for now) +#endif +#endif PRInt32 len = strlen(szFile); PRInt32 sum = len + sizeof(FILE_PROTOCOL); char* lpszFileURL = (char *)PR_Malloc(sum + 1); +#ifdef XP_PC // Translate '\' to '/' for (PRInt32 i = 0; i < len; i++) { if (szFile[i] == '\\') { @@ -1461,6 +1473,7 @@ static void convertFileToURL(const nsString &aIn, nsString &aOut) szFile[i] = '|'; } } +#endif // Build the file URL PR_snprintf(lpszFileURL, sum, "%s%s", FILE_PROTOCOL, szFile); @@ -1468,7 +1481,6 @@ static void convertFileToURL(const nsString &aIn, nsString &aOut) PR_Free((void *)lpszFileURL); } else -#endif { aOut = aIn; } @@ -1802,6 +1814,7 @@ nsWebShell::DoContent(const char * aContentType, if (NS_SUCCEEDED(rv)) pURILoader->GetStringForCommand(aCommand, getter_Copies(strCommand)); + // determine if the channel has just been retargeted to us... nsLoadFlags loadAttribs = 0; aOpenedChannel->GetLoadAttributes(&loadAttribs); diff --git a/mozilla/mailnews/base/util/nsMsgFolder.cpp b/mozilla/mailnews/base/util/nsMsgFolder.cpp index 1d08fe7fd93..73b1b00542b 100644 --- a/mozilla/mailnews/base/util/nsMsgFolder.cpp +++ b/mozilla/mailnews/base/util/nsMsgFolder.cpp @@ -42,10 +42,12 @@ #include "nsIAllocator.h" #include "nsIURL.h" #include "nsMsgUtils.h" // for NS_MsgHashIfNecessary() +#include "nsIIOService.h" static NS_DEFINE_CID(kStandardUrlCID, NS_STANDARDURL_CID); static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); static NS_DEFINE_CID(kMsgMailSessionCID, NS_MSGMAILSESSION_CID); +static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); PRInt32 nsMsgFolder::gInstanceCount = 0; @@ -448,6 +450,8 @@ nsMsgFolder::parseURI(PRBool needServer) rv = url->SetSpec(mURI); if (NS_FAILED(rv)) return rv; + NS_WITH_SERVICE(nsIIOService, ioServ, kIOServiceCID, &rv); + // // pull some info out of the URI // @@ -473,7 +477,10 @@ nsMsgFolder::parseURI(PRBool needServer) rv = url->GetFileName(getter_Copies(fileName)); if (NS_SUCCEEDED(rv)) { // XXX conversion to unicode here? is fileName in UTF8? - mName = fileName; + + char* result = nsnull; + rv = ioServ->Unescape(fileName, &result); + mName = result; } } @@ -541,6 +548,9 @@ nsMsgFolder::parseURI(PRBool needServer) nsXPIDLCString urlPath; url->GetFilePath(getter_Copies(urlPath)); + char* result = nsnull; + rv = ioServ->Unescape(urlPath, &result); + // transform the filepath from the URI, such as // "/folder1/folder2/foldern" // to @@ -553,7 +563,7 @@ nsMsgFolder::parseURI(PRBool needServer) char *newStr=nsnull; nsCAutoString hashedToken; char *token = - nsCRT::strtok(NS_CONST_CAST(char *,(const char*)urlPath), "/", &newStr); + nsCRT::strtok(NS_CONST_CAST(char *,(const char*)result), "/", &newStr); // trick to make sure we only add the path to the first n-1 folders PRBool haveFirst=PR_FALSE; @@ -593,6 +603,7 @@ nsMsgFolder::parseURI(PRBool needServer) // URI is completely parsed when we've attempted to get the server mHaveParsedURI=PR_TRUE; + CRTFREEIF(result); } return NS_OK; diff --git a/mozilla/mailnews/base/util/nsMsgMailNewsUrl.cpp b/mozilla/mailnews/base/util/nsMsgMailNewsUrl.cpp index dd19ca694e5..cc3f3e9770f 100644 --- a/mozilla/mailnews/base/util/nsMsgMailNewsUrl.cpp +++ b/mozilla/mailnews/base/util/nsMsgMailNewsUrl.cpp @@ -320,6 +320,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,6 +370,16 @@ 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); diff --git a/mozilla/mailnews/compose/src/nsSmtpUrl.cpp b/mozilla/mailnews/compose/src/nsSmtpUrl.cpp index cbfa7a9764e..99bf1b566e8 100644 --- a/mozilla/mailnews/compose/src/nsSmtpUrl.cpp +++ b/mozilla/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); @@ -353,6 +373,15 @@ NS_IMETHODIMP nsMailtoUrl::Equals(nsIURI *other, PRBool *_retval) return m_baseURL->Equals(other, _retval); } +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::Clone(nsIURI **_retval) { diff --git a/mozilla/mailnews/imap/src/nsImapMailFolder.cpp b/mozilla/mailnews/imap/src/nsImapMailFolder.cpp index b60e1ec2660..4c409b0c2d0 100644 --- a/mozilla/mailnews/imap/src/nsImapMailFolder.cpp +++ b/mozilla/mailnews/imap/src/nsImapMailFolder.cpp @@ -3188,7 +3188,7 @@ NS_IMETHODIMP nsImapMailFolder::GetPath(nsIFileSpec ** aPathName) return NS_ERROR_OUT_OF_MEMORY; rv = nsImapURI2Path(kImapRootURI, mURI, *m_pathName); -// printf("constructing path %s\n", (const char *) *m_pathName); + // printf("constructing path %s\n", (const char *) *m_pathName); if (NS_FAILED(rv)) return rv; } rv = NS_NewFileSpecWithSpec(*m_pathName, aPathName); diff --git a/mozilla/mailnews/imap/src/nsImapUrl.cpp b/mozilla/mailnews/imap/src/nsImapUrl.cpp index 188524596e1..160c13c56a0 100644 --- a/mozilla/mailnews/imap/src/nsImapUrl.cpp +++ b/mozilla/mailnews/imap/src/nsImapUrl.cpp @@ -275,6 +275,7 @@ nsresult nsImapUrl::ParseUrl() char * imapPartOfUrl = nsnull; rv = GetPath(&imapPartOfUrl); + imapPartOfUrl = nsUnescape(imapPartOfUrl); if (NS_SUCCEEDED(rv) && imapPartOfUrl && imapPartOfUrl+1) { ParseImapPart(imapPartOfUrl+1); // GetPath leaves leading '/' in the path!!! @@ -410,6 +411,7 @@ void nsImapUrl::ParseImapPart(char *imapPartOfUrl) { m_tokenPlaceHolder = imapPartOfUrl; m_urlidSubString = m_tokenPlaceHolder ? nsIMAPGenericParser::Imapstrtok_r(nsnull, IMAP_URL_TOKEN_SEPARATOR, &m_tokenPlaceHolder) : (char *)NULL; + if (!m_urlidSubString) { m_validUrl = PR_FALSE; diff --git a/mozilla/mailnews/local/src/nsParseMailbox.cpp b/mozilla/mailnews/local/src/nsParseMailbox.cpp index 5b31db3bb7d..7d713df7621 100644 --- a/mozilla/mailnews/local/src/nsParseMailbox.cpp +++ b/mozilla/mailnews/local/src/nsParseMailbox.cpp @@ -44,13 +44,14 @@ #include "nsIMsgFilterService.h" #include "nsIMsgFilterList.h" #include "nsIMsgFilter.h" - +#include "nsIIOService.h" #include "nsIPref.h" static NS_DEFINE_CID(kCMailDB, NS_MAILDB_CID); static NS_DEFINE_CID(kMsgFilterServiceCID, NS_MSGFILTERSERVICE_CID); static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); +static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); /* the following macros actually implement addref, release and query interface for our component. */ NS_IMPL_ISUPPORTS_INHERITED(nsMsgMailboxParser, nsParseMailMessageState, nsIStreamListener); @@ -79,6 +80,7 @@ NS_IMETHODIMP nsMsgMailboxParser::OnStartRequest(nsIChannel * /* aChannel */, ns // we have an error. nsresult rv = NS_OK; + NS_WITH_SERVICE(nsIIOService, ioServ, kIOServiceCID, &rv); nsCOMPtr runningUrl = do_QueryInterface(ctxt, &rv); @@ -90,12 +92,20 @@ NS_IMETHODIMP nsMsgMailboxParser::OnStartRequest(nsIChannel * /* aChannel */, ns // okay, now fill in our event sinks...Note that each getter ref counts before // it returns the interface to us...we'll release when we are done - nsXPIDLCString fileName; - url->GetFilePath(getter_Copies(fileName)); - url->GetFileName(getter_Copies(m_folderName)); + nsXPIDLCString fileName; + nsXPIDLCString folderName; + rv = url->GetFilePath(getter_Copies(fileName)); + url->GetFileName(getter_Copies(folderName)); + char* tempfolder = nsnull; + rv = ioServ->Unescape(folderName, &tempfolder); + m_folderName = tempfolder; + CRTFREEIF(tempfolder); if (fileName) { - nsFilePath dbPath(fileName); + char* result = nsnull; + rv = ioServ->Unescape(fileName, &result); + nsFilePath dbPath(result); + CRTFREEIF(result); nsFileSpec dbName(dbPath); // the size of the mailbox file is our total base line for measuring progress @@ -115,7 +125,7 @@ NS_IMETHODIMP nsMsgMailboxParser::OnStartRequest(nsIChannel * /* aChannel */, ns printf("url file = %s\n", (const char *)fileName); #endif } - } + } // need to get the mailbox name out of the url and call SetMailboxName with it. // then, we need to open the mail db for this parser. diff --git a/mozilla/modules/libjar/nsJARURI.cpp b/mozilla/modules/libjar/nsJARURI.cpp index d89236e9fc3..d19da020682 100644 --- a/mozilla/modules/libjar/nsJARURI.cpp +++ b/mozilla/modules/libjar/nsJARURI.cpp @@ -151,6 +151,30 @@ nsJARURI::SetScheme(const char * aScheme) 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::GetPreHost(char * *aPreHost) { @@ -199,6 +223,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 *result) { diff --git a/mozilla/netwerk/base/public/MANIFEST_IDL b/mozilla/netwerk/base/public/MANIFEST_IDL index 6a4473c9ef6..18e1e0dfbff 100644 --- a/mozilla/netwerk/base/public/MANIFEST_IDL +++ b/mozilla/netwerk/base/public/MANIFEST_IDL @@ -13,3 +13,4 @@ nsIFileTransportService.idl nsIFileSystem.idl nsIPrompt.idl nsIStreamLoader.idl +nsIURLParser.idl diff --git a/mozilla/netwerk/base/public/Makefile.in b/mozilla/netwerk/base/public/Makefile.in index d6221a3419d..c72cd92c524 100644 --- a/mozilla/netwerk/base/public/Makefile.in +++ b/mozilla/netwerk/base/public/Makefile.in @@ -52,6 +52,7 @@ XPIDLSRCS = \ nsIStreamLoader.idl \ nsINetPrompt.idl \ nsISocketTransport.idl \ + nsIURLParser.idl \ $(NULL) EXPORTS = \ diff --git a/mozilla/netwerk/base/public/makefile.win b/mozilla/netwerk/base/public/makefile.win index 22494da37dd..f658ea5c26c 100644 --- a/mozilla/netwerk/base/public/makefile.win +++ b/mozilla/netwerk/base/public/makefile.win @@ -50,9 +50,10 @@ XPIDLSRCS = \ .\nsIFileTransportService.idl \ .\nsIStatusCodeEventSink.idl \ .\nsIFileSystem.idl \ - .\nsIStreamLoader.idl \ - .\nsINetPrompt.idl \ - .\nsISocketTransport.idl \ + .\nsIStreamLoader.idl \ + .\nsINetPrompt.idl \ + .\nsISocketTransport.idl \ + .\nsIURLParser.idl \ $(NULL) include <$(DEPTH)/config/rules.mak> diff --git a/mozilla/netwerk/base/public/nsIIOService.idl b/mozilla/netwerk/base/public/nsIIOService.idl index b63c37b1ef8..845f1c51b6c 100644 --- a/mozilla/netwerk/base/public/nsIIOService.idl +++ b/mozilla/netwerk/base/public/nsIIOService.idl @@ -42,6 +42,20 @@ interface nsIOutputStream; [scriptable, uuid(ab7c3a84-d488-11d3-8cda-0060b0fc14a3)] 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. */ diff --git a/mozilla/netwerk/base/public/nsIURI.idl b/mozilla/netwerk/base/public/nsIURI.idl index 8efcef5ad38..8d44bef0f88 100644 --- a/mozilla/netwerk/base/public/nsIURI.idl +++ b/mozilla/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/mozilla/netwerk/base/src/Makefile.in b/mozilla/netwerk/base/src/Makefile.in index d8ebb9ce477..d49afa89dde 100644 --- a/mozilla/netwerk/base/src/Makefile.in +++ b/mozilla/netwerk/base/src/Makefile.in @@ -30,6 +30,7 @@ MODULE = necko LIBRARY_NAME = neckobase_s CPPSRCS = \ + nsURLHelper.cpp \ nsFileStreams.cpp \ nsAsyncStreamListener.cpp \ nsSyncStreamListener.cpp \ @@ -38,6 +39,9 @@ CPPSRCS = \ nsSocketTransportService.cpp \ nsFileTransport.cpp \ nsFileTransportService.cpp \ + nsStdURLParser.cpp \ + nsAuthURLParser.cpp \ + nsNoAuthURLParser.cpp \ nsStdURL.cpp \ nsSimpleURI.cpp \ nsNetModuleMgr.cpp \ diff --git a/mozilla/netwerk/base/src/makefile.win b/mozilla/netwerk/base/src/makefile.win index 043d2c79553..314e5a10fd1 100644 --- a/mozilla/netwerk/base/src/makefile.win +++ b/mozilla/netwerk/base/src/makefile.win @@ -27,6 +27,7 @@ LCFLAGS = -DWIN32_LEAN_AND_MEAN -D_IMPL_NS_NET LIBRARY_NAME=neckobase_s CPP_OBJS = \ + .\$(OBJDIR)\nsURLHelper.obj \ .\$(OBJDIR)\nsFileStreams.obj \ .\$(OBJDIR)\nsBufferedStreams.obj \ .\$(OBJDIR)\nsAsyncStreamListener.obj \ @@ -36,6 +37,9 @@ CPP_OBJS = \ .\$(OBJDIR)\nsSocketTransportService.obj \ .\$(OBJDIR)\nsFileTransport.obj \ .\$(OBJDIR)\nsFileTransportService.obj \ + .\$(OBJDIR)\nsStdURLParser.obj \ + .\$(OBJDIR)\nsAuthURLParser.obj \ + .\$(OBJDIR)\nsNoAuthURLParser.obj \ .\$(OBJDIR)\nsStdURL.obj \ .\$(OBJDIR)\nsSimpleURI.obj \ .\$(OBJDIR)\nsNetModuleMgr.obj \ diff --git a/mozilla/netwerk/base/src/nsAuthURLParser.cpp b/mozilla/netwerk/base/src/nsAuthURLParser.cpp index ca2c2fef96e..2b147c65646 100644 --- a/mozilla/netwerk/base/src/nsAuthURLParser.cpp +++ b/mozilla/netwerk/base/src/nsAuthURLParser.cpp @@ -70,6 +70,7 @@ nsAuthURLParser::ParseAtScheme(const char* i_Spec, char* *o_Scheme, if (!brk) // everything is a host { rv = ExtractString((char*)i_Spec, o_Host, len); + ToLowerCase(*o_Host); return rv; } else len = PL_strlen(brk); @@ -89,6 +90,7 @@ nsAuthURLParser::ParseAtScheme(const char* i_Spec, char* *o_Scheme, rv = ExtractString((char*)i_Spec, o_Host, (brk - i_Spec)); if (NS_FAILED(rv)) return rv; + ToLowerCase(*o_Host); rv = ParseAtPath(brk, o_Path); return rv; } @@ -111,6 +113,7 @@ nsAuthURLParser::ParseAtScheme(const char* i_Spec, char* *o_Scheme, rv = ExtractString((char*)i_Spec, o_Host, (brk - i_Spec)); if (NS_FAILED(rv)) return rv; + ToLowerCase(*o_Host); rv = ParseAtPort(brk+1, o_Port, o_Path); return rv; } else { @@ -151,13 +154,19 @@ nsAuthURLParser::ParseAtPreHost(const char* i_Spec, char* *o_Username, if (fwdPtr && (*fwdPtr != '\0') && (*fwdPtr == '/')) fwdPtr++; - // Search for @ - static const char delimiters[] = "@"; + static const char delimiters[] = "/:@?"; char* brk = PL_strpbrk(fwdPtr, delimiters); - if (brk) + if (!brk) { - char* e_PreHost = nsnull; + rv = ParseAtHost(fwdPtr, o_Host, o_Port, o_Path); + return rv; + } + + char* e_PreHost = nsnull; + switch (*brk) + { + case '@' : rv = ExtractString(fwdPtr, &e_PreHost, (brk - fwdPtr)); if (NS_FAILED(rv)) { CRTFREEIF(e_PreHost); @@ -169,7 +178,8 @@ nsAuthURLParser::ParseAtPreHost(const char* i_Spec, char* *o_Username, return rv; rv = ParseAtHost(brk+1, o_Host, o_Port, o_Path); - } else { + break; + default: rv = ParseAtHost(fwdPtr, o_Host, o_Port, o_Path); } return rv; @@ -187,6 +197,7 @@ nsAuthURLParser::ParseAtHost(const char* i_Spec, char* *o_Host, if (!brk) // everything is a host { rv = ExtractString((char*)i_Spec, o_Host, len); + ToLowerCase(*o_Host); return rv; } @@ -198,6 +209,7 @@ nsAuthURLParser::ParseAtHost(const char* i_Spec, char* *o_Host, rv = ExtractString((char*)i_Spec, o_Host, (brk - i_Spec)); if (NS_FAILED(rv)) return rv; + ToLowerCase(*o_Host); rv = ParseAtPath(brk, o_Path); return rv; break; @@ -206,6 +218,7 @@ nsAuthURLParser::ParseAtHost(const char* i_Spec, char* *o_Host, rv = ExtractString((char*)i_Spec, o_Host, (brk - i_Spec)); if (NS_FAILED(rv)) return rv; + ToLowerCase(*o_Host); rv = ParseAtPort(brk+1, o_Port, o_Path); return rv; break; diff --git a/mozilla/netwerk/base/src/nsIOService.cpp b/mozilla/netwerk/base/src/nsIOService.cpp index 3d7d7c71a77..3c464f6f31a 100644 --- a/mozilla/netwerk/base/src/nsIOService.cpp +++ b/mozilla/netwerk/base/src/nsIOService.cpp @@ -393,22 +393,21 @@ nsIOService::SetOffline(PRBool offline) NS_IMETHODIMP nsIOService::Escape(const char *str, PRInt16 mask, char **result) { - // XXX Andreas - return NS_ERROR_NOT_IMPLEMENTED; + return nsURLEscape((char*)str,mask,result); } NS_IMETHODIMP nsIOService::Unescape(const char *str, char **result) { - // XXX Andreas - return NS_ERROR_NOT_IMPLEMENTED; + return nsURLUnescape((char*)str,result); } NS_IMETHODIMP nsIOService::ExtractPort(const char *str, PRInt32 *result) { - // XXX Andreas - return NS_ERROR_NOT_IMPLEMENTED; + PRInt32 returnValue = -1; + *result = (0 < PR_sscanf(str, "%d", &returnValue)) ? returnValue : -1; + return NS_OK; } NS_IMETHODIMP diff --git a/mozilla/netwerk/base/src/nsIOService.h b/mozilla/netwerk/base/src/nsIOService.h index a452a2b0ef4..2110609fee1 100644 --- a/mozilla/netwerk/base/src/nsIOService.h +++ b/mozilla/netwerk/base/src/nsIOService.h @@ -29,6 +29,7 @@ #include "nsIFileTransportService.h" #include "nsIDNSService.h" #include "nsCOMPtr.h" +#include "nsURLHelper.h" class nsIOService : public nsIIOService { diff --git a/mozilla/netwerk/base/src/nsSimpleURI.cpp b/mozilla/netwerk/base/src/nsSimpleURI.cpp index cb4b69b21de..d0022358662 100644 --- a/mozilla/netwerk/base/src/nsSimpleURI.cpp +++ b/mozilla/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/mozilla/netwerk/base/src/nsStdURL.cpp b/mozilla/netwerk/base/src/nsStdURL.cpp index a59eb2a9342..49ddcedec4c 100644 --- a/mozilla/netwerk/base/src/nsStdURL.cpp +++ b/mozilla/netwerk/base/src/nsStdURL.cpp @@ -20,174 +20,128 @@ * Contributor(s): */ +#include "nsIIOService.h" +#include "nsURLHelper.h" #include "nsStdURL.h" +#include "nsStdURLParser.h" #include "nscore.h" #include "nsCRT.h" #include "nsString.h" #include "prmem.h" #include "prprf.h" #include "nsXPIDLString.h" +#include "nsCOMPtr.h" +#include "nsIServiceManager.h" #include "nsILocalFile.h" #include "nsEscape.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; } @@ -203,15 +157,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); @@ -243,9 +198,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; @@ -264,433 +222,150 @@ 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; + } + } + 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) + + rv = AppendPreHost(finalSpec,mUsername,mPassword,ESCAPED); + if (mUsername) { - finalSpec += mPreHost; - finalSpec += '@'; + finalSpec += "@"; } + if (mHost) { - finalSpec += mHost; + rv = AppendString(finalSpec,mHost,ESCAPED,nsIIOService::url_Host); if (-1 != mPort) { char* portBuffer = PR_smprintf(":%d", mPort); @@ -701,12 +376,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 @@ -725,40 +409,35 @@ 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; + + if (!mUsername) { + *o_PreHost = nsnull; + } else { + 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 @@ -782,10 +461,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 @@ -794,54 +474,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 @@ -852,10 +528,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[] = "/;?#:"; @@ -866,32 +548,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; @@ -899,17 +605,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; @@ -924,26 +634,55 @@ 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) + + rv = AppendPreHost(finalSpec,mUsername,mPassword,ESCAPED); + if (mUsername) { - finalSpec += mPreHost; finalSpec += '@'; } + if (mHost) { - finalSpec += mHost; + rv = AppendString(finalSpec,mHost,ESCAPED,nsIIOService::url_Host); if (-1 != mPort) { char* portBuffer = PR_smprintf(":%d", mPort); @@ -955,52 +694,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 @@ -1008,320 +760,216 @@ 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; + if (mFileBaseName || mFileExtension) { + 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; + } else { + *o_FileName = nsnull; + } + return NS_OK; +} + NS_METHOD nsStdURL::SetFilePath(const char *filePath) { - return NS_ERROR_NOT_IMPLEMENTED; + return SetPath(filePath); } -NS_METHOD -nsStdURL::GetFileBaseName(char **o_name) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_METHOD -nsStdURL::SetFileBaseName(const char *name) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -//////////////////////////////////////////////////////////////////////////////// -// nsIFileURL methods: - NS_IMETHODIMP nsStdURL::GetFile(nsIFile * *aFile) { - nsresult rv; - if (mFile) { - *aFile = mFile; - NS_ADDREF(*aFile); - return NS_OK; - } - - // if we didn't have an nsIFile already, then synthesize one and cache it + nsresult rv = NS_OK; if (nsCRT::strcasecmp(mScheme, "file") != 0) { // if this isn't a file: URL, then we can't return an nsIFile return NS_ERROR_FAILURE; } - NS_ASSERTION(mPreHost == nsnull, "file: with mPreHost"); + NS_ASSERTION(mUsername == nsnull, "file: with mUsername"); // we do not use the path cause it can contain the # char - nsCAutoString path(mDirectory); - path.Append(mFileName); -#ifdef XP_PC - if (path.CharAt(2) == '|') { - path.SetCharAt(':', 2); - // cut off the leading '/' - if (path.CharAt(0) == '/') - path.Cut(0, 1); + nsCAutoString path; + if (mDirectory) + { + rv = AppendString(path,mDirectory,ESCAPED,nsIIOService::url_Directory); } + + rv = AppendFileName(path,mFileBaseName,mFileExtension,ESCAPED); + +#ifdef XP_PC + if (path.CharAt(2) == '|') + path.SetCharAt(':', 2); + + // cut off the leading '/' + if (path.CharAt(0) == '/') + path.Cut(0, 1); else if (mHost) { // Deal with the case where the user type file://C|/ (2 slashes instead of 3). // In this case, the C| ends up as the host name (ugh). nsCAutoString host(mHost); PRInt32 len = host.Length(); if (len == 2 && host.CharAt(1) == '|') { - host.SetCharAt(':', 1); - path.Insert(host, 0); - } + host.SetCharAt(':', 1); + path.Insert(host, 0); + } } path.ReplaceChar('/', '\\'); #elif defined(XP_MAC) @@ -1347,15 +995,19 @@ NS_IMETHODIMP nsStdURL::SetFile(nsIFile * aFile) { nsresult rv; + mFile = aFile; // set up this URL to denote the nsIFile SetScheme("file"); - rv = mFile->GetPath(&mPath); - if (NS_FAILED(rv)) return rv; - - return ParsePath(); + char* ePath = nsnull; + rv = aFile->GetPath(&ePath); + if (NS_SUCCEEDED(rv)) { + rv = SetPath(ePath); + } + CRTFREEIF(ePath); + return rv; } //////////////////////////////////////////////////////////////////////////////// diff --git a/mozilla/netwerk/base/src/nsStdURL.h b/mozilla/netwerk/base/src/nsStdURL.h index 21a19b0d3d4..352983efb51 100644 --- a/mozilla/netwerk/base/src/nsStdURL.h +++ b/mozilla/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!! @@ -41,14 +43,10 @@ class nsStdURL : public nsIFileURL { public: - NS_DECL_AGGREGATED - NS_DECL_NSIURI - NS_DECL_NSIURL - NS_DECL_NSIFILEURL - - //////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// // nsStdURL methods: + nsStdURL(); nsStdURL(const char* i_Spec, nsISupports* outer=nsnull); nsStdURL(const nsStdURL& i_URL); virtual ~nsStdURL(); @@ -59,151 +57,67 @@ public: static NS_METHOD Create(nsISupports *aOuter, REFNSIID aIID, void **aResult); - /* todo move this to protected later */ - nsresult ParsePath(void); + NS_DECL_AGGREGATED + NS_DECL_NSIURI + NS_DECL_NSIURL + NS_DECL_NSIFILEURL protected: - nsresult Parse(void); - nsresult ReconstructPath(void); - nsresult ReconstructSpec(void); - - // Some handy functions - nsresult DupString(char* *o_Dest, const char* i_Src); - nsresult ExtractString(char* i_Src, char* *o_Dest, PRUint32 length); + 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); 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; // If a file was given to SetFile, then this instance variable holds it. // If GetFile is called, we synthesize one and cache it here. nsCOMPtr mFile; }; -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,88 @@ 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); + nsresult rv = DupString(&mScheme, i_Scheme); + ToLowerCase(mScheme); + return rv; +} + +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); + nsresult rv = DupString(&mHost, i_Host); + ToLowerCase(mHost); + return rv; +} + 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/mozilla/netwerk/base/src/nsStdURLParser.cpp b/mozilla/netwerk/base/src/nsStdURLParser.cpp index 727978429c6..3ae2fc0ca20 100644 --- a/mozilla/netwerk/base/src/nsStdURLParser.cpp +++ b/mozilla/netwerk/base/src/nsStdURLParser.cpp @@ -71,6 +71,7 @@ nsStdURLParser::ParseAtScheme(const char* i_Spec, char* *o_Scheme, if (!brk) // everything is a host { rv = ExtractString((char*)i_Spec, o_Host, len); + ToLowerCase(*o_Host); return rv; } else len = PL_strlen(brk); @@ -90,6 +91,7 @@ nsStdURLParser::ParseAtScheme(const char* i_Spec, char* *o_Scheme, rv = ExtractString((char*)i_Spec, o_Host, (brk - i_Spec)); if (NS_FAILED(rv)) return rv; + ToLowerCase(*o_Host); rv = ParseAtPath(brk, o_Path); return rv; } @@ -147,6 +149,7 @@ nsStdURLParser::ParseAtScheme(const char* i_Spec, char* *o_Scheme, rv = ExtractString((char*)i_Spec, o_Host, (brk - i_Spec)); if (NS_FAILED(rv)) return rv; + ToLowerCase(*o_Host); rv = ParseAtPort(brk+1, o_Port, o_Path); return rv; } @@ -179,13 +182,19 @@ nsStdURLParser::ParseAtPreHost(const char* i_Spec, char* *o_Username, if (fwdPtr && (*fwdPtr != '\0') && (*fwdPtr == '/')) fwdPtr++; - // Search for @ - static const char delimiters[] = "@"; + static const char delimiters[] = "/:@?"; char* brk = PL_strpbrk(fwdPtr, delimiters); - if (brk) + if (!brk) { - char* e_PreHost = nsnull; + rv = ParseAtHost(fwdPtr, o_Host, o_Port, o_Path); + return rv; + } + + char* e_PreHost = nsnull; + switch (*brk) + { + case '@' : rv = ExtractString(fwdPtr, &e_PreHost, (brk - fwdPtr)); if (NS_FAILED(rv)) { CRTFREEIF(e_PreHost); @@ -197,12 +206,11 @@ nsStdURLParser::ParseAtPreHost(const char* i_Spec, char* *o_Username, return rv; rv = ParseAtHost(brk+1, o_Host, o_Port, o_Path); - return rv; - } else { + break; + default: rv = ParseAtHost(fwdPtr, o_Host, o_Port, o_Path); - return rv; } - return NS_OK; + return rv; } nsresult @@ -217,6 +225,7 @@ nsStdURLParser::ParseAtHost(const char* i_Spec, char* *o_Host, if (!brk) // everything is a host { rv = ExtractString((char*)i_Spec, o_Host, len); + ToLowerCase(*o_Host); return rv; } @@ -228,6 +237,7 @@ nsStdURLParser::ParseAtHost(const char* i_Spec, char* *o_Host, rv = ExtractString((char*)i_Spec, o_Host, (brk - i_Spec)); if (NS_FAILED(rv)) return rv; + ToLowerCase(*o_Host); rv = ParseAtPath(brk, o_Path); return rv; break; @@ -236,6 +246,7 @@ nsStdURLParser::ParseAtHost(const char* i_Spec, char* *o_Host, rv = ExtractString((char*)i_Spec, o_Host, (brk - i_Spec)); if (NS_FAILED(rv)) return rv; + ToLowerCase(*o_Host); rv = ParseAtPort(brk+1, o_Port, o_Path); return rv; break; diff --git a/mozilla/netwerk/base/src/nsURLHelper.cpp b/mozilla/netwerk/base/src/nsURLHelper.cpp index 7f67778e894..8612444186f 100644 --- a/mozilla/netwerk/base/src/nsURLHelper.cpp +++ b/mozilla/netwerk/base/src/nsURLHelper.cpp @@ -158,7 +158,7 @@ NS_NET nsresult ExtractString(char* i_Src, char* *o_Dest, PRUint32 length) { NS_PRECONDITION( (nsnull != i_Src), "Extract called on empty string!"); - /* CRTFREEIF(*o_Dest);*/ + CRTFREEIF(*o_Dest); *o_Dest = PL_strndup(i_Src, length); return (*o_Dest ? NS_OK : NS_ERROR_OUT_OF_MEMORY); } @@ -201,8 +201,10 @@ CoaleseDirs(char* io_Path) (*fwdPtr != '?') && (*fwdPtr != '#'); ++fwdPtr) { +#ifdef XP_PC if (*fwdPtr == '\\') *fwdPtr = '/'; +#endif if (*fwdPtr == '/' && *(fwdPtr+1) == '.' && (*(fwdPtr+2) == '/' || *(fwdPtr+2) == '\\')) { @@ -255,7 +257,6 @@ CoaleseDirs(char* io_Path) NS_NET void ToLowerCase(char* str) { -#ifdef UNDEF if (str) { char* lstr = str; PRInt8 shift = 'a' - 'A'; @@ -266,5 +267,4 @@ ToLowerCase(char* str) *(lstr) = *(lstr) + shift; } } -#endif } diff --git a/mozilla/netwerk/build/nsNetModule.cpp b/mozilla/netwerk/build/nsNetModule.cpp index b02c98a3920..fedfdcf1779 100644 --- a/mozilla/netwerk/build/nsNetModule.cpp +++ b/mozilla/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" @@ -107,7 +110,19 @@ static nsModuleComponentInfo gNetModuleInfo[] = { { NS_FILEOUTPUTSTREAM_CLASSNAME, NS_FILEOUTPUTSTREAM_CID, NS_FILEOUTPUTSTREAM_PROGID, - nsFileOutputStream::Create } + nsFileOutputStream::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/mozilla/netwerk/protocol/file/src/nsFileProtocolHandler.cpp b/mozilla/netwerk/protocol/file/src/nsFileProtocolHandler.cpp index 97771af3190..7f71d60b27b 100644 --- a/mozilla/netwerk/protocol/file/src/nsFileProtocolHandler.cpp +++ b/mozilla/netwerk/protocol/file/src/nsFileProtocolHandler.cpp @@ -23,6 +23,7 @@ #include "nsFileChannel.h" #include "nsFileProtocolHandler.h" #include "nsIURL.h" +#include "nsIURLParser.h" #include "nsCRT.h" #include "nsIComponentManager.h" #include "nsIServiceManager.h" @@ -35,6 +36,7 @@ #include "nsAutoLock.h" static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID); +static NS_DEFINE_CID(kNoAuthUrlParserCID, NS_NOAUTHORITYURLPARSER_CID); //////////////////////////////////////////////////////////////////////////////// @@ -101,17 +103,31 @@ nsFileProtocolHandler::NewURI(const char *aSpec, nsIURI *aBaseURI, // file: URLs (currently) have no additional structure beyond that provided by standard // URLs, so there is no "outer" given to CreateInstance - 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(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/mozilla/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp b/mozilla/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp index e2e5f94c117..1cbe6497e5f 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp +++ b/mozilla/netwerk/protocol/ftp/src/nsFtpProtocolHandler.cpp @@ -23,6 +23,7 @@ #include "nsFtpProtocolHandler.h" #include "nsFTPChannel.h" #include "nsIURL.h" +#include "nsIURLParser.h" #include "nsCRT.h" #include "nsIComponentManager.h" #include "nsIInterfaceRequestor.h" @@ -47,6 +48,7 @@ PRLogModuleInfo* gFTPLog = nsnull; #endif /* PR_LOGGING */ 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/mozilla/netwerk/protocol/http/src/nsHTTPHandler.cpp b/mozilla/netwerk/protocol/http/src/nsHTTPHandler.cpp index 5e85d8a138c..da9e8250c75 100644 --- a/mozilla/netwerk/protocol/http/src/nsHTTPHandler.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHTTPHandler.cpp @@ -29,6 +29,7 @@ #include "plstr.h" // For PL_strcasecmp maybe DEBUG only... TODO check #include "nsXPIDLString.h" #include "nsIURL.h" +#include "nsIURLParser.h" #include "nsIChannel.h" #include "nsISocketTransportService.h" #include "nsIServiceManager.h" @@ -65,6 +66,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); @@ -292,6 +294,7 @@ nsHTTPHandler::NewURI(const char *aSpec, nsIURI *aBaseURI, nsresult rv; nsIURI* url = nsnull; + nsIURLParser* urlparser = nsnull; if (aBaseURI) { rv = aBaseURI->Clone(&url); @@ -300,10 +303,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/mozilla/netwerk/protocol/jar/src/nsJARURI.cpp b/mozilla/netwerk/protocol/jar/src/nsJARURI.cpp index d89236e9fc3..d19da020682 100644 --- a/mozilla/netwerk/protocol/jar/src/nsJARURI.cpp +++ b/mozilla/netwerk/protocol/jar/src/nsJARURI.cpp @@ -151,6 +151,30 @@ nsJARURI::SetScheme(const char * aScheme) 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::GetPreHost(char * *aPreHost) { @@ -199,6 +223,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 *result) { diff --git a/mozilla/netwerk/protocol/res/src/nsResProtocolHandler.cpp b/mozilla/netwerk/protocol/res/src/nsResProtocolHandler.cpp index 3237f5cd548..58033c1c6a4 100644 --- a/mozilla/netwerk/protocol/res/src/nsResProtocolHandler.cpp +++ b/mozilla/netwerk/protocol/res/src/nsResProtocolHandler.cpp @@ -193,7 +193,7 @@ nsResProtocolHandler::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) NS_IMETHODIMP nsResProtocolHandler::GetScheme(char* *result) { - *result = nsCRT::strdup("res"); + *result = nsCRT::strdup("resource"); if (*result == nsnull) return NS_ERROR_OUT_OF_MEMORY; return NS_OK; diff --git a/mozilla/webshell/src/nsWebShell.cpp b/mozilla/webshell/src/nsWebShell.cpp index c40a71f86b0..ee0f4f3a46c 100644 --- a/mozilla/webshell/src/nsWebShell.cpp +++ b/mozilla/webshell/src/nsWebShell.cpp @@ -20,6 +20,7 @@ * Contributor(s): * Pierre Phaneuf */ + #include "nsDocShell.h" #include "nsIWebShell.h" #include "nsIInterfaceRequestor.h" @@ -1440,18 +1441,29 @@ nsWebShell::GetDocumentLoader(nsIDocumentLoader*& aResult) return (nsnull != mDocLoader) ? NS_OK : NS_ERROR_FAILURE; } -#define FILE_PROTOCOL "file:///" +#define FILE_PROTOCOL "file://" static void convertFileToURL(const nsString &aIn, nsString &aOut) { -#ifdef XP_PC char szFile[1000]; aIn.ToCString(szFile, sizeof(szFile)); +#ifdef XP_PC + // Check for \ in the url-string (PC) if (PL_strchr(szFile, '\\')) { +#else +#if XP_UNIX + // Check if it starts with / or \ (UNIX) + if (*(szFile) == '/' || *(szFile) == '\\') { +#else + if (0) { + // Do nothing (All others for now) +#endif +#endif PRInt32 len = strlen(szFile); PRInt32 sum = len + sizeof(FILE_PROTOCOL); char* lpszFileURL = (char *)PR_Malloc(sum + 1); +#ifdef XP_PC // Translate '\' to '/' for (PRInt32 i = 0; i < len; i++) { if (szFile[i] == '\\') { @@ -1461,6 +1473,7 @@ static void convertFileToURL(const nsString &aIn, nsString &aOut) szFile[i] = '|'; } } +#endif // Build the file URL PR_snprintf(lpszFileURL, sum, "%s%s", FILE_PROTOCOL, szFile); @@ -1468,7 +1481,6 @@ static void convertFileToURL(const nsString &aIn, nsString &aOut) PR_Free((void *)lpszFileURL); } else -#endif { aOut = aIn; } @@ -1802,6 +1814,7 @@ nsWebShell::DoContent(const char * aContentType, if (NS_SUCCEEDED(rv)) pURILoader->GetStringForCommand(aCommand, getter_Copies(strCommand)); + // determine if the channel has just been retargeted to us... nsLoadFlags loadAttribs = 0; aOpenedChannel->GetLoadAttributes(&loadAttribs); diff --git a/mozilla/xpfe/components/directory/nsDirectoryViewer.cpp b/mozilla/xpfe/components/directory/nsDirectoryViewer.cpp index 2722afdbe21..c8ef0221167 100644 --- a/mozilla/xpfe/components/directory/nsDirectoryViewer.cpp +++ b/mozilla/xpfe/components/directory/nsDirectoryViewer.cpp @@ -59,7 +59,8 @@ #include "nsXPIDLString.h" #include "rdf.h" #include "nsIInterfaceRequestor.h" - +#include "iostream.h" +#include "nsIIOService.h" //////////////////////////////////////////////////////////////////////// // Common CIDs @@ -72,6 +73,7 @@ static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID); static NS_DEFINE_CID(kDirectoryViewerFactoryCID, NS_DIRECTORYVIEWERFACTORY_CID); static NS_DEFINE_CID(kGenericFactoryCID, NS_GENERICFACTORY_CID); static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); +static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); #define HTTPINDEX_NAMESPACE_URI "urn:http-index-format:" @@ -610,6 +612,7 @@ nsHTTPIndexParser::ParseData(const char* aDataStr) // make sure that the mDirectoryURI ends with a '/' before // concatenating. nsresult rv; + NS_WITH_SERVICE(nsIIOService, ioServ, kIOServiceCID, &rv); nsCOMPtr realbase; { @@ -687,7 +690,11 @@ nsHTTPIndexParser::ParseData(const char* aDataStr) if (field && field->mProperty == kHTTPIndex_Filename) { // we found the filename; construct a resource for its entry nsAutoString entryuri; - rv = NS_MakeAbsoluteURI(value, realbase, entryuri); + char* result = nsnull; + rv = ioServ->Escape(value.mStr, nsIIOService::url_FileBaseName, + &result); + rv = NS_MakeAbsoluteURI(result, realbase, entryuri); + CRTFREEIF(result); NS_ASSERTION(NS_SUCCEEDED(rv), "unable make absolute URI"); if (NS_FAILED(rv)) break; rv = gRDF->GetResource(nsCAutoString(entryuri), getter_AddRefs(entry));