From b473c5f9cb3ee9364a93ea508132ea0d0999271a Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <vital.had@gmail.com>
Date: Sun, 18 Aug 2024 13:34:56 +0800
Subject: [PATCH 3/6] qlibrary.cpp: fix for macOS

---
 src/core/CMakeLists.txt         |   1 +
 src/core/kernel/qcore_mac_p.cpp | 138 ++++++++++++++++++++++++++
 src/core/kernel/qcore_mac_p.h   | 169 ++++++++++++++++++++++++++++++++
 src/core/plugin/qlibrary.cpp    |  22 ++++-
 4 files changed, 327 insertions(+), 3 deletions(-)
 create mode 100644 src/core/kernel/qcore_mac_p.cpp
 create mode 100644 src/core/kernel/qcore_mac_p.h

diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index b5ff2a995..f6298e97e 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -152,6 +152,7 @@ set(CORE_HEADERS
     ${CMAKE_CURRENT_SOURCE_DIR}/kernel/qobject_p.h
     ${CMAKE_CURRENT_SOURCE_DIR}/kernel/qmath.h
     ${CMAKE_CURRENT_SOURCE_DIR}/kernel/qcore_unix_p.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/kernel/qcore_mac_p.h
     ${CMAKE_CURRENT_SOURCE_DIR}/kernel/qeventdispatcher_unix_p.h
     ${CMAKE_CURRENT_SOURCE_DIR}/plugin/qpluginloader.h
     ${CMAKE_CURRENT_SOURCE_DIR}/plugin/qlibrary.h
diff --git a/src/core/kernel/qcore_mac_p.cpp b/src/core/kernel/qcore_mac_p.cpp
new file mode 100644
index 000000000..696e1f5aa
--- /dev/null
+++ b/src/core/kernel/qcore_mac_p.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qcore_mac_p.h>
+#include <new>
+
+QT_BEGIN_NAMESPACE
+
+QString QCFString::toQString(CFStringRef str)
+{
+    if (!str)
+        return QString();
+
+    CFIndex length = CFStringGetLength(str);
+    if (length == 0)
+        return QString();
+
+    QString string(length, Qt::Uninitialized);
+    CFStringGetCharacters(str, CFRangeMake(0, length), reinterpret_cast<UniChar *>(const_cast<QChar *>(string.unicode())));
+
+    return string;
+}
+
+QCFString::operator QString() const
+{
+    if (string.isEmpty() && type)
+        const_cast<QCFString*>(this)->string = toQString(type);
+    return string;
+}
+
+CFStringRef QCFString::toCFStringRef(const QString &string)
+{
+    return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar *>(string.unicode()),
+                                        string.length());
+}
+
+QCFString::operator CFStringRef() const
+{
+    if (!type) {
+        if (string.d->data != string.d->array)
+            const_cast<QCFString*>(this)->string.realloc(); // ### Qt5: do we really need this stupid user protection?
+        const_cast<QCFString*>(this)->type =
+            CFStringCreateWithCharactersNoCopy(0,
+                                               reinterpret_cast<const UniChar *>(string.unicode()),
+                                               string.length(),
+                                               kCFAllocatorNull);
+    }
+    return type;
+}
+
+void qt_mac_to_pascal_string(const QString &s, Str255 str, TextEncoding encoding, int len)
+{
+    if(len == -1)
+        len = s.length();
+#if 0
+    UnicodeMapping mapping;
+    mapping.unicodeEncoding = CreateTextEncoding(kTextEncodingUnicodeDefault,
+                                                 kTextEncodingDefaultVariant,
+                                                 kUnicode16BitFormat);
+    mapping.otherEncoding = (encoding ? encoding : );
+    mapping.mappingVersion = kUnicodeUseLatestMapping;
+
+    UnicodeToTextInfo info;
+    OSStatus err = CreateUnicodeToTextInfo(&mapping, &info);
+    if(err != noErr) {
+        qDebug("Qt: internal: Unable to create pascal string '%s'::%d [%ld]",
+               s.left(len).latin1(), (int)encoding, err);
+        return;
+    }
+    const int unilen = len * 2;
+    const UniChar *unibuf = (UniChar *)s.unicode();
+    ConvertFromUnicodeToPString(info, unilen, unibuf, str);
+    DisposeUnicodeToTextInfo(&info);
+#else
+    Q_UNUSED(encoding);
+    CFStringGetPascalString(QCFString(s), str, 256, CFStringGetSystemEncoding());
+#endif
+}
+
+QString qt_mac_from_pascal_string(const Str255 pstr)
+{
+    return QCFString(CFStringCreateWithPascalString(0, pstr, CFStringGetSystemEncoding()));
+}
+
+OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref)
+{
+    return FSPathMakeRef(reinterpret_cast<const UInt8 *>(file.toUtf8().constData()), fsref, 0);
+}
+
+// Don't use this function, it won't work in 10.5 (Leopard) and up
+OSErr qt_mac_create_fsspec(const QString &file, FSSpec *spec)
+{
+    FSRef fsref;
+    OSErr ret = qt_mac_create_fsref(file, &fsref);
+    if (ret == noErr)
+        ret = FSGetCatalogInfo(&fsref, kFSCatInfoNone, 0, 0, spec, 0);
+    return ret;
+}
+
+QT_END_NAMESPACE
diff --git a/src/core/kernel/qcore_mac_p.h b/src/core/kernel/qcore_mac_p.h
new file mode 100644
index 000000000..caa347a9e
--- /dev/null
+++ b/src/core/kernel/qcore_mac_p.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCORE_MAC_P_H
+#define QCORE_MAC_P_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists for the convenience
+// of other Qt classes.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef __IMAGECAPTURE__
+#  define __IMAGECAPTURE__
+#endif
+
+#undef OLD_DEBUG
+#ifdef DEBUG
+# define OLD_DEBUG DEBUG
+# undef DEBUG
+#endif
+#define DEBUG 0
+#ifdef qDebug
+#  define old_qDebug qDebug
+#  undef qDebug
+#endif
+
+#if defined(QT_BUILD_QMAKE) || defined(QT_BOOTSTRAPPED)
+#include <ApplicationServices/ApplicationServices.h>
+#else
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+#include <CoreServices/CoreServices.h>
+
+#undef DEBUG
+#ifdef OLD_DEBUG
+#  define DEBUG OLD_DEBUG
+#  undef OLD_DEBUG
+#endif
+
+#ifdef old_qDebug
+#  undef qDebug
+#  define qDebug QT_NO_QDEBUG_MACRO
+#  undef old_qDebug
+#endif
+
+#include "qstring.h"
+
+QT_BEGIN_NAMESPACE
+
+/*
+    Helper class that automates refernce counting for CFtypes.
+    After constructing the QCFType object, it can be copied like a
+    value-based type.
+
+    Note that you must own the object you are wrapping.
+    This is typically the case if you get the object from a Core
+    Foundation function with the word "Create" or "Copy" in it. If
+    you got the object from a "Get" function, either retain it or use
+    constructFromGet(). One exception to this rule is the
+    HIThemeGet*Shape functions, which in reality are "Copy" functions.
+*/
+template <typename T>
+class Q_CORE_EXPORT QCFType
+{
+public:
+    inline QCFType(const T &t = 0) : type(t) {}
+    inline QCFType(const QCFType &helper) : type(helper.type) { if (type) CFRetain(type); }
+    inline ~QCFType() { if (type) CFRelease(type); }
+    inline operator T() { return type; }
+    inline QCFType operator =(const QCFType &helper)
+    {
+    if (helper.type)
+        CFRetain(helper.type);
+    CFTypeRef type2 = type;
+    type = helper.type;
+    if (type2)
+        CFRelease(type2);
+    return *this;
+    }
+    inline T *operator&() { return &type; }
+    template <typename X> X as() const { return reinterpret_cast<X>(type); }
+    static QCFType constructFromGet(const T &t)
+    {
+        CFRetain(t);
+        return QCFType<T>(t);
+    }
+protected:
+    T type;
+};
+
+class Q_CORE_EXPORT QCFString : public QCFType<CFStringRef>
+{
+public:
+    inline QCFString(const QString &str) : QCFType<CFStringRef>(0), string(str) {}
+    inline QCFString(const CFStringRef cfstr = 0) : QCFType<CFStringRef>(cfstr) {}
+    inline QCFString(const QCFType<CFStringRef> &other) : QCFType<CFStringRef>(other) {}
+    operator QString() const;
+    operator CFStringRef() const;
+    static QString toQString(CFStringRef cfstr);
+    static CFStringRef toCFStringRef(const QString &str);
+private:
+    QString string;
+};
+
+Q_CORE_EXPORT void qt_mac_to_pascal_string(const QString &s, Str255 str, TextEncoding encoding = 0, int len = -1);
+Q_CORE_EXPORT QString qt_mac_from_pascal_string(const Str255 pstr);
+
+Q_CORE_EXPORT OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref);
+// Don't use this function, it won't work in 10.5 (Leopard) and up
+Q_CORE_EXPORT OSErr qt_mac_create_fsspec(const QString &file, FSSpec *spec);
+
+QT_END_NAMESPACE
+
+#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)
+#ifndef __LP64__
+    typedef float CGFloat;
+        typedef int NSInteger;
+        typedef unsigned int NSUInteger;
+    #define SRefCon SInt32
+    #define URefCon UInt32
+#endif
+#endif
+
+#endif // QCORE_MAC_P_H
diff --git a/src/core/plugin/qlibrary.cpp b/src/core/plugin/qlibrary.cpp
index ea0ac6cac..6be3c2ead 100644
--- a/src/core/plugin/qlibrary.cpp
+++ b/src/core/plugin/qlibrary.cpp
@@ -34,9 +34,13 @@
 #include "qcorecommon_p.h"
 #include "qcore_unix_p.h"
 
+#ifdef Q_OS_MAC
+#  include <qcore_mac_p.h>
+#endif
+
 #include <errno.h>
 
-#ifndef QT_NO_PLUGIN_CHECK
+#if !defined(QT_NO_PLUGIN_CHECK) && !defined(Q_OS_MAC)
 #  include <elf.h>
 #  if QT_POINTER_SIZE == 8
 #    define QT_ELF_CLASS_TYPE ELFCLASS64
@@ -124,7 +128,7 @@ QT_BEGIN_NAMESPACE
     \sa loadHints
 */
 
-#ifndef QT_NO_PLUGIN_CHECK
+#if !defined(QT_NO_PLUGIN_CHECK) && !defined(Q_OS_MAC)
 /*
   This opens the specified library and checks for the ELF magic and class.
   The advantage of this approach is that we can do verification without
@@ -314,11 +318,23 @@ bool QLibrary::isLibrary(const QString &fileName)
     //  libfoo-0.3.so
     //  libfoo-0.3.so.0.3.0
 
+#ifdef Q_OS_MAC
+    QStringList suffixes = completeSuffix.split(QLatin1Char('.'));
+    const QString lastSuffix = suffixes.at(suffixes.count() - 1);
+    const QString firstSuffix = suffixes.at(0);
+
+    bool valid = (lastSuffix == QLatin1String("dylib")
+            || firstSuffix == QLatin1String("so")
+            || firstSuffix == QLatin1String("bundle"));
+
+    return valid;
+#else
     foreach (const QString &suffix, completeSuffix.split(QLatin1Char('.'))) {
         if (suffix == QLatin1String("so")) {
             return true;
         };
     }
+#endif
     return false;
 }
 
@@ -329,7 +345,7 @@ bool QLibraryPrivate::isPlugin()
         return (pluginState == QLibraryPrivate::IsAPlugin);
     }
 
-#ifndef QT_NO_PLUGIN_CHECK
+#if !defined(QT_NO_PLUGIN_CHECK) && !defined(Q_OS_MAC)
     if (Q_UNLIKELY(fileName.endsWith(QLatin1String(".debug")))) {
         // refuse to load a file that ends in .debug
         // these are the debug symbols from the libraries
-- 
2.49.0

