Bug 704622 - Sync the OSX and Unix logic for handling file name extensions. r=smichaud, a=akeybl.
--- 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;