Exemple #1
0
bool QgsArchive::zip( const QString &filename )
{
  // create a temporary path
  QTemporaryFile tmpFile;
  tmpFile.open();
  tmpFile.close();

  // zip content
  if ( ! QgsZipUtils::zip( tmpFile.fileName(), mFiles ) )
  {
    QString err = QObject::tr( "Unable to zip content" );
    QgsMessageLog::logMessage( err, QStringLiteral( "QgsArchive" ) );
    return false;
  }

  // remove existing zip file
  if ( QFile::exists( filename ) )
    QFile::remove( filename );

  // save zip archive
  if ( ! tmpFile.rename( filename ) )
  {
    QString err = QObject::tr( "Unable to save zip file '%1'" ).arg( filename );
    QgsMessageLog::logMessage( err, QStringLiteral( "QgsArchive" ) );
    return false;
  }

  // keep the zip filename
  tmpFile.setAutoRemove( false );

  return true;
}
Exemple #2
0
void
writeXml( const QDomDocument& xml, const QString& path )
{
    // we write to a temporary file, and then do an atomic move
    // this prevents the client from potentially reading a corrupt XML file
    QTemporaryFile f;

    f.setAutoRemove( false );
    
    if (!f.open())
        throw "Couldn't write XML";

    QTextStream s( &f );
    xml.save( s, 2 );
    
    if ( !f.rename( path ) )
        throw QString("Couldn't move to ") + path;
}
Exemple #3
0
static int assemble(Input input, const QInstaller::Settings &settings, const QString &signingIdentity)
{
#ifdef Q_OS_OSX
    if (QInstaller::isInBundle(input.installerExePath)) {
        const QString bundle = input.installerExePath;
        // if the input file was a bundle
        const QSettings s(QString::fromLatin1("%1/Contents/Info.plist").arg(input.installerExePath),
            QSettings::NativeFormat);
        input.installerExePath = QString::fromLatin1("%1/Contents/MacOS/%2").arg(bundle)
            .arg(s.value(QLatin1String("CFBundleExecutable"),
            QFileInfo(input.installerExePath).completeBaseName()).toString());
    }

    const bool createDMG = input.outputPath.endsWith(QLatin1String(".dmg"));
    if (createDMG)
        input.outputPath.replace(input.outputPath.length() - 4, 4, QLatin1String(".app"));

    const bool isBundle = input.outputPath.endsWith(QLatin1String(".app"));
    const QString bundle = isBundle ? input.outputPath : QString();
    const BundleBackup bundleBackup(bundle);

    if (isBundle) {
        // output should be a bundle
        const QFileInfo fi(input.outputPath);

        const QString contentsResourcesPath = fi.filePath() + QLatin1String("/Contents/Resources/");

        QInstaller::mkpath(fi.filePath() + QLatin1String("/Contents/MacOS"));
        QInstaller::mkpath(contentsResourcesPath);

        {
            QFile pkgInfo(fi.filePath() + QLatin1String("/Contents/PkgInfo"));
            pkgInfo.open(QIODevice::WriteOnly);
            QTextStream pkgInfoStream(&pkgInfo);
            pkgInfoStream << QLatin1String("APPL????") << endl;
        }

        QString iconFile;
        if (QFile::exists(settings.installerApplicationIcon())) {
            iconFile = settings.installerApplicationIcon();
        } else {
            iconFile = QString::fromLatin1(":/resources/default_icon_mac.icns");
        }

        const QString iconTargetFile = fi.completeBaseName() + QLatin1String(".icns");
        QFile::copy(iconFile, contentsResourcesPath + iconTargetFile);
        if (QDir(qApp->applicationDirPath() + QLatin1String("/qt_menu.nib")).exists()) {
            copyDirectoryContents(qApp->applicationDirPath() + QLatin1String("/qt_menu.nib"),
                contentsResourcesPath + QLatin1String("/qt_menu.nib"));
        }

        QFile infoPList(fi.filePath() + QLatin1String("/Contents/Info.plist"));
        infoPList.open(QIODevice::WriteOnly);
        QTextStream plistStream(&infoPList);
        plistStream << QLatin1String("<?xml version=\"1.0\" encoding=\"UTF-8\"?>") << endl;
        plistStream << QLatin1String("<!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs"
            "/PropertyList.dtd\">") << endl;
        plistStream << QLatin1String("<plist version=\"0.9\">") << endl;
        plistStream << QLatin1String("<dict>") << endl;
        plistStream << QLatin1String("    <key>CFBundleIconFile</key>") << endl;
        plistStream << QLatin1String("    <string>") << iconTargetFile << QLatin1String("</string>")
            << endl;
        plistStream << QLatin1String("    <key>CFBundlePackageType</key>") << endl;
        plistStream << QLatin1String("    <string>APPL</string>") << endl;
        plistStream << QLatin1String("    <key>CFBundleGetInfoString</key>") << endl;
#define QUOTE_(x) #x
#define QUOTE(x) QUOTE_(x)
        plistStream << QLatin1String("    <string>") << QLatin1String(QUOTE(IFW_VERSION_STR)) << ("</string>")
            << endl;
#undef QUOTE
#undef QUOTE_
        plistStream << QLatin1String("    <key>CFBundleSignature</key>") << endl;
        plistStream << QLatin1String("    <string> ???? </string>") << endl;
        plistStream << QLatin1String("    <key>CFBundleExecutable</key>") << endl;
        plistStream << QLatin1String("    <string>") << fi.completeBaseName() << QLatin1String("</string>")
            << endl;
        plistStream << QLatin1String("    <key>CFBundleIdentifier</key>") << endl;
        plistStream << QLatin1String("    <string>com.yourcompany.installerbase</string>") << endl;
        plistStream << QLatin1String("    <key>NOTE</key>") << endl;
        plistStream << QLatin1String("    <string>This file was generated by Qt Installer Framework.</string>")
            << endl;
        plistStream << QLatin1String("    <key>NSPrincipalClass</key>") << endl;
        plistStream << QLatin1String("    <string>NSApplication</string>") << endl;
        plistStream << QLatin1String("</dict>") << endl;
        plistStream << QLatin1String("</plist>") << endl;

        input.outputPath = QString::fromLatin1("%1/Contents/MacOS/%2").arg(input.outputPath)
            .arg(fi.completeBaseName());
    }
#elif defined(Q_OS_LINUX)
    Q_UNUSED(settings)
#endif

    QTemporaryFile file(input.outputPath);
    if (!file.open()) {
        throw Error(QString::fromLatin1("Cannot copy %1 to %2: %3").arg(input.installerExePath,
            input.outputPath, file.errorString()));
    }

    const QString tempFile = file.fileName();
    file.close();
    file.remove();

    QFile instExe(input.installerExePath);
    if (!instExe.copy(tempFile)) {
        throw Error(QString::fromLatin1("Cannot copy %1 to %2: %3").arg(instExe.fileName(),
            tempFile, instExe.errorString()));
    }

    QtPatch::patchBinaryFile(tempFile, QByteArray("MY_InstallerCreateDateTime_MY"),
        QDateTime::currentDateTime().toString(QLatin1String("yyyy-MM-dd - HH:mm:ss")).toLatin1());


    input.installerExePath = tempFile;

#if defined(Q_OS_WIN)
    // setting the windows icon must happen before we append our binary data - otherwise they get lost :-/
    if (QFile::exists(settings.installerApplicationIcon())) {
        // no error handling as this is not fatal
        setApplicationIcon(tempFile, settings.installerApplicationIcon());
    }
#elif defined(Q_OS_OSX)
    if (isBundle) {
        // no error handling as this is not fatal
        const QString copyscript = QDir::temp().absoluteFilePath(QLatin1String("copylibsintobundle.sh"));
        QFile::copy(QLatin1String(":/resources/copylibsintobundle.sh"), copyscript);
        QFile::rename(tempFile, input.outputPath);
        chmod755(copyscript);
        QProcess p;
        p.start(copyscript, QStringList() << bundle);
        p.waitForFinished(-1);
        QFile::rename(input.outputPath, tempFile);
        QFile::remove(copyscript);
    }
#endif

    QTemporaryFile out;
    QString targetName = input.outputPath;
#ifdef Q_OS_OSX
    QDir resourcePath(QFileInfo(input.outputPath).dir());
    resourcePath.cdUp();
    resourcePath.cd(QLatin1String("Resources"));
    targetName = resourcePath.filePath(QLatin1String("installer.dat"));
#endif

    {
        QFile target(targetName);
        if (target.exists() && !target.remove()) {
            qCritical("Cannot remove target %s: %s", qPrintable(target.fileName()),
                qPrintable(target.errorString()));
            QFile::remove(tempFile);
            return EXIT_FAILURE;
        }
    }

    try {
        QInstaller::openForWrite(&out);
        QFile exe(input.installerExePath);

#ifdef Q_OS_OSX
        if (!exe.copy(input.outputPath)) {
            throw Error(QString::fromLatin1("Cannot copy %1 to %2: %3").arg(exe.fileName(),
                input.outputPath, exe.errorString()));
        }
#else
        QInstaller::openForRead(&exe);
        QInstaller::appendData(&out, &exe, exe.size());
#endif

        foreach (const QInstallerTools::PackageInfo &info, input.packages) {
            QInstaller::ResourceCollection collection;
            collection.setName(info.name.toUtf8());

            qDebug() << "Creating resource archive for" << info.name;
            foreach (const QString &file, info.copiedFiles) {
                const QSharedPointer<Resource> resource(new Resource(file));
                qDebug().nospace() << "Appending " << file << " (" << humanReadableSize(resource->size()) << ")";
                collection.appendResource(resource);
            }
            input.manager.insertCollection(collection);
        }

        const QList<QInstaller::OperationBlob> operations;
        BinaryContent::writeBinaryContent(&out, operations, input.manager,
            BinaryContent::MagicInstallerMarker, BinaryContent::MagicCookie);
    } catch (const Error &e) {
        qCritical("Error occurred while assembling the installer: %s", qPrintable(e.message()));
        QFile::remove(tempFile);
        return EXIT_FAILURE;
    }

    if (!out.rename(targetName)) {
        qCritical("Cannot write installer to %s: %s", targetName.toUtf8().constData(),
            out.errorString().toUtf8().constData());
        QFile::remove(tempFile);
        return EXIT_FAILURE;
    }
    out.setAutoRemove(false);

#ifndef Q_OS_WIN
    chmod755(out.fileName());
#endif
    QFile::remove(tempFile);

#ifdef Q_OS_OSX
    if (isBundle && !signingIdentity.isEmpty()) {
        qDebug() << "Signing .app bundle...";

        QProcess p;
        p.start(QLatin1String("codesign"),
                QStringList() << QLatin1String("--force")
                              << QLatin1String("--deep")
                              << QLatin1String("--sign") << signingIdentity
                              << bundle);

        if (!p.waitForFinished(-1)) {
            qCritical("Failed to sign app bundle: error while running '%s %s': %s",
                      p.program().toUtf8().constData(),
                      p.arguments().join(QLatin1Char(' ')).toUtf8().constData(),
                      p.errorString().toUtf8().constData());
            return EXIT_FAILURE;
        }

        if (p.exitStatus() == QProcess::NormalExit) {
            if (p.exitCode() != 0) {
                qCritical("Failed to sign app bundle: running codesign failed "
                          "with exit code %d: %s", p.exitCode(),
                          p.readAllStandardError().constData());
                return EXIT_FAILURE;
            }
        }

        qDebug() << "done.";
    }

    bundleBackup.release();

    if (createDMG) {
        qDebug() << "creating a DMG disk image...";

        const QString volumeName = QFileInfo(input.outputPath).fileName();
        const QString imagePath = QString::fromLatin1("%1/%2.dmg")
                                    .arg(QFileInfo(bundle).path())
                                    .arg(volumeName);

        // no error handling as this is not fatal
        QProcess p;
        p.start(QLatin1String("/usr/bin/hdiutil"),
                QStringList() << QLatin1String("create")
                              << imagePath
                              << QLatin1String("-srcfolder")
                              << bundle
                              << QLatin1String("-ov")
                              << QLatin1String("-volname")
                              << volumeName
                              << QLatin1String("-fs")
                              << QLatin1String("HFS+"));
        qDebug() << "running " << p.program() << p.arguments();
        p.waitForFinished(-1);
        qDebug() << "removing" << bundle;
        QDir(bundle).removeRecursively();
        qDebug() <<  "done.";
    }
#else
    Q_UNUSED(signingIdentity)
#endif
    return EXIT_SUCCESS;
}
Exemple #4
0
void HistoryManager::save()
{
    QSettings settings;
    settings.beginGroup(QLatin1String("history"));
    settings.setValue(QLatin1String("historyLimit"), m_historyLimit);

    bool saveAll = m_lastSavedUrl.isEmpty();
    int first = m_history.count() - 1;
    if (!saveAll) {
        // find the first one to save
        for (int i = 0; i < m_history.count(); ++i) {
            if (m_history.at(i).url == m_lastSavedUrl) {
                first = i - 1;
                break;
            }
        }
    }
    if (first == m_history.count() - 1)
        saveAll = true;

    QString directory = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
    if (directory.isEmpty())
        directory = QDir::homePath() + QLatin1String("/.") + QCoreApplication::applicationName();
    if (!QFile::exists(directory)) {
        QDir dir;
        dir.mkpath(directory);
    }

    QFile historyFile(directory + QLatin1String("/history"));
    // When saving everything use a temporary file to prevent possible data loss.
    QTemporaryFile tempFile;
    tempFile.setAutoRemove(false);
    bool open = false;
    if (saveAll) {
        open = tempFile.open();
    } else {
        open = historyFile.open(QFile::Append);
    }

    if (!open) {
        qWarning() << "Unable to open history file for saving"
                   << (saveAll ? tempFile.fileName() : historyFile.fileName());
        return;
    }

    QDataStream out(saveAll ? &tempFile : &historyFile);
    for (int i = first; i >= 0; --i) {
        QByteArray data;
        QDataStream stream(&data, QIODevice::WriteOnly);
        HistoryItem item = m_history.at(i);
        stream << HISTORY_VERSION << item.url << item.dateTime << item.title;
        out << data;
    }
    tempFile.close();

    if (saveAll) {
        if (historyFile.exists() && !historyFile.remove())
            qWarning() << "History: error removing old history." << historyFile.errorString();
        if (!tempFile.rename(historyFile.fileName()))
            qWarning() << "History: error moving new history over old." << tempFile.errorString() << historyFile.fileName();
    }
    m_lastSavedUrl = m_history.value(0).url;
}