Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qstandardpaths_mac.mm
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:critical reason:provides-trusted-directory-paths
4
6
7#ifndef QT_NO_STANDARDPATHS
8
9#include <qdir.h>
10#include <qurl.h>
11#include <private/qcore_mac_p.h>
12
13#ifndef QT_BOOTSTRAPPED
14#include <qcoreapplication.h>
15#endif
16
17#import <Foundation/Foundation.h>
18
20
21using namespace Qt::StringLiterals;
22
23static QString pathForDirectory(NSSearchPathDirectory directory,
24 NSSearchPathDomainMask mask)
25{
26 return QString::fromNSString(
27 [NSSearchPathForDirectoriesInDomains(directory, mask, YES) lastObject]);
28}
29
30static NSSearchPathDirectory searchPathDirectory(QStandardPaths::StandardLocation type)
31{
32 switch (type) {
33 case QStandardPaths::DesktopLocation:
34 return NSDesktopDirectory;
35 case QStandardPaths::DocumentsLocation:
36 return NSDocumentDirectory;
37 case QStandardPaths::ApplicationsLocation:
38 return NSApplicationDirectory;
39 case QStandardPaths::MusicLocation:
40 return NSMusicDirectory;
41 case QStandardPaths::MoviesLocation:
42 return NSMoviesDirectory;
43 case QStandardPaths::PicturesLocation:
44 return NSPicturesDirectory;
45 case QStandardPaths::GenericDataLocation:
46 case QStandardPaths::RuntimeLocation:
47 case QStandardPaths::AppDataLocation:
48 case QStandardPaths::AppLocalDataLocation:
49 return NSApplicationSupportDirectory;
50 case QStandardPaths::GenericCacheLocation:
51 case QStandardPaths::CacheLocation:
52 return NSCachesDirectory;
53 case QStandardPaths::DownloadLocation:
54 return NSDownloadsDirectory;
55 case QStandardPaths::PublicShareLocation:
56 return NSSharedPublicDirectory;
57 case QStandardPaths::TemplatesLocation:
58 default:
59 return (NSSearchPathDirectory)0;
60 }
61}
62
63static void appendOrganizationAndApp(QString &path)
64{
65#ifndef QT_BOOTSTRAPPED
66 const QString org = QCoreApplication::organizationName();
67 if (!org.isEmpty())
68 path += u'/' + org;
69 const QString appName = QCoreApplication::applicationName();
70 if (!appName.isEmpty())
71 path += u'/' + appName;
72#else
73 Q_UNUSED(path);
74#endif
75}
76
77static QString baseWritableLocation(QStandardPaths::StandardLocation type,
78 NSSearchPathDomainMask mask = NSUserDomainMask,
79 bool appendOrgAndApp = false)
80{
81 QString path;
82 const NSSearchPathDirectory dir = searchPathDirectory(type);
83 switch (type) {
84 case QStandardPaths::HomeLocation:
85 path = QDir::homePath();
86 break;
87 case QStandardPaths::TempLocation:
88 path = QDir::tempPath();
89 break;
90#if defined(QT_PLATFORM_UIKIT)
91 // These locations point to non-existing write-protected paths. Use sensible fallbacks.
92 case QStandardPaths::MusicLocation:
93 path = pathForDirectory(NSDocumentDirectory, mask) + "/Music"_L1;
94 break;
95 case QStandardPaths::MoviesLocation:
96 path = pathForDirectory(NSDocumentDirectory, mask) + "/Movies"_L1;
97 break;
98 case QStandardPaths::PicturesLocation:
99 path = pathForDirectory(NSDocumentDirectory, mask) + "/Pictures"_L1;
100 break;
101 case QStandardPaths::DownloadLocation:
102 path = pathForDirectory(NSDocumentDirectory, mask) + "/Downloads"_L1;
103 break;
104 case QStandardPaths::DesktopLocation:
105 path = pathForDirectory(NSDocumentDirectory, mask) + "/Desktop"_L1;
106 break;
107 case QStandardPaths::ApplicationsLocation:
108 break;
109 case QStandardPaths::PublicShareLocation:
110 path = pathForDirectory(NSDocumentDirectory, mask) + "/Public"_L1;
111 break;
112 case QStandardPaths::TemplatesLocation:
113 path = pathForDirectory(NSDocumentDirectory, mask) + "/Templates"_L1;
114 break;
115#endif
116 case QStandardPaths::FontsLocation:
117 path = pathForDirectory(NSLibraryDirectory, mask) + "/Fonts"_L1;
118 break;
119 case QStandardPaths::ConfigLocation:
120 case QStandardPaths::GenericConfigLocation:
121 case QStandardPaths::AppConfigLocation:
122 path = pathForDirectory(NSLibraryDirectory, mask) + "/Preferences"_L1;
123 break;
124 case QStandardPaths::StateLocation:
125 if (appendOrgAndApp) { break; }
126 Q_FALLTHROUGH();
127 case QStandardPaths::GenericStateLocation:
128 path = pathForDirectory(NSLibraryDirectory, mask) + "/Preferences/State"_L1;
129 break;
130 default:
131 path = pathForDirectory(dir, mask);
132 break;
133 }
134
135 if (appendOrgAndApp) {
136 switch (type) {
137 case QStandardPaths::AppDataLocation:
138 case QStandardPaths::AppLocalDataLocation:
139 case QStandardPaths::AppConfigLocation:
140 case QStandardPaths::CacheLocation:
141 appendOrganizationAndApp(path);
142 break;
143 case QStandardPaths::StateLocation:
144 path = pathForDirectory(NSLibraryDirectory, mask) + "/Preferences"_L1;
145 appendOrganizationAndApp(path);
146 path += "/State"_L1;
147 break;
148 default:
149 break;
150 }
151 }
152
153 return path;
154}
155
156QString QStandardPaths::writableLocation(StandardLocation type)
157{
158 QString location = baseWritableLocation(type, NSUserDomainMask, true);
159 if (isTestModeEnabled())
160 location = location.replace(QDir::homePath(), QDir::homePath() + "/.qttest"_L1);
161
162 return location;
163}
164
165QStringList QStandardPaths::standardLocations(StandardLocation type)
166{
167 QStringList dirs;
168
169#if defined(QT_PLATFORM_UIKIT)
170 if (type == PicturesLocation)
171 dirs << writableLocation(PicturesLocation) << "assets-library://"_L1;
172#endif
173
174 if (type == GenericDataLocation || type == FontsLocation || type == ApplicationsLocation
175 || type == AppDataLocation || type == AppLocalDataLocation
176 || type == GenericCacheLocation || type == CacheLocation) {
177 QList<NSSearchPathDomainMask> masks;
178 masks << NSLocalDomainMask;
179 if (type == FontsLocation || type == GenericCacheLocation)
180 masks << NSSystemDomainMask;
181
182 for (QList<NSSearchPathDomainMask>::const_iterator it = masks.begin();
183 it != masks.end(); ++it) {
184 const QString path = baseWritableLocation(type, *it, true);
185 if (!path.isEmpty() && !dirs.contains(path))
186 dirs.append(path);
187 }
188 }
189
190 if (type == AppDataLocation || type == AppLocalDataLocation) {
191 CFBundleRef mainBundle = CFBundleGetMainBundle();
192 if (mainBundle) {
193 if (QCFType<CFURLRef> resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle)) {
194 if (QCFType<CFURLRef> absoluteResouresURL = CFURLCopyAbsoluteURL(resourcesURL)) {
195 if (QCFType<CFStringRef> path = CFURLCopyFileSystemPath(absoluteResouresURL,
196 kCFURLPOSIXPathStyle)) {
197 dirs.append(QString::fromCFString(path));
198 }
199 }
200 }
201 }
202 }
203
204 const QString localDir = writableLocation(type);
205 if (!localDir.isEmpty())
206 dirs.prepend(localDir);
207 return dirs;
208}
209
210#ifndef QT_BOOTSTRAPPED
211QString QStandardPaths::displayName(StandardLocation type)
212{
213 // Use "Home" instead of the user's Unix username
214 if (QStandardPaths::HomeLocation == type)
215 return QCoreApplication::translate("QStandardPaths", "Home");
216
217 // The temporary directory returned by the old Carbon APIs is ~/Library/Caches/TemporaryItems,
218 // the display name of which ("TemporaryItems") isn't translated by the system. The standard
219 // temporary directory has no reasonable display name either, so use something more sensible.
220 if (QStandardPaths::TempLocation == type) {
221 //: macOS: Temporary directory
222 return QCoreApplication::translate("QStandardPaths", "Temporary Items");
223 }
224
225 // standardLocations() may return an empty list on some platforms
226 if (QStandardPaths::ApplicationsLocation == type)
227 return QCoreApplication::translate("QStandardPaths", "Applications");
228
229 const QCFString fsPath(standardLocations(type).constFirst());
230 if (QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
231 fsPath, kCFURLPOSIXPathStyle, true)) {
232 QCFString name;
233 CFURLCopyResourcePropertyForKey(url, kCFURLLocalizedNameKey, &name, NULL);
234 if (name && CFStringGetLength(name))
235 return QString::fromCFString(name);
236 }
237
238 return QFileInfo(baseWritableLocation(type)).fileName();
239}
240#endif
241
242QT_END_NAMESPACE
243
244#endif // QT_NO_STANDARDPATHS
static QString baseWritableLocation(QStandardPaths::StandardLocation type, NSSearchPathDomainMask mask=NSUserDomainMask, bool appendOrgAndApp=false)
static NSSearchPathDirectory searchPathDirectory(QStandardPaths::StandardLocation type)
static void appendOrganizationAndApp(QString &path)
static QString pathForDirectory(NSSearchPathDirectory directory, NSSearchPathDomainMask mask)