8#include <qcryptographichash.h>
9#include <qstandardpaths.h>
10#include <qstringconverter.h>
14#if defined(Q_OS_DARWIN)
15# include "private/qcore_mac_p.h"
16# if !defined(SHM_NAME_MAX)
21# define SHM_NAME_MAX 30
23#elif defined(Q_OS_WINDOWS)
24# include "qt_windows.h"
27#if QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
31using namespace Qt::StringLiterals;
33static QStringView staticTypeToString(QNativeIpcKey::Type type)
36 case QNativeIpcKey::Type::SystemV:
38 case QNativeIpcKey::Type::PosixRealtime:
40 case QNativeIpcKey::Type::Windows:
46static QString typeToString(QNativeIpcKey::Type type)
48 QStringView typeString = staticTypeToString(type);
50 case QNativeIpcKey::Type::SystemV:
51 case QNativeIpcKey::Type::PosixRealtime:
52 case QNativeIpcKey::Type::Windows:
53 return QString::fromRawData(typeString.constData(), typeString.size());
56 int value =
int(type);
57 if (value >= 1 && value <= 0xff) {
59 typeString = staticTypeToString(QNativeIpcKey::Type::SystemV);
60 return typeString + QString::number(-value);
66static QNativeIpcKey::Type stringToType(QStringView typeString)
68 if (typeString == staticTypeToString(QNativeIpcKey::Type::PosixRealtime))
69 return QNativeIpcKey::Type::PosixRealtime;
70 if (typeString == staticTypeToString(QNativeIpcKey::Type::Windows))
71 return QNativeIpcKey::Type::Windows;
73 auto fromNumber = [](QStringView number,
int low,
int high) {
75 int n = -number.toInt(&ok, 10);
76 if (!ok || n < low || n > high)
77 return QNativeIpcKey::Type{};
78 return QNativeIpcKey::Type(n);
81 QStringView sysv = staticTypeToString(QNativeIpcKey::Type::SystemV);
82 if (typeString.startsWith(sysv)) {
83 if (typeString.size() == sysv.size())
84 return QNativeIpcKey::Type::SystemV;
85 return fromNumber(typeString.sliced(sysv.size()), 1, 0xff);
89 return QNativeIpcKey::Type{};
93
94
95
96
97
98
99
100
101
102
103
104QNativeIpcKey QtIpcCommon::legacyPlatformSafeKey(
const QString &key, QtIpcCommon::IpcType ipcType,
105 QNativeIpcKey::Type type)
107 QNativeIpcKey k(type);
111 QByteArray hex = QCryptographicHash::hash(key.toUtf8(), QCryptographicHash::Sha1).toHex();
113 if (type == QNativeIpcKey::Type::PosixRealtime) {
114#if defined(Q_OS_DARWIN)
115 if (qt_apple_isSandboxed()) {
120 QNativeIpcKeyPrivate::setNativeAndLegacyKeys(k, key, key);
126 QString native = u'/' + QLatin1StringView(hex).left(SHM_NAME_MAX - 1);
127 QNativeIpcKeyPrivate::setNativeAndLegacyKeys(k, native, key);
134 result.reserve(1 + 18 + key.size() + 40);
136 case IpcType::SharedMemory:
137 result +=
"qipc_sharedmemory_"_L1;
139 case IpcType::SystemSemaphore:
140 result +=
"qipc_systemsem_"_L1;
144 for (QChar ch : key) {
145 if ((ch >= u'a' && ch <= u'z') ||
146 (ch >= u'A' && ch <= u'Z'))
149 result.append(QLatin1StringView(hex));
152 case QNativeIpcKey::Type::Windows:
153 if (isIpcSupported(ipcType, QNativeIpcKey::Type::Windows))
154 QNativeIpcKeyPrivate::setNativeAndLegacyKeys(k, result, key);
156 case QNativeIpcKey::Type::PosixRealtime:
157 result.prepend(u'/');
158 if (isIpcSupported(ipcType, QNativeIpcKey::Type::PosixRealtime))
159 QNativeIpcKeyPrivate::setNativeAndLegacyKeys(k, result, key);
161 case QNativeIpcKey::Type::SystemV:
164 if (isIpcSupported(ipcType, QNativeIpcKey::Type::SystemV)) {
165 result = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + u'/' + result;
166 QNativeIpcKeyPrivate::setNativeAndLegacyKeys(k, result, key);
172
173
174
175
176
177
178QNativeIpcKey QtIpcCommon::platformSafeKey(
const QString &key, QtIpcCommon::IpcType ipcType,
179 QNativeIpcKey::Type type)
181 QNativeIpcKey k(type);
186 case QNativeIpcKey::Type::PosixRealtime:
187 if (isIpcSupported(ipcType, QNativeIpcKey::Type::PosixRealtime)) {
192 k.setNativeKey(u'/' + QStringView(key).left(SHM_NAME_MAX - 1));
194#if defined(Q_OS_OHOS)
199 case IpcType::SharedMemory:
200 suffix = u"_shm";
break;
201 case IpcType::SystemSemaphore:
202 suffix = u"_sem";
break;
204 k.setNativeKey(u'/' + key + suffix);
206 k.setNativeKey(u'/' + key);
212 case QNativeIpcKey::Type::Windows:
213 if (isIpcSupported(ipcType, QNativeIpcKey::Type::Windows)) {
215 QStringView payload = key;
217 for (QStringView candidate : { u"Local\\"_sv, u"Global\\"_sv }) {
218 if (!key.startsWith(candidate))
221 payload = payload.sliced(prefix.size());
227 case IpcType::SharedMemory: mid = u"shm_";
break;
228 case IpcType::SystemSemaphore: mid = u"sem_";
break;
231 QString result = prefix + mid + payload;
233 result.truncate(MAX_PATH);
235 k.setNativeKey(result);
239 case QNativeIpcKey::Type::SystemV:
244 if (isIpcSupported(ipcType, QNativeIpcKey::Type::SystemV)) {
245 if (key.startsWith(u'/')) {
248 QString baseDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
249 k.setNativeKey(baseDir + u'/' + key);
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
341
342
343
344
345
346
347
348
349
350
351
354
355
356
357
358
359
360
361
362
365
366
367
368
369
370
371
372
373
374
375
376#if defined(Q_OS_DARWIN)
377QNativeIpcKey::Type QNativeIpcKey::defaultTypeForOs_internal()
noexcept
379 if (qt_apple_isSandboxed())
380 return Type::PosixRealtime;
381 return Type::SystemV;
386
387
388
389
392
393
394
395
396
397
400
401
402
403
404
405
406
407void QNativeIpcKey::copy_internal(
const QNativeIpcKey &other)
409 d =
new QNativeIpcKeyPrivate(*other.d);
412void QNativeIpcKey::move_internal(QNativeIpcKey &&)
noexcept
417QNativeIpcKey &QNativeIpcKey::assign_internal(
const QNativeIpcKey &other)
419 Q_ASSERT(d || other.d);
425 d =
new QNativeIpcKeyPrivate(*other.d);
430
431
432
433
434void QNativeIpcKey::destroy_internal()
noexcept
440
441
442
445
446
447
448
449
450
453
454
455
456
457
458
461
462
463
464
465
466
467
468
469
470
471
474
475
476
477
478
479
482
483
484
485
486
487
488void QNativeIpcKey::setType_internal(Type type)
494
495
496
497
498
499
502
503
504
505
506
507
508void QNativeIpcKey::setNativeKey_internal(
const QString &)
510 d->legacyKey_.clear();
514
515
516
517size_t qHash(
const QNativeIpcKey &ipcKey, size_t seed)
noexcept
521 return qHashMulti(seed, ipcKey.key, ipcKey.type());
525
526
527
528
529
530int QNativeIpcKey::compare_internal(
const QNativeIpcKey &lhs,
const QNativeIpcKey &rhs)
noexcept
532 return (QNativeIpcKeyPrivate::legacyKey(lhs) == QNativeIpcKeyPrivate::legacyKey(rhs)) ? 0 : 1;
536
537
538
539
540
541
542
543
544
545QString QNativeIpcKey::toString()
const
547 QString prefix = typeToString(type());
548 if (prefix.isEmpty()) {
549 Q_ASSERT(prefix.isNull());
553 QString copy = nativeKey();
554 copy.replace(u'%',
"%25"_L1);
555 if (copy.startsWith(
"//"_L1))
556 copy.replace(0, 2, u"/%2F"_s);
560 u.setPath(copy, QUrl::TolerantMode);
563 if (!d->legacyKey_.isEmpty())
564 q.addQueryItem(u"legacyKey"_s, QString(d->legacyKey_).replace(u'%',
"%25"_L1));
567 return u.toString(QUrl::DecodeReserved);
571
572
573
574
575
576
577
578
579
580QNativeIpcKey QNativeIpcKey::fromString(
const QString &text)
582 QUrl u(text, QUrl::TolerantMode);
583 Type invalidType = {};
584 Type type = stringToType(u.scheme());
585 if (type == invalidType || !u.isValid() || !u.userInfo().isEmpty() || !u.host().isEmpty()
587 return QNativeIpcKey(invalidType);
589 QNativeIpcKey result(QString(), type);
590 if (result.type() != type)
591 return QNativeIpcKey(invalidType);
594 result.setNativeKey(u.path());
597 const QList items = QUrlQuery(u).queryItems();
598 for (
const auto &item : items) {
599 if (item.first == u"legacyKey"_s) {
600 QString legacyKey = QUrl::fromPercentEncoding(item.second.toUtf8());
601 QNativeIpcKeyPrivate::setLegacyKey(result, std::move(legacyKey));
604 return QNativeIpcKey(invalidType);
613#include "moc_qtipccommon.cpp"