From bcfc68f9cd00982decd7ceb312966caf6b1ca05e Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Wed, 29 Jan 2014 08:38:40 +0100 Subject: [PATCH] Use Uniform Type Identifiers to detect OS X bundles Following Apple's documentation, the first step to identify a bundle is to check if it has a known extension. Currently, it's done using string comparisons ored in an if statement. The list is not complete and new types, whether provided by a system update or other means, can't be detected. 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. Task-number: QTBUG-31884 Change-Id: Ief73a83904adf27ccb71b0070e67cba081d1fd4a Reviewed-by: Jake Petroules Reviewed-by: Thiago Macieira --- src/corelib/io/qfilesystemengine_unix.cpp | 48 +++++++++-------------- 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index ea3a3ca13da..6c0f31fb55a 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2013 Samuel Gaist > ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Samuel Gaist ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -89,35 +89,23 @@ static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &e QFileInfo info(entry.filePath()); QString suffix = info.suffix(); - // First step: is the extenstion known ? - if (suffix == QLatin1String("app") - || suffix == QLatin1String("debug") - || suffix == QLatin1String("profile") - || suffix == QLatin1String("bundle") - || suffix == QLatin1String("pkg")) { - return true; - } - - // Second step: check if an application knows the package type - const QByteArray &native = entry.nativeFilePath(); - const char *nativeFilePath = native.constData(); - int nativeFilePathLength = native.size(); - - QCFType path = CFStringCreateWithBytes(0, - reinterpret_cast(nativeFilePath), - nativeFilePathLength, - kCFStringEncodingUTF8, - false); - - QCFType 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 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 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 application; LSGetApplicationForURL(url, kLSRolesEditor|kLSRolesViewer|kLSRolesViewer, @@ -134,7 +122,7 @@ static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &e // Third step: check if the directory has the package bit set FSRef packageRef; - FSPathMakeRef((UInt8 *)nativeFilePath, &packageRef, NULL); + FSPathMakeRef((UInt8 *)entry.nativeFilePath().constData(), &packageRef, NULL); FSCatalogInfo catalogInfo; FSGetCatalogInfo(&packageRef,