Bug 704622 - Sync the OSX and Unix logic for handling file name extensions. r=smichaud, a=akeybl.
authorRafael Ávila de Espíndola <respindola@mozilla.com>
Thu, 08 Dec 2011 15:27:10 -0500
changeset 35235 eefedeec832edabd7a2d0c4196c057eb7665a02b
parent 35234 5a3c09ad5f4ae4acd218323e23e88651081fbdea
child 35236 489b4f2582a338f1bc12ad806d9117c74404d233
child 35239 677e7959cf6c4b3f83a35a986f04fee796e12acf
push id2005
push userrespindola@mozilla.com
push dateThu, 08 Dec 2011 20:30:12 +0000
reviewerssmichaud, akeybl
bugs704622
milestone1.9.2.25pre
Bug 704622 - Sync the OSX and Unix logic for handling file name extensions. r=smichaud, a=akeybl.
xpcom/io/nsLocalFileOSX.mm
--- a/xpcom/io/nsLocalFileOSX.mm
+++ b/xpcom/io/nsLocalFileOSX.mm
@@ -952,18 +952,56 @@ NS_IMETHODIMP nsLocalFile::IsExecutable(
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   CHECK_INIT();
 
   NS_ENSURE_ARG_POINTER(_retval);
   *_retval = PR_FALSE;
   
+  // Check extension (bug 663899). On certain platforms, the file
+  // extension may cause the OS to treat it as executable regardless of
+  // the execute bit, such as .jar on Mac OS X. We borrow the code from
+  // nsLocalFileWin, slightly modified.
+
+  // Don't be fooled by symlinks.
+  PRBool symLink;
+  nsresult rv = IsSymlink(&symLink);
+  if (NS_FAILED(rv))
+      return rv;
+
+  nsAutoString path;
+  if (symLink)
+      GetTarget(path);
+  else
+      GetPath(path);
+  
+  PRInt32 dotIdx = path.RFindChar(PRUnichar('.'));
+  if (dotIdx != kNotFound) {
+      // Convert extension to lower case.
+      PRUnichar *p = path.BeginWriting();
+      for(p += dotIdx + 1; *p; p++)
+          *p +=  (*p >= L'A' && *p <= L'Z') ? 'a' - 'A' : 0; 
+        
+      // Search for any of the set of executable extensions.
+      static const char * const executableExts[] = {
+          "air",         // Adobe AIR installer
+          "jar"};        // java application bundle
+      nsDependentSubstring ext = Substring(path, dotIdx + 1);
+      for (int i = 0; i < NS_ARRAY_LENGTH(executableExts); i++) {
+          if (ext.EqualsASCII(executableExts[i])) {
+              // Found a match.  Set result and quit.
+              *_retval = PR_TRUE;
+              return NS_OK;
+          }
+      }
+  }
+
   FSRef fsRef;
-  nsresult rv = GetFSRefInternal(fsRef);
+  rv = GetFSRefInternal(fsRef);
   if (NS_FAILED(rv))
     return rv;
     
   LSRequestedInfo theInfoRequest = kLSRequestAllInfo;
   LSItemInfoRecord theInfo;
   if (::LSCopyItemInfoForRef(&fsRef, theInfoRequest, &theInfo) == noErr) {
     if ((theInfo.flags & kLSItemInfoIsApplication) != 0)
     *_retval = PR_TRUE;