bug 436998 - Implement -app parameter support for xulrunner-stub r=mfinkle, bsmedberg
authorAntonio Gomes <tonikitoo@gmail.com>
Thu, 16 Apr 2009 15:19:32 -0400
changeset 27408 fc10ea0d9806c7e93cab1b8ef511463b67ec9156
parent 27407 93bc0760d0d2b927797719948d3953eec9af63d5
child 27409 6a9dbf40d6f863edffee33c9d94f453d852bc823
push idunknown
push userunknown
push dateunknown
reviewersmfinkle, bsmedberg
bugs436998
milestone1.9.2a1pre
bug 436998 - Implement -app parameter support for xulrunner-stub r=mfinkle, bsmedberg
xulrunner/stub/nsXULStub.cpp
--- a/xulrunner/stub/nsXULStub.cpp
+++ b/xulrunner/stub/nsXULStub.cpp
@@ -45,16 +45,17 @@
 
 #include <stdarg.h>
 
 #ifdef XP_WIN
 #include <windows.h>
 #include <io.h>
 #define snprintf _snprintf
 #define vsnprintf _vsnprintf
+#define strcasecmp _stricmp
 #define PATH_SEPARATOR_CHAR '\\'
 #define R_OK 04
 #elif defined(XP_MACOSX)
 #include <CoreFoundation/CoreFoundation.h>
 #define PATH_SEPARATOR_CHAR '/'
 #elif defined (XP_OS2)
 #define INCL_DOS
 #define INCL_DOSMISC
@@ -109,16 +110,70 @@ static void Output(PRBool isError, const
   MessageBoxW(NULL, wide_msg, L"XULRunner", flags);
 #else
   vfprintf(stderr, fmt, ap);
 #endif
 
   va_end(ap);
 }
 
+/**
+ * Return true if |arg| matches the given argument name.
+ */
+static PRBool IsArg(const char* arg, const char* s)
+{
+  if (*arg == '-')
+  {
+    if (*++arg == '-')
+      ++arg;
+    return !strcasecmp(arg, s);
+  }
+
+#if defined(XP_WIN) || defined(XP_OS2)
+  if (*arg == '/')
+    return !strcasecmp(++arg, s);
+#endif
+
+  return PR_FALSE;
+}
+
+/**
+ * Return true if |aDir| is a valid file/directory.
+ */
+static PRBool FolderExists(const char* aDir)
+{
+#ifdef XP_WIN
+  wchar_t wideDir[MAX_PATH];
+  MultiByteToWideChar(CP_UTF8, 0, aDir, -1, wideDir, MAX_PATH);
+  DWORD fileAttrs = GetFileAttributesW(wideDir);
+  return fileAttrs != INVALID_FILE_ATTRIBUTES;
+#else
+  return access(aDir, R_OK) == 0;
+#endif
+}
+
+static nsresult GetRealPath(const char* appDataFile, char* *aResult)
+{
+#ifdef XP_WIN
+  wchar_t wAppDataFile[MAX_PATH];
+  wchar_t wIniPath[MAX_PATH];
+  MultiByteToWideChar(CP_UTF8, 0, appDataFile, -1, wAppDataFile, MAX_PATH);
+  _wfullpath(wIniPath, wAppDataFile, MAX_PATH);
+  WideCharToMultiByte(CP_UTF8, 0, wIniPath, -1, *aResult, MAX_PATH, 0, 0);
+#else
+  struct stat fileStat;
+  if (!realpath(appDataFile, *aResult) || stat(*aResult, &fileStat))
+    return NS_ERROR_FAILURE;
+#endif
+  if (!*aResult || !**aResult)
+    return NS_ERROR_FAILURE;
+
+  return NS_OK;
+}
+
 class AutoAppData
 {
 public:
   AutoAppData(nsILocalFile* aINIFile) : mAppData(nsnull) {
     nsresult rv = XRE_CreateAppData(aINIFile, &mAppData);
     if (NS_FAILED(rv))
       mAppData = nsnull;
   }
@@ -184,19 +239,18 @@ main(int argc, char **argv)
 
 #else
 
 #ifdef XP_WIN
   wchar_t wide_path[MAX_PATH];
   if (!::GetModuleFileNameW(NULL, wide_path, MAX_PATH))
     return 1;
 
-  WideCharToMultiByte(CP_ACP, 0, wide_path,-1,
+  WideCharToMultiByte(CP_UTF8, 0, wide_path,-1,
 		      iniPath, MAX_PATH, NULL, NULL);
-  
 
 #elif defined(XP_OS2)
    PPIB ppib;
    PTIB ptib;
 
    DosGetInfoBlocks(&ptib, &ppib);
    DosQueryModuleName(ppib->pib_hmte, sizeof(iniPath), iniPath);
 
@@ -255,28 +309,70 @@ main(int argc, char **argv)
   *(++lastSlash) = '\0';
 
   // On Linux/Win, look for XULRunner in appdir/xulrunner
 
   snprintf(greDir, sizeof(greDir),
            "%sxulrunner" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL,
            iniPath);
 
-#ifdef WINCE
-  wchar_t wideGreDir[MAX_PATH];
-  MultiByteToWideChar(CP_ACP, 0, greDir, -1, wideGreDir, MAX_PATH);
-  DWORD fileAttrs = GetFileAttributesW(wideGreDir);
-  greFound = fileAttrs != INVALID_FILE_ATTRIBUTES;
-#else
-  greFound = (access(greDir, R_OK) == 0);
-#endif
+  greFound = FolderExists(greDir);
+
   strncpy(lastSlash, "application.ini", sizeof(iniPath) - (lastSlash - iniPath));
 
 #endif
 
+  // If -app parameter was passed in, it is now time to take it under 
+  // consideration.
+  const char *appDataFile;
+  appDataFile = getenv("XUL_APP_FILE");
+  if (!appDataFile || !*appDataFile) 
+    if (argc > 1 && IsArg(argv[1], "app")) {
+      if (argc == 2) {
+        Output(PR_FALSE, "specify APP-FILE (optional)\n");
+        return 1;
+      }
+      argv[1] = argv[0];
+      ++argv;
+      --argc;
+
+      appDataFile = argv[1];
+      argv[1] = argv[0];
+      ++argv;
+      --argc;
+
+      char kAppEnv[MAXPATHLEN];
+      snprintf(kAppEnv, MAXPATHLEN, "XUL_APP_FILE=%s", appDataFile);
+      if (putenv(kAppEnv)) 
+        Output(PR_FALSE, "Couldn't set %s.\n", kAppEnv);
+
+      char *result = (char*) calloc(sizeof(char), MAXPATHLEN);
+      if (NS_FAILED(GetRealPath(appDataFile, &result))) {
+        Output(PR_TRUE, "Invalid application.ini path.\n");
+        return 1;
+      }
+      
+      // We have a valid application.ini path passed in to the -app parameter 
+      // but not yet a valid greDir, so lets look for it also on the same folder
+      // as the stub.
+      if (!greFound) {
+        lastSlash = strrchr(iniPath, PATH_SEPARATOR_CHAR);
+        if (!lastSlash)
+          return 1;
+
+        *(++lastSlash) = '\0';
+
+        snprintf(greDir, sizeof(greDir), "%s" XPCOM_DLL, iniPath);
+        greFound = FolderExists(greDir);
+      }
+      
+      // copy it back.
+      strcpy(iniPath, result);
+    }
+  
   nsINIParser parser;
   rv = parser.Init(iniPath);
   if (NS_FAILED(rv)) {
     fprintf(stderr, "Could not read application.ini\n");
     return 1;
   }
 
   if (!greFound) {