diff --git a/browser/components/nsBrowserContentHandler.js b/browser/components/nsBrowserContentHandler.js index bc0fdf622b8..24f8d9b7b40 100644 --- a/browser/components/nsBrowserContentHandler.js +++ b/browser/components/nsBrowserContentHandler.js @@ -61,6 +61,7 @@ const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher; const nsICategoryManager = Components.interfaces.nsICategoryManager; const nsIWebNavigationInfo = Components.interfaces.nsIWebNavigationInfo; const nsIBrowserSearchService = Components.interfaces.nsIBrowserSearchService; +const nsICommandLineValidator = Components.interfaces.nsICommandLineValidator; const NS_BINDING_ABORTED = 0x804b0002; const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001; @@ -301,6 +302,7 @@ var nsBrowserContentHandler = { !iid.equals(nsICommandLineHandler) && !iid.equals(nsIBrowserHandler) && !iid.equals(nsIContentHandler) && + !iid.equals(nsICommandLineValidator) && !iid.equals(nsIFactory)) throw Components.results.NS_ERROR_NO_INTERFACE; @@ -604,6 +606,21 @@ var nsBrowserContentHandler = { request.cancel(NS_BINDING_ABORTED); }, + /* nsICommandLineValidator */ + validate : function bch_validate(cmdLine) { + // Other handlers may use osint so only handle the osint flag if the url + // flag is also present and the command line is valid. + var osintFlagIdx = cmdLine.findFlag("osint", false); + var urlFlagIdx = cmdLine.findFlag("url", false); + if (urlFlagIdx > -1 && (osintFlagIdx > -1 || + cmdLine.state == nsICommandLine.STATE_REMOTE_EXPLICIT)) { + var urlParam = cmdLine.getArgument(urlFlagIdx + 1); + if (cmdLine.length != urlFlagIdx + 2 || /firefoxurl:/.test(urlParam)) + throw NS_ERROR_ABORT; + cmdLine.handleFlag("osint", false) + } + }, + /* nsIFactory */ createInstance: function bch_CI(outer, iid) { if (outer != null) @@ -866,6 +883,9 @@ var Module = { catMan.addCategoryEntry("command-line-handler", "x-default", dch_contractID, true, true); + catMan.addCategoryEntry("command-line-validator", + "b-browser", + bch_contractID, true, true); }, unregisterSelf : function mod_unregself(compMgr, location, type) { @@ -880,6 +900,8 @@ var Module = { "m-browser", true); catMan.deleteCategoryEntry("command-line-handler", "x-default", true); + catMan.deleteCategoryEntry("command-line-validator", + "b-browser", true); }, canUnload: function(compMgr) { diff --git a/browser/components/shell/src/nsWindowsShellService.cpp b/browser/components/shell/src/nsWindowsShellService.cpp index cd76ec0a9f3..edc717985cd 100644 --- a/browser/components/shell/src/nsWindowsShellService.cpp +++ b/browser/components/shell/src/nsWindowsShellService.cpp @@ -151,7 +151,7 @@ OpenKeyForWriting(HKEY aStartKey, const char* aKeyName, HKEY* aKey, // // HKCU\SOFTWARE\Classes\FirefoxHTML\ // DefaultIcon (default) REG_SZ ,1 -// shell\open\command (default) REG_SZ -url "%1" -requestPending +// shell\open\command (default) REG_SZ -requestPending -osint -url "%1" // shell\open\ddeexec (default) REG_SZ "%1",,0,0,,,, // shell\open\ddeexec NoActivateHandler REG_SZ // \Application (default) REG_SZ Firefox @@ -163,7 +163,7 @@ OpenKeyForWriting(HKEY aStartKey, const char* aKeyName, HKEY* aKey, // EditFlags REG_DWORD 2 // FriendlyTypeName REG_SZ URL // DefaultIcon (default) REG_SZ ,1 -// shell\open\command (default) REG_SZ -url "%1" -requestPending +// shell\open\command (default) REG_SZ -requestPending -osint -url "%1" // shell\open\ddeexec (default) REG_SZ "%1",,0,0,,,, // shell\open\ddeexec NoActivateHandler REG_SZ // \Application (default) REG_SZ Firefox @@ -177,7 +177,7 @@ OpenKeyForWriting(HKEY aStartKey, const char* aKeyName, HKEY* aKey, // // HKCU\SOFTWARE\Classes\\ // DefaultIcon (default) REG_SZ ,1 -// shell\open\command (default) REG_SZ -url "%1" -requestPending +// shell\open\command (default) REG_SZ -requestPending -osint -url "%1" // shell\open\ddeexec (default) REG_SZ "%1",,0,0,,,, // shell\open\ddeexec NoActivateHandler REG_SZ // \Application (default) REG_SZ Firefox @@ -232,7 +232,7 @@ typedef struct { #define CLS_HTML "FirefoxHTML" #define CLS_URL "FirefoxURL" #define VAL_FILE_ICON "%APPPATH%,1" -#define VAL_OPEN "\"%APPPATH%\" -url \"%1\" -requestPending" +#define VAL_OPEN "\"%APPPATH%\" -requestPending -osint -url \"%1\"" #define MAKE_KEY_NAME1(PREFIX, MID) \ PREFIX MID diff --git a/browser/installer/windows/nsis/shared.nsh b/browser/installer/windows/nsis/shared.nsh index 7516564cc62..862cee9d079 100755 --- a/browser/installer/windows/nsis/shared.nsh +++ b/browser/installer/windows/nsis/shared.nsh @@ -136,7 +136,7 @@ GetFullPathName $8 "$INSTDIR\${FileMainEXE}" StrCpy $0 "SOFTWARE\Classes" - StrCpy $2 "$\"$8$\" -url $\"%1$\" -requestPending" + StrCpy $2 "$\"$8$\" -requestPending -osint -url $\"%1$\"" ; Associate the file handlers with FirefoxHTML WriteRegStr SHCTX "$0\.htm" "" "FirefoxHTML" @@ -364,7 +364,7 @@ ; Store the command to open the app with an url in a register for easy access. GetFullPathName $8 "$INSTDIR\${FileMainEXE}" - StrCpy $1 "$\"$8$\" -url $\"%1$\" -requestPending" + StrCpy $1 "$\"$8$\" -requestPending -osint -url $\"%1$\"" ; Always set the file and protocol handlers since they may specify a ; different path and the path is used by Vista when setting associations. diff --git a/mail/components/nsMailDefaultHandler.js b/mail/components/nsMailDefaultHandler.js index 9f94d07789e..bc45e4a794a 100644 --- a/mail/components/nsMailDefaultHandler.js +++ b/mail/components/nsMailDefaultHandler.js @@ -40,6 +40,7 @@ const nsISupports = Components.interfaces.nsISupports; const nsICommandLine = Components.interfaces.nsICommandLine; const nsICommandLineHandler = Components.interfaces.nsICommandLineHandler; +const nsICommandLineValidator = Components.interfaces.nsICommandLineValidator; const nsIDOMWindowInternal = Components.interfaces.nsIDOMWindowInternal; const nsIFactory = Components.interfaces.nsIFactory; const nsISupportsString = Components.interfaces.nsISupportsString; @@ -123,6 +124,7 @@ var nsMailDefaultHandler = { QueryInterface : function mdh_QI(iid) { if (iid.equals(nsICommandLineHandler) || + iid.equals(nsICommandLineValidator) || iid.equals(nsIFactory) || iid.equals(nsISupports)) return this; @@ -294,6 +296,30 @@ var nsMailDefaultHandler = { } }, + /* nsICommandLineValidator */ + validate : function mdh_validate(cmdLine) { + // Other handlers may use osint so only handle the osint flag if the mail + // or compose flag is also present and the command line is valid. + var osintFlagIdx = cmdLine.findFlag("osint", false); + var mailFlagIdx = cmdLine.findFlag("mail", false); + var composeFlagIdx = cmdLine.findFlag("compose", false); + + // If both flags are present use the first flag found so the command line + // length test will fail. + if (mailFlagIdx > -1 && composeFlagIdx > -1) + var actionFlagIdx = mailFlagIdx > composeFlagIdx ? composeFlagIdx : mailFlagIdx; + else + actionFlagIdx = mailFlagIdx > -1 ? mailFlagIdx : composeFlagIdx; + + if (actionFlagIdx && (osintFlagIdx > -1)) { + var param = cmdLine.getArgument(actionFlagIdx + 1); + if (cmdLine.length != actionFlagIdx + 2 || + /thunderbird.url.(mailto|news):/.test(param)) + throw NS_ERROR_ABORT; + cmdLine.handleFlag("osint", false) + } + }, + helpInfo : "", /* nsIFactory */ @@ -349,6 +375,9 @@ var Module = { catMan.addCategoryEntry("command-line-handler", "x-default", mdh_contractID, true, true); + catMan.addCategoryEntry("command-line-validator", + "b-default", + mdh_contractID, true, true); }, unregisterSelf : function mod_unregself(compMgr, location, type) { @@ -359,7 +388,9 @@ var Module = { .getService(Components.interfaces.nsICategoryManager); catMan.deleteCategoryEntry("command-line-handler", - "y-default", true); + "x-default", true); + catMan.deleteCategoryEntry("command-line-validator", + "b-default", true); }, canUnload: function(compMgr) { diff --git a/mail/components/shell/nsMailWinIntegration.cpp b/mail/components/shell/nsMailWinIntegration.cpp index 5b8b8c8cc8b..2580eaa228b 100644 --- a/mail/components/shell/nsMailWinIntegration.cpp +++ b/mail/components/shell/nsMailWinIntegration.cpp @@ -174,11 +174,11 @@ static SETTING gMailSettings[] = { // Protocol Handler Class - for Vista and above { MAKE_KEY_NAME2(CLS, CLS_MAILTOURL, DI), "", VAL_ICON, APP_PATH_SUBSTITUTION }, - { MAKE_KEY_NAME2(CLS, CLS_MAILTOURL, SOP), "", "\"%APPPATH%\" -compose \"%1\"", APP_PATH_SUBSTITUTION }, + { MAKE_KEY_NAME2(CLS, CLS_MAILTOURL, SOP), "", "\"%APPPATH%\" -osint -compose \"%1\"", APP_PATH_SUBSTITUTION }, // Protocol Handlers { MAKE_KEY_NAME2(CLS, "mailto", DI), "", VAL_ICON, APP_PATH_SUBSTITUTION}, - { MAKE_KEY_NAME2(CLS, "mailto", SOP), "", "\"%APPPATH%\" -compose \"%1\"", APP_PATH_SUBSTITUTION | USE_FOR_DEFAULT_TEST}, + { MAKE_KEY_NAME2(CLS, "mailto", SOP), "", "\"%APPPATH%\" -osint -compose \"%1\"", APP_PATH_SUBSTITUTION | USE_FOR_DEFAULT_TEST}, // Mail Client Keys { MAKE_KEY_NAME1(MAILCLIENTS, "%APPNAME%"), @@ -214,15 +214,15 @@ static SETTING gMailSettings[] = { static SETTING gNewsSettings[] = { // Protocol Handler Class - for Vista and above { MAKE_KEY_NAME2(CLS, CLS_NEWSURL, DI), "", VAL_ICON, APP_PATH_SUBSTITUTION }, - { MAKE_KEY_NAME2(CLS, CLS_NEWSURL, SOP), "", "\"%APPPATH%\" -mail \"%1\"", APP_PATH_SUBSTITUTION }, + { MAKE_KEY_NAME2(CLS, CLS_NEWSURL, SOP), "", "\"%APPPATH%\" -osint -mail \"%1\"", APP_PATH_SUBSTITUTION }, // Protocol Handlers { MAKE_KEY_NAME2(CLS, "news", DI), "", VAL_ICON, APP_PATH_SUBSTITUTION}, - { MAKE_KEY_NAME2(CLS, "news", SOP), "", "\"%APPPATH%\" -mail \"%1\"", APP_PATH_SUBSTITUTION | USE_FOR_DEFAULT_TEST}, + { MAKE_KEY_NAME2(CLS, "news", SOP), "", "\"%APPPATH%\" -osint -mail \"%1\"", APP_PATH_SUBSTITUTION | USE_FOR_DEFAULT_TEST}, { MAKE_KEY_NAME2(CLS, "nntp", DI), "", VAL_ICON, APP_PATH_SUBSTITUTION}, - { MAKE_KEY_NAME2(CLS, "nntp", SOP), "", "\"%APPPATH%\" -mail \"%1\"", APP_PATH_SUBSTITUTION | USE_FOR_DEFAULT_TEST}, + { MAKE_KEY_NAME2(CLS, "nntp", SOP), "", "\"%APPPATH%\" -osint -mail \"%1\"", APP_PATH_SUBSTITUTION | USE_FOR_DEFAULT_TEST}, { MAKE_KEY_NAME2(CLS, "snews", DI), "", VAL_ICON, APP_PATH_SUBSTITUTION}, - { MAKE_KEY_NAME2(CLS, "snews", SOP), "", "\"%APPPATH%\" -mail \"%1\"", APP_PATH_SUBSTITUTION}, + { MAKE_KEY_NAME2(CLS, "snews", SOP), "", "\"%APPPATH%\" -osint -mail \"%1\"", APP_PATH_SUBSTITUTION}, // News Client Keys { MAKE_KEY_NAME1(NEWSCLIENTS, "%APPNAME%"), @@ -246,7 +246,7 @@ static SETTING gFeedSettings[] = { // Protocol Handlers { MAKE_KEY_NAME2(CLS, "feed", DI), "", VAL_ICON, APP_PATH_SUBSTITUTION}, - { MAKE_KEY_NAME2(CLS, "feed", SOP), "", "\"%APPPATH%\" -mail \"%1\"", APP_PATH_SUBSTITUTION | USE_FOR_DEFAULT_TEST}, + { MAKE_KEY_NAME2(CLS, "feed", SOP), "", "\"%APPPATH%\" -osint -mail \"%1\"", APP_PATH_SUBSTITUTION | USE_FOR_DEFAULT_TEST}, }; nsresult nsWindowsShellService::Init() diff --git a/mail/installer/windows/nsis/shared.nsh b/mail/installer/windows/nsis/shared.nsh index 52d2c6b7df0..77dd5e0a981 100755 --- a/mail/installer/windows/nsis/shared.nsh +++ b/mail/installer/windows/nsis/shared.nsh @@ -135,8 +135,8 @@ GetFullPathName $8 "$INSTDIR\${FileMainEXE}" StrCpy $0 "SOFTWARE\Classes" - StrCpy $2 "$\"$8$\" -mail $\"%1$\"" - StrCpy $3 "$\"$8$\" -compose $\"%1$\"" + StrCpy $2 "$\"$8$\" -osint -mail $\"%1$\"" + StrCpy $3 "$\"$8$\" -osint -compose $\"%1$\"" ; Associate the file handlers with ThunderbirdEML WriteRegStr SHCTX "$0\.eml" "" "ThunderbirdEML" @@ -218,7 +218,7 @@ WriteRegStr HKLM "$0\shell\safemode\command" "" "$\"$8$\" -safe-mode" ; Protocols - StrCpy $1 "$\"$8$\" -compose $\"%1$\"" + StrCpy $1 "$\"$8$\" -osint -compose $\"%1$\"" ${AddHandlerValues} "$0\Protocols\mailto" "$1" "$8,0" "${AppRegNameMail} URL" "true" "" ; Vista Capabilities registry keys @@ -253,7 +253,7 @@ WriteRegStr HKLM "$0\Capabilities\URLAssociations" "snews" "Thunderbird.Url.news" ; Protocols - StrCpy $1 "$\"$8$\" -mail $\"%1$\"" + StrCpy $1 "$\"$8$\" -osint -mail $\"%1$\"" ${AddHandlerValues} "$0\Protocols\nntp" "$1" "$8,0" "${AppRegNameNews} URL" "true" "" ${AddHandlerValues} "$0\Protocols\news" "$1" "$8,0" "${AppRegNameNews} URL" "true" "" ${AddHandlerValues} "$0\Protocols\snews" "$1" "$8,0" "${AppRegNameNews} URL" "true" "" @@ -361,7 +361,7 @@ StrCpy $0 "SOFTWARE\Classes" GetFullPathName $8 "$INSTDIR\${FileMainEXE}" - StrCpy $1 "$\"$8$\" -compose $\"%1$\"" + StrCpy $1 "$\"$8$\" -osint -compose $\"%1$\"" ${AddHandlerValues} "$0\Thunderbird.Url.mailto" "$1" "$8,0" "${AppRegNameMail} URL" "true" "" ReadRegStr $2 SHCTX "$0\mailto\shell\open\command" "" @@ -376,7 +376,7 @@ StrCpy $1 "$\"$8$\" $\"%1$\"" ${AddHandlerValues} "$0\ThunderbirdEML" "$1" "$8,0" "${AppRegNameMail} Document" "" "" - StrCpy $1 "$\"$8$\" -mail $\"%1$\"" + StrCpy $1 "$\"$8$\" -osint -mail $\"%1$\"" ${AddHandlerValues} "$0\Thunderbird.Url.news" "$1" "$8,0" "${AppRegNameNews} URL" "true" "" ReadRegStr $2 SHCTX "$0\news\shell\open\command" "" diff --git a/toolkit/components/commandlines/public/Makefile.in b/toolkit/components/commandlines/public/Makefile.in index 64890e045bc..03420076ba7 100644 --- a/toolkit/components/commandlines/public/Makefile.in +++ b/toolkit/components/commandlines/public/Makefile.in @@ -49,6 +49,7 @@ XPIDLSRCS = \ nsICommandLine.idl \ nsICommandLineRunner.idl \ nsICommandLineHandler.idl \ + nsICommandLineValidator.idl \ $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/toolkit/components/commandlines/public/nsICommandLineValidator.idl b/toolkit/components/commandlines/public/nsICommandLineValidator.idl new file mode 100644 index 00000000000..327070d1146 --- /dev/null +++ b/toolkit/components/commandlines/public/nsICommandLineValidator.idl @@ -0,0 +1,70 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla toolkit. + * + * The Initial Developer of the Original Code is + * Robert Strong + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +interface nsICommandLine; + +/** + * Validates arguments on the command line of an XUL application. + * + * Each validator is registered in the category "command-line-validator". + * The entries in this category are read in alphabetical order, and each + * category value is treated as a service contractid implementing this + * interface. + * + * By convention, validator with ordinary priority should begin with "m". + * + * Example: + * Category Entry Value + * command-line-validator b-browser @mozilla.org/browser/clh;1 + * command-line-validator m-edit @mozilla.org/composer/clh;1 + * command-line-validator m-irc @mozilla.org/chatzilla/clh;1 + * + */ + +[scriptable, uuid(5ecaa593-7660-4a3a-957a-92d5770671c7)] +interface nsICommandLineValidator : nsISupports +{ + /** + * Process the command-line validators in the proper order, calling + * "validate()" on each. + * + * @throws NS_ERROR_ABORT if any validator throws NS_ERROR_ABORT. All other + * errors thrown by validators will be silently ignored. + */ + void validate(in nsICommandLine aCommandLine); +}; diff --git a/toolkit/components/commandlines/src/nsCommandLine.cpp b/toolkit/components/commandlines/src/nsCommandLine.cpp index 9f360de1324..706a109237e 100644 --- a/toolkit/components/commandlines/src/nsCommandLine.cpp +++ b/toolkit/components/commandlines/src/nsCommandLine.cpp @@ -39,6 +39,7 @@ #include "nsICategoryManager.h" #include "nsICommandLineHandler.h" +#include "nsICommandLineValidator.h" #include "nsIClassInfoImpl.h" #include "nsIDOMWindow.h" #include "nsIFile.h" @@ -86,12 +87,16 @@ public: protected: ~nsCommandLine() { } - typedef nsresult (*EnumerateCallback)(nsICommandLineHandler* aHandler, + typedef nsresult (*EnumerateHandlersCallback)(nsICommandLineHandler* aHandler, + nsICommandLine* aThis, + void *aClosure); + typedef nsresult (*EnumerateValidatorsCallback)(nsICommandLineValidator* aValidator, nsICommandLine* aThis, void *aClosure); void appendArg(const char* arg); - nsresult EnumerateHandlers(EnumerateCallback aCallback, void *aClosure); + nsresult EnumerateHandlers(EnumerateHandlersCallback aCallback, void *aClosure); + nsresult EnumerateValidators(EnumerateValidatorsCallback aCallback, void *aClosure); nsStringArray mArgs; PRUint32 mState; @@ -537,7 +542,7 @@ nsCommandLine::Init(PRInt32 argc, char** argv, nsIFile* aWorkingDir, } nsresult -nsCommandLine::EnumerateHandlers(EnumerateCallback aCallback, void *aClosure) +nsCommandLine::EnumerateHandlers(EnumerateHandlersCallback aCallback, void *aClosure) { nsresult rv; @@ -579,6 +584,55 @@ nsCommandLine::EnumerateHandlers(EnumerateCallback aCallback, void *aClosure) return rv; } +nsresult +nsCommandLine::EnumerateValidators(EnumerateValidatorsCallback aCallback, void *aClosure) +{ + nsresult rv; + + nsCOMPtr catman + (do_GetService(NS_CATEGORYMANAGER_CONTRACTID)); + NS_ENSURE_TRUE(catman, NS_ERROR_UNEXPECTED); + + nsCOMPtr entenum; + rv = catman->EnumerateCategory("command-line-validator", + getter_AddRefs(entenum)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr strenum (do_QueryInterface(entenum)); + NS_ENSURE_TRUE(strenum, NS_ERROR_UNEXPECTED); + + nsCAutoString entry; + PRBool hasMore; + while (NS_SUCCEEDED(strenum->HasMore(&hasMore)) && hasMore) { + strenum->GetNext(entry); + + nsXPIDLCString contractID; + rv = catman->GetCategoryEntry("command-line-validator", + entry.get(), + getter_Copies(contractID)); + if (!contractID) + continue; + + nsCOMPtr clv(do_GetService(contractID.get())); + if (!clv) + continue; + + rv = (aCallback)(clv, this, aClosure); + if (rv == NS_ERROR_ABORT) + break; + + rv = NS_OK; + } + + return rv; +} + +static nsresult +EnumValidate(nsICommandLineValidator* aValidator, nsICommandLine* aThis, void*) +{ + return aValidator->Validate(aThis); +} + static nsresult EnumRun(nsICommandLineHandler* aHandler, nsICommandLine* aThis, void*) { @@ -590,6 +644,10 @@ nsCommandLine::Run() { nsresult rv; + rv = EnumerateValidators(EnumValidate, nsnull); + if (rv == NS_ERROR_ABORT) + return rv; + rv = EnumerateHandlers(EnumRun, nsnull); if (rv == NS_ERROR_ABORT) return rv; diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 5475b7c3ac3..dd1b729ffe9 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -386,13 +386,16 @@ static void RemoveArg(char **argv) * --arg (or /arg on win32/OS2). * * @param aArg the parameter to check. Must be lowercase. + * @param aCheckOSInt if true returns ARG_BAD if the osint argument is present + * when aArg is also present. * @param if non-null, the -arg will be stored in this pointer. This is *not* * allocated, but rather a pointer to the argv data. */ static ArgResult -CheckArg(const char* aArg, const char **aParam = nsnull) +CheckArg(const char* aArg, PRBool aCheckOSInt = PR_FALSE, const char **aParam = nsnull) { char **curarg = gArgv + 1; // skip argv[0] + ArgResult ar = ARG_NONE; while (*curarg) { char *arg = curarg[0]; @@ -409,7 +412,8 @@ CheckArg(const char* aArg, const char **aParam = nsnull) if (strimatch(aArg, arg)) { RemoveArg(curarg); if (!aParam) { - return ARG_FOUND; + ar = ARG_FOUND; + break; } if (*curarg) { @@ -422,7 +426,8 @@ CheckArg(const char* aArg, const char **aParam = nsnull) *aParam = *curarg; RemoveArg(curarg); - return ARG_FOUND; + ar = ARG_FOUND; + break; } return ARG_BAD; } @@ -431,7 +436,15 @@ CheckArg(const char* aArg, const char **aParam = nsnull) ++curarg; } - return ARG_NONE; + if (aCheckOSInt && ar == ARG_FOUND) { + ArgResult arOSInt = CheckArg("osint"); + if (arOSInt == ARG_FOUND) { + ar = ARG_BAD; + PR_fprintf(PR_STDERR, "Error: argument -osint is invalid\n"); + } + } + + return ar; } #if defined(XP_WIN) @@ -1163,14 +1176,14 @@ HandleRemoteArgument(const char* remote, const char* aDesktopStartupID) ToLowerCase(program); const char *username = getenv("LOGNAME"); - ar = CheckArg("p", &profile); + ar = CheckArg("p", PR_FALSE, &profile); if (ar == ARG_BAD) { PR_fprintf(PR_STDERR, "Error: argument -p requires a profile name\n"); return 1; } const char *temp = nsnull; - ar = CheckArg("a", &temp); + ar = CheckArg("a", PR_FALSE, &temp); if (ar == ARG_BAD) { PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n"); return 1; @@ -1178,7 +1191,7 @@ HandleRemoteArgument(const char* remote, const char* aDesktopStartupID) program.Assign(temp); } - ar = CheckArg("u", &username); + ar = CheckArg("u", PR_FALSE, &username); if (ar == ARG_BAD) { PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n"); return 1; @@ -1221,7 +1234,7 @@ RemoteCommandLine(const char* aDesktopStartupID) const char *username = getenv("LOGNAME"); const char *temp = nsnull; - ar = CheckArg("a", &temp); + ar = CheckArg("a", PR_TRUE, &temp); if (ar == ARG_BAD) { PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n"); return PR_FALSE; @@ -1229,7 +1242,7 @@ RemoteCommandLine(const char* aDesktopStartupID) program.Assign(temp); } - ar = CheckArg("u", &username); + ar = CheckArg("u", PR_TRUE, &username); if (ar == ARG_BAD) { PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n"); return PR_FALSE; @@ -1697,10 +1710,17 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative, *aResult = nsnull; *aStartOffline = PR_FALSE; + ar = CheckArg("offline", PR_TRUE); + if (ar == ARG_BAD) { + PR_fprintf(PR_STDERR, "Error: argument -offline is invalid when argument -osint is specified\n"); + return NS_ERROR_FAILURE; + } + arg = PR_GetEnv("XRE_START_OFFLINE"); - if ((arg && *arg) || CheckArg("offline")) + if ((arg && *arg) || ar) *aStartOffline = PR_TRUE; + arg = PR_GetEnv("XRE_PROFILE_PATH"); if (arg && *arg) { nsCOMPtr lf; @@ -1725,17 +1745,22 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative, // Clear out flags that we handled (or should have handled!) last startup. const char *dummy; - CheckArg("p", &dummy); - CheckArg("profile", &dummy); + CheckArg("p", PR_FALSE, &dummy); + CheckArg("profile", PR_FALSE, &dummy); CheckArg("profilemanager"); return NS_LockProfilePath(lf, localDir, nsnull, aResult); } - if (CheckArg("migration")) + ar = CheckArg("migration", PR_TRUE); + if (ar == ARG_BAD) { + PR_fprintf(PR_STDERR, "Error: argument -migration is invalid when argument -osint is specified\n"); + return NS_ERROR_FAILURE; + } else if (ar == ARG_FOUND) { gDoMigration = PR_TRUE; + } - ar = CheckArg("profile", &arg); + ar = CheckArg("profile", PR_TRUE, &arg); if (ar == ARG_BAD) { PR_fprintf(PR_STDERR, "Error: argument -profile requires a path\n"); return NS_ERROR_FAILURE; @@ -1760,7 +1785,7 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative, rv = NS_NewToolkitProfileService(getter_AddRefs(profileSvc)); NS_ENSURE_SUCCESS(rv, rv); - ar = CheckArg("createprofile", &arg); + ar = CheckArg("createprofile", PR_TRUE, &arg); if (ar == ARG_BAD) { PR_fprintf(PR_STDERR, "Error: argument -createprofile requires a profile name\n"); return NS_ERROR_FAILURE; @@ -1822,11 +1847,21 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative, } } - ar = CheckArg("p", &arg); + ar = CheckArg("p", PR_FALSE, &arg); if (ar == ARG_BAD) { + ar = CheckArg("osint"); + if (ar == ARG_FOUND) { + PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument -osint is specified\n"); + return NS_ERROR_FAILURE; + } return ShowProfileManager(profileSvc, aNative); } if (ar) { + ar = CheckArg("osint"); + if (ar == ARG_FOUND) { + PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument -osint is specified\n"); + return NS_ERROR_FAILURE; + } nsCOMPtr profile; rv = profileSvc->GetProfileByName(nsDependentCString(arg), getter_AddRefs(profile)); @@ -1854,7 +1889,11 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative, return ShowProfileManager(profileSvc, aNative); } - if (CheckArg("profilemanager")) { + ar = CheckArg("profilemanager", PR_TRUE); + if (ar == ARG_BAD) { + PR_fprintf(PR_STDERR, "Error: argument -profilemanager is invalid when argument -osint is specified\n"); + return NS_ERROR_FAILURE; + } else if (ar == ARG_FOUND) { return ShowProfileManager(profileSvc, aNative); } @@ -2219,6 +2258,7 @@ int XRE_main(int argc, char* argv[], const nsXREAppData* aAppData) { nsresult rv; + ArgResult ar; NS_TIMELINE_MARK("enter main"); #ifdef DEBUG @@ -2448,17 +2488,28 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData) ScopedFPHandler handler; #endif /* XP_OS2 */ -#ifdef XP_MACOSX - if (CheckArg("safe-mode") || GetCurrentKeyModifiers() & optionKey) -#else - if (CheckArg("safe-mode")) -#endif + ar = CheckArg("safe-mode", PR_TRUE); + if (ar == ARG_BAD) { + PR_fprintf(PR_STDERR, "Error: argument -safe-mode is invalid when argument -osint is specified\n"); + return 1; + } else if (ar == ARG_FOUND) { gSafeMode = PR_TRUE; + } + +#ifdef XP_MACOSX + if (GetCurrentKeyModifiers() & optionKey) + gSafeMode = PR_TRUE; +#endif // Handle -no-remote command line argument. Setup the environment to // better accommodate other components and various restart scenarios. - if (CheckArg("no-remote")) + ar = CheckArg("no-remote", PR_TRUE); + if (ar == ARG_BAD) { + PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n"); + return 1; + } else if (ar == ARG_FOUND) { PR_SetEnv("MOZ_NO_REMOTE=1"); + } // Handle -help and -version command line arguments. // They should return quickly, so we deal with them here. @@ -2483,7 +2534,11 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData) return 1; // Check for -register, which registers chrome and then exits immediately. - if (CheckArg("register")) { + ar = CheckArg("register", PR_TRUE); + if (ar == ARG_BAD) { + PR_fprintf(PR_STDERR, "Error: argument -register is invalid when argument -osint is specified\n"); + return 1; + } else if (ar == ARG_FOUND) { ScopedXPCOMStartup xpcom; rv = xpcom.Initialize(); NS_ENSURE_SUCCESS(rv, 1); @@ -2584,7 +2639,7 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData) // handle -remote now that xpcom is fired up const char* xremotearg; - ArgResult ar = CheckArg("remote", &xremotearg); + ar = CheckArg("remote", PR_TRUE, &xremotearg); if (ar == ARG_BAD) { PR_fprintf(PR_STDERR, "Error: -remote requires an argument\n"); return 1; @@ -2804,7 +2859,21 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData) nsCOMPtr em(do_GetService("@mozilla.org/extensions/manager;1")); NS_ENSURE_TRUE(em, 1); - if (CheckArg("install-global-extension") || CheckArg("install-global-theme")) { + ar = CheckArg("install-global-extension", PR_TRUE); + if (ar == ARG_BAD) { + PR_fprintf(PR_STDERR, "Error: argument -install-global-extension is invalid when argument -osint is specified\n"); + return 1; + } else if (ar == ARG_FOUND) { + // Do the required processing and then shut down. + em->HandleCommandLineArgs(cmdLine); + return 0; + } + + ar = CheckArg("install-global-theme", PR_TRUE); + if (ar == ARG_BAD) { + PR_fprintf(PR_STDERR, "Error: argument -install-global-theme is invalid when argument -osint is specified\n"); + return 1; + } else if (ar == ARG_FOUND) { // Do the required processing and then shut down. em->HandleCommandLineArgs(cmdLine); return 0;