Example #1
0
static QString locatePlugin(const QString& fileName)
{
    QStringList prefixes = QLibraryPrivate::prefixes_sys();
    prefixes.prepend(QString());
    QStringList suffixes = QLibraryPrivate::suffixes_sys(QString());
    suffixes.prepend(QString());

    // Split up "subdir/filename"
    const int slash = fileName.lastIndexOf('/');
    const QString baseName = fileName.mid(slash + 1);
    const QString basePath = fileName.left(slash + 1); // keep the '/'

    const bool debug = qt_debug_component();

    QStringList paths = QCoreApplication::libraryPaths();
    paths.prepend(QStringLiteral("./")); // search in current dir first
    foreach (const QString &path, paths) {
        foreach (const QString &prefix, prefixes) {
            foreach (const QString &suffix, suffixes) {
                const QString fn = path + QLatin1Char('/') + basePath + prefix + baseName + suffix;
                if (debug)
                    qDebug() << "Trying..." << fn;
                if (QFileInfo(fn).isFile())
                    return fn;
            }
        }
Example #2
0
static void installCoverageTool(QLibraryPrivate *libPrivate)
{
#ifdef __COVERAGESCANNER__
    /*
      __COVERAGESCANNER__ is defined when Qt has been instrumented for code
      coverage by TestCocoon. CoverageScanner is the name of the tool that
      generates the code instrumentation.
      This code is required here when code coverage analysis with TestCocoon
      is enabled in order to allow the loading application to register the plugin
      and then store its execution report. The execution report gathers information
      about each part of the plugin's code that has been used when
      the plugin was loaded by the launching application.
      The execution report for the plugin will go to the same execution report
      as the one defined for the application loading it.
    */

    int ret = __coveragescanner_register_library(libPrivate->fileName.toLocal8Bit());

    if (qt_debug_component()) {
        if (ret >= 0) {
            qDebug("%s: coverage data for %s registered",
                     Q_FUNC_INFO,
                     qPrintable(libPrivate->fileName));
        } else {
            qWarning("%s: could not register %s: error %d; coverage data may be incomplete",
                     Q_FUNC_INFO,
                     qPrintable(libPrivate->fileName),
                     ret);
        }
    }
#else
    Q_UNUSED(libPrivate);
#endif
}
Example #3
0
/*!
    \property QPluginLoader::fileName
    \brief the file name of the plugin

    To be loadable, the file's suffix must be a valid suffix for a
    loadable library in accordance with the platform, e.g. \c .so on
    Unix, \c .dylib on Mac OS X, and \c .dll on Windows. The suffix
    can be verified with QLibrary::isLibrary().

    If the file name does not exist, it will not be set. This property
    will then contain an empty string.

    By default, this property contains an empty string.

    \sa load()
*/
void QPluginLoader::setFileName(const QString &fileName)
{
#if defined(QT_SHARED)
    QLibrary::LoadHints lh;
    if (d) {
        lh = d->loadHints;
        d->release();
        d = 0;
        did_load = false;
    }

    QString fn = QFileInfo(fileName).canonicalFilePath();

    d = QLibraryPrivate::findOrCreate(fn);
    d->loadHints = lh;
    if (fn.isEmpty())
        d->errorString = QLibrary::tr("The shared library was not found.");
#else
    if (qt_debug_component()) {
        qWarning("Cannot load %s into a statically linked Qt library.",
            (const char*)QFile::encodeName(fileName));
    }
    Q_UNUSED(fileName);
#endif
}
Example #4
0
/*
  This opens the specified library, mmaps it into memory, and searches
  for the QT_PLUGIN_VERIFICATION_DATA.  The advantage of this approach is that
  we can get the verification data without have to actually load the library.
  This lets us detect mismatches more safely.

  Returns false if version information is not present, or if the
                information could not be read.
  Returns  true if version information is present and successfully read.
*/
static bool qt_unix_query(const QString &library, uint *version, bool *debug, QLibraryPrivate *lib = 0)
{
    QFile file(library);
    if (!file.open(QIODevice::ReadOnly)) {
        if (lib)
            lib->errorString = file.errorString();
        if (qt_debug_component()) {
            qWarning("%s: %s", QFile::encodeName(library).data(),
                qPrintable(qt_error_string(errno)));
        }
        return false;
    }

    QByteArray data;
    const char *filedata = 0;
    ulong fdlen = file.size();
    filedata = (char *) file.map(0, fdlen);
    if (filedata == 0) {
        // try reading the data into memory instead
        data = file.readAll();
        filedata = data.constData();
        fdlen = data.size();
    }

    /*
       ELF binaries on GNU, have .qplugin sections.
    */
    const char pattern[] = "pattern=QT_PLUGIN_VERIFICATION_DATA";
    const ulong plen = qstrlen(pattern);
    const long pos = qt_find_pattern(filedata, fdlen, pattern, plen);
    bool ret = false;
    if (pos >= 0)
        ret = qt_parse_pattern(filedata + pos, version, debug);

    if (!ret && lib)
        lib->errorString = QLibrary::tr("Plugin verification data mismatch in '%1'").arg(library);
    file.close();
    return ret;
}
Example #5
0
/*
  This opens the specified library, mmaps it into memory, and searches
  for the QT_PLUGIN_VERIFICATION_DATA.  The advantage of this approach is that
  we can get the verification data without have to actually load the library.
  This lets us detect mismatches more safely.

  Returns false if version/key information is not present, or if the
                information could not be read.
  Returns  true if version/key information is present and successfully read.
*/
static bool qt_unix_query(const QString &library, uint *version, bool *debug, QByteArray *key, QLibraryPrivate *lib = 0)
{
    QFile file(library);
    if (!file.open(QIODevice::ReadOnly)) {
        if (lib)
            lib->errorString = file.errorString();
        if (qt_debug_component()) {
            qWarning("%s: %s", (const char*) QFile::encodeName(library),
                qPrintable(qt_error_string(errno)));
        }
        return false;
    }

    QByteArray data;
    const char *filedata = 0;
    ulong fdlen = file.size();
    filedata = (char *) file.map(0, fdlen);
    if (filedata == 0) {
        // try reading the data into memory instead
        data = file.readAll();
        filedata = data.constData();
        fdlen = data.size();
    }

    /*
       ELF binaries on GNU, have .qplugin sections.
    */
    long pos = 0;
    const char pattern[] = "pattern=QT_PLUGIN_VERIFICATION_DATA";
    const ulong plen = qstrlen(pattern);
#if defined (Q_OF_ELF) && defined(Q_CC_GNU)
    int r = QElfParser().parse(filedata, fdlen, library, lib, &pos, &fdlen);
    if (r == QElfParser::NoQtSection) {
        if (pos > 0) {
            // find inside .rodata
            long rel = qt_find_pattern(filedata + pos, fdlen, pattern, plen);
            if (rel < 0) {
                pos = -1;
            } else {
                pos += rel;
            }
        } else {
            pos = qt_find_pattern(filedata, fdlen, pattern, plen);
        }
    } else if (r != QElfParser::Ok) {
        if (lib && qt_debug_component()) {
            qWarning("QElfParser: %s",qPrintable(lib->errorString));
        }
        return false;
    }
#else
    pos = qt_find_pattern(filedata, fdlen, pattern, plen);
#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU)
    bool ret = false;
    if (pos >= 0)
        ret = qt_parse_pattern(filedata + pos, version, debug, key);

    if (!ret && lib)
        lib->errorString = QLibrary::tr("Plugin verification data mismatch in '%1'").arg(library);
    file.close();
    return ret;
}
Example #6
0
void QFactoryLoader::update()
{
#ifdef QT_SHARED
    Q_D(QFactoryLoader);
    QStringList paths = QCoreApplication::libraryPaths();
    for (int i = 0; i < paths.count(); ++i) {
        const QString &pluginDir = paths.at(i);
        // Already loaded, skip it...
        if (d->loadedPaths.contains(pluginDir))
            continue;
        d->loadedPaths << pluginDir;

        QString path = pluginDir + d->suffix;
        if (!QDir(path).exists(QLatin1String(".")))
            continue;

        QStringList plugins = QDir(path).entryList(QDir::Files);
        QLibraryPrivate *library = 0;
        for (int j = 0; j < plugins.count(); ++j) {
            QString fileName = QDir::cleanPath(path + QLatin1Char('/') + plugins.at(j));

            if (qt_debug_component()) {
                qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName;
            }
            library = QLibraryPrivate::findOrCreate(QFileInfo(fileName).canonicalFilePath());
            if (!library->isPlugin()) {
                if (qt_debug_component()) {
                    qDebug() << library->errorString;
                    qDebug() << "         not a plugin";
                }
                library->release();
                continue;
            }

            QStringList keys;
            bool metaDataOk = false;

            QString iid = library->metaData.value(QLatin1String("IID")).toString();
            if (iid == QLatin1String(d->iid.constData(), d->iid.size())) {
                QJsonObject object = library->metaData.value(QLatin1String("MetaData")).toObject();
                metaDataOk = true;

                QJsonArray k = object.value(QLatin1String("Keys")).toArray();
                for (int i = 0; i < k.size(); ++i) {
                    QString s = k.at(i).toString();
                    keys += s;
                }
            }
            if (qt_debug_component())
                qDebug() << "Got keys from plugin meta data" << keys;


            if (!metaDataOk) {
                library->release();
                continue;
            }

            d->libraryList += library;
            for (int k = 0; k < keys.count(); ++k) {
                // first come first serve, unless the first
                // library was built with a future Qt version,
                // whereas the new one has a Qt version that fits
                // better
                QString key = keys.at(k);
                if (!d->cs)
                    key = key.toLower();
                QLibraryPrivate *previous = d->keyMap.value(key);
                int prev_qt_version = 0;
                if (previous) {
                    prev_qt_version = (int)previous->metaData.value(QLatin1String("version")).toDouble();
                }
                int qt_version = (int)library->metaData.value(QLatin1String("version")).toDouble();
                if (!previous || (prev_qt_version > QT_VERSION && qt_version <= QT_VERSION)) {
                    d->keyMap[key] = library;
                    d->keyList += keys.at(k);
                }
            }
        }
    }
#else
    Q_D(QFactoryLoader);
    if (qt_debug_component()) {
        qDebug() << "QFactoryLoader::QFactoryLoader() ignoring" << d->iid
                 << "since plugins are disabled in static builds";
    }
#endif
}
Example #7
0
/*
  This opens the specified library, mmaps it into memory, and searches
  for the QT_PLUGIN_VERIFICATION_DATA.  The advantage of this approach is that
  we can get the verification data without have to actually load the library.
  This lets us detect mismatches more safely.

  Returns false if version information is not present, or if the
                information could not be read.
  Returns  true if version information is present and successfully read.
*/
static bool qt_unix_query(const QString &library, QLibraryPrivate *lib)
{
    QFile file(library);
    if (!file.open(QIODevice::ReadOnly)) {
        if (lib)
            lib->errorString = file.errorString();
        if (qt_debug_component()) {
            qWarning("%s: %s", (const char*) QFile::encodeName(library),
                qPrintable(qt_error_string(errno)));
        }
        return false;
    }

    QByteArray data;
    const char *filedata = 0;
    ulong fdlen = file.size();
    filedata = (char *) file.map(0, fdlen);
    if (filedata == 0) {
        // try reading the data into memory instead
        data = file.readAll();
        filedata = data.constData();
        fdlen = data.size();
    }

    /*
       ELF binaries on GNU, have .qplugin sections.
    */
    bool hasMetaData = false;
    long pos = 0;
    const char pattern[] = "QTMETADATA  ";
    const ulong plen = qstrlen(pattern);
#if defined (Q_OF_ELF) && defined(Q_CC_GNU)
    int r = QElfParser().parse(filedata, fdlen, library, lib, &pos, &fdlen);
    if (r == QElfParser::Corrupt || r == QElfParser::NotElf) {
            if (lib && qt_debug_component()) {
                qWarning("QElfParser: %s",qPrintable(lib->errorString));
            }
            return false;
    } else if (r == QElfParser::QtMetaDataSection) {
        long rel = qt_find_pattern(filedata + pos, fdlen, pattern, plen);
        if (rel < 0)
            pos = -1;
        else
            pos += rel;
        hasMetaData = true;
    }
#else
    pos = qt_find_pattern(filedata, fdlen, pattern, plen);
    if (pos > 0)
        hasMetaData = true;
#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU)

    bool ret = false;

    if (pos >= 0) {
        if (hasMetaData) {
            const char *data = filedata + pos;
            QJsonDocument doc = QLibraryPrivate::fromRawMetaData(data);
            lib->metaData = doc.object();
            if (qt_debug_component())
                qWarning("Found metadata in lib %s, metadata=\n%s\n",
                         library.toLocal8Bit().constData(), doc.toJson().constData());
            ret = !doc.isNull();
        }
    }

    if (!ret && lib)
        lib->errorString = QLibrary::tr("Plugin verification data mismatch in '%1'").arg(library);
    file.close();
    return ret;
}