summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Gaist <samuel.gaist@edeltech.ch>2014-05-02 07:26:25 (GMT)
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-05-02 21:15:30 (GMT)
commit4c45b6ca8ae38f56efab881f3c996a8a89edbd08 (patch)
treeb9b3cfa02e3a24e15a624048b612ada7ac4dd9df
parent136ab6592f8034e3954fb8842ed6e2f40cee2b86 (diff)
downloadQt-4c45b6ca8ae38f56efab881f3c996a8a89edbd08.zip
Qt-4c45b6ca8ae38f56efab881f3c996a8a89edbd08.tar.gz
Qt-4c45b6ca8ae38f56efab881f3c996a8a89edbd08.tar.bz2
Refactor OS X bundle detection for QFileInfo
CFBundleGetPackageInfoInDirectory originally used tests for the presence of information that are not mandatory in a bundle. Following Apple's documentation, the new approach is to use Uniform Type Identifier which queries the OS directly to check whether the extension conforms to kUTTypeBundle. That includes e.g. applications, frameworks etc. Then it tries to determine if the bundle can be opened with an application that is not Finder. Last thing, it checks whether the package bit is set. (cherry picked from qtbase/72d60ea08c14037250459a5424ffee7a36b909b1) (cherry picked from qtbase/bcfc68f9cd00982decd7ceb312966caf6b1ca05e) (cherry picked from qtbase/afacf694d5a6f34b88989e76971d70d700ce4949) Task-number: QTBUG-31884 Change-Id: I4ce3d8b90d116960b2044d3fafe3f745f6141416 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp78
-rw-r--r--src/tools/bootstrap/bootstrap.pro2
2 files changed, 66 insertions, 14 deletions
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index 3aa179b..0261600 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -34,6 +34,7 @@
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
+** Copyright (C) 2014 Samuel Gaist <samuel.gaist@edeltech.ch>
**
** $QT_END_LICENSE$
**
@@ -44,6 +45,7 @@
#include "qplatformdefs.h"
#include "qfsfileengine.h"
#include "qfile.h"
+#include "qfileinfo.h"
#include <QtCore/qvarlengtharray.h>
@@ -52,11 +54,14 @@
#include <stdio.h>
#include <errno.h>
-
#if defined(Q_OS_MAC)
# include <QtCore/private/qcore_mac_p.h>
#endif
+#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC)
+# include <CoreFoundation/CFBundle.h>
+#endif
+
QT_BEGIN_NAMESPACE
#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC)
@@ -78,6 +83,63 @@ static inline bool _q_isMacHidden(const char *nativePath)
FileInfo * const fileInfo = reinterpret_cast<FileInfo*>(&catInfo.finderInfo);
return (fileInfo->finderFlags & kIsInvisible);
}
+
+static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &entry)
+{
+ if (!data.isDirectory())
+ return false;
+
+ QFileInfo info(entry.filePath());
+ QString suffix = info.suffix();
+
+ if (suffix.length() > 0) {
+ // First step: is the extension known ?
+ CFStringRef extensionRef = QCFString::toCFStringRef(suffix);
+ CFStringRef uniformTypeIdentifier = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extensionRef, NULL);
+ if (UTTypeConformsTo(uniformTypeIdentifier, kUTTypeBundle))
+ return true;
+
+ // Second step: check if an application knows the package type
+ CFStringRef path = QCFString::toCFStringRef(entry.filePath());
+ QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle, true);
+
+ UInt32 type, creator;
+ // Well created packages have the PkgInfo file
+ if (CFBundleGetPackageInfoInDirectory(url, &type, &creator))
+ return true;
+
+ // Find if an application other than Finder claims to know how to handle the package
+ QCFType<CFURLRef> application;
+ LSGetApplicationForURL(url,
+ kLSRolesEditor|kLSRolesViewer|kLSRolesViewer,
+ NULL,
+ &application);
+
+ if (application) {
+ QCFType<CFBundleRef> bundle = CFBundleCreate(kCFAllocatorDefault, application);
+ CFStringRef identifier = CFBundleGetIdentifier(bundle);
+ QString applicationId = QCFString::toQString(identifier);
+ if (applicationId != QLatin1String("com.apple.finder"))
+ return true;
+ }
+ }
+
+ // Third step: check if the directory has the package bit set
+ FSRef packageRef;
+ FSPathMakeRef((UInt8 *)entry.nativeFilePath().constData(), &packageRef, NULL);
+
+ FSCatalogInfo catalogInfo;
+ FSGetCatalogInfo(&packageRef,
+ kFSCatInfoFinderInfo,
+ &catalogInfo,
+ NULL,
+ NULL,
+ NULL);
+
+ FolderInfo *folderInfo = reinterpret_cast<FolderInfo *>(catalogInfo.finderInfo);
+ return folderInfo->finderFlags & kHasBundle;
+}
+
#else
static inline bool _q_isMacHidden(const char *nativePath)
{
@@ -468,18 +530,8 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC)
if (what & QFileSystemMetaData::BundleType) {
- if (entryExists && data.isDirectory()) {
- QCFType<CFStringRef> path = CFStringCreateWithBytes(0,
- (const UInt8*)nativeFilePath, nativeFilePathLength,
- kCFStringEncodingUTF8, false);
- QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, path,
- kCFURLPOSIXPathStyle, true);
-
- UInt32 type, creator;
- if (CFBundleGetPackageInfoInDirectory(url, &type, &creator))
- data.entryFlags |= QFileSystemMetaData::BundleType;
- }
-
+ if (entryExists && isPackage(data, entry))
+ data.entryFlags |= QFileSystemMetaData::BundleType;
data.knownFlagsMask |= QFileSystemMetaData::BundleType;
}
#endif
diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro
index f0278f1..1885c8b 100644
--- a/src/tools/bootstrap/bootstrap.pro
+++ b/src/tools/bootstrap/bootstrap.pro
@@ -105,7 +105,7 @@ else:win32:SOURCES += ../../corelib/tools/qlocale_win.cpp
macx: {
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4 #enables weak linking for 10.4 (exported)
SOURCES += ../../corelib/kernel/qcore_mac.cpp
- LIBS += -framework CoreServices
+ LIBS += -framework CoreServices -framework ApplicationServices
}
if(contains(QT_CONFIG, zlib)|cross_compile):include(../../3rdparty/zlib.pri)