From d33b2e33c81bf28ea84bfffb68a2d992336465f3 Mon Sep 17 00:00:00 2001 From: "mkaply%us.ibm.com" Date: Mon, 22 Nov 2004 19:28:24 +0000 Subject: [PATCH] #264647 r=mkaply, sr=blizzard (platform specific), a=mkaply (OS/2 only) Patch from Peter Weilbacher - Add protocols to ExternalProtocolHandlerExists/Add GetApplicationDescription for OS/2 --- .../exthandler/os2/nsOSHelperAppService.cpp | 421 ++++++++++++------ .../exthandler/os2/nsOSHelperAppService.h | 4 + 2 files changed, 289 insertions(+), 136 deletions(-) diff --git a/uriloader/exthandler/os2/nsOSHelperAppService.cpp b/uriloader/exthandler/os2/nsOSHelperAppService.cpp index f3ad9209f66..3525c6bc18d 100644 --- a/uriloader/exthandler/os2/nsOSHelperAppService.cpp +++ b/uriloader/exthandler/os2/nsOSHelperAppService.cpp @@ -23,6 +23,7 @@ * Contributor(s): * Scott MacGregor * Boris Zbarsky (Added mailcap and mime.types support) + * Peter Weilbacher * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -70,6 +71,8 @@ static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID); // XXX need to conver #define INCL_WINSHELLDATA #include +#define MAXINIPARAMLENGTH 1024 // max length of OS/2 INI key for application parameters + #define LOG(args) PR_LOG(mLog, PR_LOG_DEBUG, args) #define LOG_ENABLED() PR_LOG_TEST(mLog, PR_LOG_DEBUG) @@ -1138,10 +1141,111 @@ nsOSHelperAppService::GetHandlerAndDescriptionFromMailcapFile(const nsAString& a return rv; } +// Check OS/2 INI for application and parameters for the protocol +// return NS_OK, if application exists for protocol in INI and is not empty +nsresult +nsOSHelperAppService::GetApplicationAndParametersFromINI(const nsACString& aProtocol, + char * app, ULONG appLength, + char * param, ULONG paramLength) +{ + /* initialize app to '\0' for later check */ + *app = '\0'; + + /* http or https */ + if ((aProtocol == NS_LITERAL_CSTRING("http")) || + (aProtocol == NS_LITERAL_CSTRING("https"))) { + PrfQueryProfileString(HINI_USER, + "WPURLDEFAULTSETTINGS", + "DefaultBrowserExe", + "", + app, + appLength); + PrfQueryProfileString(HINI_USER, + "WPURLDEFAULTSETTINGS", + "DefaultParameters", + "", + param, + paramLength); + } + /* mailto: */ + else if (aProtocol == NS_LITERAL_CSTRING("mailto")) { + PrfQueryProfileString(HINI_USER, + "WPURLDEFAULTSETTINGS", + "DefaultMailExe", + "", + app, + appLength); + PrfQueryProfileString(HINI_USER, + "WPURLDEFAULTSETTINGS", + "DefaultMailParameters", + "", + param, + paramLength); + } + /* ftp */ + else if (aProtocol == NS_LITERAL_CSTRING("ftp")) { + PrfQueryProfileString(HINI_USER, + "WPURLDEFAULTSETTINGS", + "DefaultFTPExe", + "", + app, + appLength); + PrfQueryProfileString(HINI_USER, + "WPURLDEFAULTSETTINGS", + "DefaultFTPParameters", + "", + param, + paramLength); + } + /* news: or snews: */ + else if ((aProtocol == NS_LITERAL_CSTRING("news")) || + (aProtocol == NS_LITERAL_CSTRING("snews"))) { + PrfQueryProfileString(HINI_USER, + "WPURLDEFAULTSETTINGS", + "DefaultNewsExe", + "", + app, + appLength); + PrfQueryProfileString(HINI_USER, + "WPURLDEFAULTSETTINGS", + "DefaultNewsParameters", + "", + param, + paramLength); + } + /* irc: */ + else if (aProtocol == NS_LITERAL_CSTRING("irc")) { + PrfQueryProfileString(HINI_USER, + "WPURLDEFAULTSETTINGS", + "DefaultIRCExe", + "", + app, + appLength); + PrfQueryProfileString(HINI_USER, + "WPURLDEFAULTSETTINGS", + "DefaultIRCParameters", + "", + param, + paramLength); + } + else { + NS_WARNING("GetApplicationAndParametersFromINI(): unsupported protocol scheme"); + return NS_ERROR_FAILURE; + } + + /* application string in INI was empty */ + if (app[0] == '\0') + return NS_ERROR_FAILURE; + + return NS_OK; +} + NS_IMETHODIMP nsOSHelperAppService::ExternalProtocolHandlerExists(const char * aProtocolScheme, PRBool * aHandlerExists) { LOG(("-- nsOSHelperAppService::ExternalProtocolHandlerExists for '%s'\n", aProtocolScheme)); + *aHandlerExists = PR_FALSE; + /* if applications.protocol is in prefs, then we have an external protocol handler */ nsresult rv; nsCAutoString prefName; @@ -1152,15 +1256,27 @@ NS_IMETHODIMP nsOSHelperAppService::ExternalProtocolHandlerExists(const char * a nsXPIDLCString prefString; rv = thePrefsService->CopyCharPref(prefName.get(), getter_Copies(prefString)); *aHandlerExists = NS_SUCCEEDED(rv) && !prefString.IsEmpty(); + if (*aHandlerExists) { + return NS_OK; + } + } + /* Check the OS/2 INI for the protocol */ + char szAppFromINI[CCHMAXPATH]; + char szParamsFromINI[MAXINIPARAMLENGTH]; + rv = GetApplicationAndParametersFromINI(nsDependentCString(aProtocolScheme), + szAppFromINI, sizeof(szAppFromINI), + szParamsFromINI, sizeof(szParamsFromINI)); + if (NS_SUCCEEDED(rv)) { + *aHandlerExists = PR_TRUE; return NS_OK; } - *aHandlerExists = PR_FALSE; - return NS_OK; + + return NS_ERROR_FAILURE; } nsresult nsOSHelperAppService::LoadUriInternal(nsIURI * aURL) { - LOG(("-- nsOSHelperAppService::LoadUrl\n")); + LOG(("-- nsOSHelperAppService::LoadUriInternal\n")); nsCOMPtr thePrefsService(do_GetService(NS_PREF_CONTRACTID)); if (!thePrefsService) { return NS_ERROR_FAILURE; @@ -1184,128 +1300,67 @@ nsresult nsOSHelperAppService::LoadUriInternal(nsIURI * aURL) prefName = NS_LITERAL_CSTRING("applications.") + uProtocol; nsXPIDLCString prefString; - nsCAutoString parameters; nsCAutoString applicationName; + nsCAutoString parameters; rv = thePrefsService->CopyCharPref(prefName.get(), getter_Copies(prefString)); if (NS_FAILED(rv) || prefString.IsEmpty()) { - char szAppFromINI[CCHMAXPATH] = "\0"; - char szParamsFromINI[CCHMAXPATH]; - /* Special case http, https, and ftp - if we get here, pass them to the shell */ - if ((uProtocol.EqualsLiteral("http")) || - (uProtocol.EqualsLiteral("https")) || - (uProtocol.EqualsLiteral("ftp"))) { - if (uProtocol.EqualsLiteral("ftp")) { - PrfQueryProfileString(HINI_USER, - "WPURLDEFAULTSETTINGS", - "DefaultFTPExe", - "", - szAppFromINI, - sizeof(szAppFromINI)) ; - PrfQueryProfileString(HINI_USER, - "WPURLDEFAULTSETTINGS", - "DefaultFTPParameters", - "", - szParamsFromINI, - sizeof(szParamsFromINI)) ; - } - /* If we didn't get a default ftp or it's http or https */ - if ((uProtocol.EqualsLiteral("http")) || - (uProtocol.EqualsLiteral("https")) || - (szAppFromINI[0] == '\0')) { - PrfQueryProfileString(HINI_USER, - "WPURLDEFAULTSETTINGS", - "DefaultBrowserExe", - "", - szAppFromINI, - sizeof(szAppFromINI)); - PrfQueryProfileString(HINI_USER, - "WPURLDEFAULTSETTINGS", - "DefaultParameters", - "", - szParamsFromINI, - sizeof(szParamsFromINI)); - // DefaultParameters is the correct OS/2 way. - // In the configapps application, it writes - // DefaultBrowserParameters as well, so let's - // support it - if (szParamsFromINI[0] = '\0') { - PrfQueryProfileString(HINI_USER, - "WPURLDEFAULTSETTINGS", - "DefaultBrowserParameters", - "", - szParamsFromINI, - sizeof(szParamsFromINI)); - } - } - } else if ((uProtocol.EqualsLiteral("mailto")) || - (uProtocol.EqualsLiteral("news"))) { - if (uProtocol.EqualsLiteral("news")) { - PrfQueryProfileString(HINI_USER, - "WPURLDEFAULTSETTINGS", - "DefaultNewsExe", - "", - szAppFromINI, - sizeof(szAppFromINI)) ; - PrfQueryProfileString(HINI_USER, - "WPURLDEFAULTSETTINGS", - "DefaultNewsParameters", - "", - szParamsFromINI, - sizeof(szParamsFromINI)) ; - } - /* If we didn't get a default news or it's mailto */ - if ((uProtocol.EqualsLiteral("mailto")) || - (szAppFromINI[0] == '\0')) { - PrfQueryProfileString(HINI_USER, - "WPURLDEFAULTSETTINGS", - "DefaultMailExe", - "", - szAppFromINI, - sizeof(szAppFromINI)); - PrfQueryProfileString(HINI_USER, - "WPURLDEFAULTSETTINGS", - "DefaultMailParameters", - "", - szParamsFromINI, - sizeof(szParamsFromINI)); - } - } else { - return NS_ERROR_FAILURE; - } - - if (szAppFromINI[0]) { + char szAppFromINI[CCHMAXPATH]; + char szParamsFromINI[MAXINIPARAMLENGTH]; + /* did OS2.INI contain application? */ + rv = GetApplicationAndParametersFromINI(uProtocol, + szAppFromINI, sizeof(szAppFromINI), + szParamsFromINI, sizeof(szParamsFromINI)); + if (NS_SUCCEEDED(rv)) { applicationName = szAppFromINI; parameters = szParamsFromINI; - parameters += " "; - parameters += urlSpec; } else { return NS_ERROR_FAILURE; } } + // Dissect the URI + nsCAutoString uURL, uUsername, uPassword, uHost, uPort, uPath; + nsCAutoString uEmail, uGroup; + PRInt32 iPort; + + // when passing to OS/2 apps later, we need ASCII URLs, + // UTF-8 would probably not get handled correctly + aURL->GetAsciiSpec(uURL); + uri->GetAsciiHost(uHost); + uri->GetUsername(uUsername); + NS_UnescapeURL(uUsername); + uri->GetPassword(uPassword); + NS_UnescapeURL(uPassword); + uri->GetPort(&iPort); + /* GetPort returns -1 if there is no port in the URI */ + if (iPort != -1) + uPort.AppendInt(iPort); + uri->GetPath(uPath); + NS_UnescapeURL(uPath); + + // One could use nsIMailtoUrl to get email and newsgroup, + // but it is probably easier to do that quickly by hand here + // uEmail is both email address and message id for news + uEmail = uUsername + NS_LITERAL_CSTRING("@") + uHost; + // uPath can almost be used as newsgroup and as channel for IRC + // but strip leading "/" + uGroup = Substring(uPath, 1, uPath.Length()); + + NS_NAMED_LITERAL_CSTRING(url, "%url%"); + NS_NAMED_LITERAL_CSTRING(username, "%username%"); + NS_NAMED_LITERAL_CSTRING(password, "%password%"); + NS_NAMED_LITERAL_CSTRING(host, "%host%"); + NS_NAMED_LITERAL_CSTRING(port, "%port%"); + NS_NAMED_LITERAL_CSTRING(email, "%email%"); + NS_NAMED_LITERAL_CSTRING(group, "%group%"); + NS_NAMED_LITERAL_CSTRING(msgid, "%msgid%"); + NS_NAMED_LITERAL_CSTRING(channel, "%channel%"); + if (applicationName.IsEmpty() && parameters.IsEmpty()) { /* Put application name in parameters */ applicationName.Append(prefString); - nsCAutoString uPort; - PRInt32 iPort; - uri->GetPort(&iPort); - /* GetPort returns -1 if there is no port in the URI */ - if (iPort != -1) - uPort.AppendInt(iPort); - - nsCAutoString uUsername; - uri->GetUsername(uUsername); - NS_UnescapeURL(uUsername); - - nsCAutoString uPassword; - uri->GetPassword(uPassword); - NS_UnescapeURL(uPassword); - - nsCAutoString uHost; - uri->GetAsciiHost(uHost); - prefName.Append("."); nsCOMPtr prefBranch; rv = thePrefsService->GetBranch(prefName.get(), getter_AddRefs(prefBranch)); @@ -1316,8 +1371,6 @@ nsresult nsOSHelperAppService::LoadUriInternal(nsIURI * aURL) parameters.Append(" "); parameters.Append(prefString); - NS_NAMED_LITERAL_CSTRING(url, "%url%"); - PRInt32 pos = parameters.Find(url.get()); if (pos != kNotFound) { nsCAutoString uURL; @@ -1361,34 +1414,79 @@ nsresult nsOSHelperAppService::LoadUriInternal(nsIURI * aURL) } } } + } + +#ifdef DEBUG_peter + printf("uURL=%s\n", uURL.get()); + printf("uUsername=%s\n", uUsername.get()); + printf("uPassword=%s\n", uPassword.get()); + printf("uHost=%s\n", uHost.get()); + printf("uPort=%s\n", uPort.get()); + printf("uPath=%s\n", uPath.get()); + printf("uEmail=%s\n", uEmail.get()); + printf("uGroup=%s\n", uGroup.get()); +#endif - PRInt32 pos; - - NS_NAMED_LITERAL_CSTRING(port, "%port%"); - NS_NAMED_LITERAL_CSTRING(username, "%username%"); - NS_NAMED_LITERAL_CSTRING(password, "%password%"); - NS_NAMED_LITERAL_CSTRING(host, "%host%"); - - pos = parameters.Find(port.get()); - if (pos != kNotFound) { - parameters.Replace(pos, port.Length(), uPort); - } - pos = parameters.Find(username.get()); - if (pos != kNotFound) { - parameters.Replace(pos, username.Length(), uUsername); - } - pos = parameters.Find(password.get()); - if (pos != kNotFound) { - parameters.Replace(pos, password.Length(), uPassword); - } - pos = parameters.Find(host.get()); - if (pos != kNotFound) { - parameters.Replace(pos, host.Length(), uHost); - } + PRInt32 pos; + PRBool replaced = PR_FALSE; + pos = parameters.Find(url.get()); + if (pos != kNotFound) { + replaced = PR_TRUE; + parameters.Replace(pos, url.Length(), uURL); + } + pos = parameters.Find(username.get()); + if (pos != kNotFound) { + replaced = PR_TRUE; + parameters.Replace(pos, username.Length(), uUsername); + } + pos = parameters.Find(password.get()); + if (pos != kNotFound) { + replaced = PR_TRUE; + parameters.Replace(pos, password.Length(), uPassword); + } + pos = parameters.Find(host.get()); + if (pos != kNotFound) { + replaced = PR_TRUE; + parameters.Replace(pos, host.Length(), uHost); + } + pos = parameters.Find(port.get()); + if (pos != kNotFound) { + replaced = PR_TRUE; + parameters.Replace(pos, port.Length(), uPort); + } + pos = parameters.Find(email.get()); + if (pos != kNotFound) { + replaced = PR_TRUE; + parameters.Replace(pos, email.Length(), uEmail); + } + pos = parameters.Find(group.get()); + if (pos != kNotFound) { + replaced = PR_TRUE; + parameters.Replace(pos, group.Length(), uGroup); + } + pos = parameters.Find(msgid.get()); + if (pos != kNotFound) { + replaced = PR_TRUE; + parameters.Replace(pos, msgid.Length(), uEmail); + } + pos = parameters.Find(channel.get()); + if (pos != kNotFound) { + replaced = PR_TRUE; + parameters.Replace(pos, channel.Length(), uGroup); + } + // If no replacement variable was used, the user most likely uses the WPS URL + // object and does not know about the replacement variables. + // Just append the full URL. + if (!replaced) { + parameters.Append(" "); + parameters.Append(uURL); } const char *params[3]; params[0] = parameters.get(); +#ifdef DEBUG_peter + printf("params[0]=%s\n", params[0]); +#endif PRInt32 numParams = 1; nsCOMPtr application; @@ -1414,7 +1512,6 @@ nsresult nsOSHelperAppService::LoadUriInternal(nsIURI * aURL) params[2] = parameters.get(); numParams = 3; } - } nsCOMPtr process = do_CreateInstance(NS_PROCESS_CONTRACTID); @@ -1657,3 +1754,55 @@ nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aType, return retval; } + +NS_IMETHODIMP +nsOSHelperAppService::GetApplicationDescription(const nsACString& aScheme, nsAString& _retval) +{ + nsCOMPtr thePrefsService(do_GetService(NS_PREF_CONTRACTID)); + if (!thePrefsService) { + return NS_ERROR_FAILURE; + } + nsCAutoString prefName = NS_LITERAL_CSTRING("applications.") + aScheme; + nsXPIDLCString prefString; + nsCAutoString applicationName; + + nsresult rv = thePrefsService->CopyCharPref(prefName.get(), getter_Copies(prefString)); + if (NS_FAILED(rv) || prefString.IsEmpty()) { + char szAppFromINI[CCHMAXPATH]; + char szParamsFromINI[MAXINIPARAMLENGTH]; + /* did OS2.INI contain application? */ + rv = GetApplicationAndParametersFromINI(aScheme, + szAppFromINI, sizeof(szAppFromINI), + szParamsFromINI, sizeof(szParamsFromINI)); + if (NS_SUCCEEDED(rv)) { + applicationName = szAppFromINI; + } else { + return NS_ERROR_NOT_AVAILABLE; + } + } else { + applicationName.Append(prefString); + } + + + nsCOMPtr application; + rv = NS_NewNativeLocalFile(nsDependentCString(applicationName.get()), + PR_FALSE, + getter_AddRefs(application)); + if (NS_FAILED(rv)) { + char szAppPath[CCHMAXPATH]; + APIRET rc = DosSearchPath(SEARCH_IGNORENETERRS | SEARCH_ENVIRONMENT, + "PATH", + applicationName.get(), + szAppPath, + sizeof(szAppPath)); + /* if that worked, we can use the full pathname */ + if (rc == NO_ERROR) { + _retval.Assign(NS_ConvertUTF8toUTF16(nsDependentCString(szAppPath))); + return NS_OK; + } + } + /* if the full path is given or not, use what we have */ + _retval.Assign(NS_ConvertUTF8toUTF16(applicationName)); + return NS_OK; +} + diff --git a/uriloader/exthandler/os2/nsOSHelperAppService.h b/uriloader/exthandler/os2/nsOSHelperAppService.h index d1a50a837b5..431b905f742 100644 --- a/uriloader/exthandler/os2/nsOSHelperAppService.h +++ b/uriloader/exthandler/os2/nsOSHelperAppService.h @@ -66,12 +66,16 @@ public: // override nsIExternalProtocolService methods NS_IMETHOD ExternalProtocolHandlerExists(const char * aProtocolScheme, PRBool * aHandlerExists); nsresult LoadUriInternal(nsIURI * aURL); + NS_IMETHODIMP GetApplicationDescription(const nsACString& aScheme, nsAString& _retval); protected: already_AddRefed GetFromType(const nsCString& aMimeType); already_AddRefed GetFromExtension(const nsCString& aFileExt); private: + nsresult GetApplicationAndParametersFromINI(const nsACString& aProtocol, + char * app, ULONG appLength, + char * param, ULONG paramLength); // Helper methods which have to access static members static nsresult UnescapeCommand(const nsAString& aEscapedCommand, const nsAString& aMajorType,