mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-01 20:00:13 +02:00
Beginning of tomahawk-side osx handling of binary resolvers
This commit is contained in:
@@ -143,5 +143,6 @@
|
|||||||
<file>data/images/process-stop.png</file>
|
<file>data/images/process-stop.png</file>
|
||||||
<file>data/icons/tomahawk-icon-128x128-grayscale.png</file>
|
<file>data/icons/tomahawk-icon-128x128-grayscale.png</file>
|
||||||
<file>data/images/collection.png</file>
|
<file>data/images/collection.png</file>
|
||||||
|
<file>data/misc/tomahawk_pubkey.pem</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@@ -23,8 +23,6 @@
|
|||||||
#include "Pipeline.h"
|
#include "Pipeline.h"
|
||||||
|
|
||||||
#include <attica/downloaditem.h>
|
#include <attica/downloaditem.h>
|
||||||
#include <quazip.h>
|
|
||||||
#include <quazipfile.h>
|
|
||||||
|
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QTemporaryFile>
|
#include <QTemporaryFile>
|
||||||
@@ -451,6 +449,7 @@ AtticaManager::installResolver( const Content& resolver, bool autoCreateAccount
|
|||||||
connect( job, SIGNAL( finished( Attica::BaseJob* ) ), this, SLOT( resolverDownloadFinished( Attica::BaseJob* ) ) );
|
connect( job, SIGNAL( finished( Attica::BaseJob* ) ), this, SLOT( resolverDownloadFinished( Attica::BaseJob* ) ) );
|
||||||
job->setProperty( "resolverId", resolver.id() );
|
job->setProperty( "resolverId", resolver.id() );
|
||||||
job->setProperty( "createAccount", autoCreateAccount );
|
job->setProperty( "createAccount", autoCreateAccount );
|
||||||
|
job->setProperty( "binarySignature", resolver.attribute("signature"));
|
||||||
|
|
||||||
job->start();
|
job->start();
|
||||||
}
|
}
|
||||||
@@ -487,6 +486,7 @@ AtticaManager::resolverDownloadFinished ( BaseJob* j )
|
|||||||
connect( reply, SIGNAL( finished() ), this, SLOT( payloadFetched() ) );
|
connect( reply, SIGNAL( finished() ), this, SLOT( payloadFetched() ) );
|
||||||
reply->setProperty( "resolverId", job->property( "resolverId" ) );
|
reply->setProperty( "resolverId", job->property( "resolverId" ) );
|
||||||
reply->setProperty( "createAccount", job->property( "createAccount" ) );
|
reply->setProperty( "createAccount", job->property( "createAccount" ) );
|
||||||
|
reply->setProperty( "binarySignature", job->property( "binarySignature" ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -513,23 +513,50 @@ AtticaManager::payloadFetched()
|
|||||||
f.write( reply->readAll() );
|
f.write( reply->readAll() );
|
||||||
f.close();
|
f.close();
|
||||||
|
|
||||||
QString resolverId = reply->property( "resolverId" ).toString();
|
bool installedSuccessfully = false;
|
||||||
QDir dir( extractPayload( f.fileName(), resolverId ) );
|
const QString resolverId = reply->property( "resolverId" ).toString();
|
||||||
QString resolverPath = dir.absoluteFilePath( m_resolverStates[ resolverId ].scriptPath );
|
if ( m_resolverStates[ resolverId ].binary )
|
||||||
|
|
||||||
if ( !resolverPath.isEmpty() )
|
|
||||||
{
|
{
|
||||||
// update with absolute, not relative, path
|
// First ensure the signature matches. If we can't verify it, abort!
|
||||||
m_resolverStates[ resolverId ].scriptPath = resolverPath;
|
const QString signature = reply->property( "binarySignature" ).toString();
|
||||||
|
// Must have a signature for binary resolvers...
|
||||||
if ( reply->property( "createAccount" ).toBool() )
|
Q_ASSERT( !signature.isEmpty() );
|
||||||
|
if ( signature.isEmpty() )
|
||||||
|
return;
|
||||||
|
if ( !TomahawkUtils::verifyFile( f.fileName(), signature ) )
|
||||||
{
|
{
|
||||||
// Do the install / add to tomahawk
|
qWarning() << "FILE SIGNATURE FAILED FOR BINARY RESOLVER! WARNING! :" << f.fileName() << signature;
|
||||||
Tomahawk::Accounts::Account* resolver = Tomahawk::Accounts::ResolverAccountFactory::createFromPath( resolverPath, "resolveraccount", true );
|
return;
|
||||||
Tomahawk::Accounts::AccountManager::instance()->addAccount( resolver );
|
|
||||||
TomahawkSettings::instance()->addAccount( resolver->accountId() );
|
|
||||||
}
|
}
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
|
||||||
|
#elif Q_OS_WIN
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QDir dir( TomahawkUtils::extractScriptPayload( f.fileName(), resolverId ) );
|
||||||
|
QString resolverPath = dir.absoluteFilePath( m_resolverStates[ resolverId ].scriptPath );
|
||||||
|
|
||||||
|
if ( !resolverPath.isEmpty() )
|
||||||
|
{
|
||||||
|
// update with absolute, not relative, path
|
||||||
|
m_resolverStates[ resolverId ].scriptPath = resolverPath;
|
||||||
|
|
||||||
|
if ( reply->property( "createAccount" ).toBool() )
|
||||||
|
{
|
||||||
|
// Do the install / add to tomahawk
|
||||||
|
Tomahawk::Accounts::Account* resolver = Tomahawk::Accounts::ResolverAccountFactory::createFromPath( resolverPath, "resolveraccount", true );
|
||||||
|
Tomahawk::Accounts::AccountManager::instance()->addAccount( resolver );
|
||||||
|
TomahawkSettings::instance()->addAccount( resolver->accountId() );
|
||||||
|
}
|
||||||
|
|
||||||
|
installedSuccessfully = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( installedSuccessfully )
|
||||||
|
{
|
||||||
m_resolverStates[ resolverId ].state = Installed;
|
m_resolverStates[ resolverId ].state = Installed;
|
||||||
TomahawkSettingsGui::instanceGui()->setAtticaResolverStates( m_resolverStates );
|
TomahawkSettingsGui::instanceGui()->setAtticaResolverStates( m_resolverStates );
|
||||||
emit resolverInstalled( resolverId );
|
emit resolverInstalled( resolverId );
|
||||||
@@ -543,75 +570,6 @@ AtticaManager::payloadFetched()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QString
|
|
||||||
AtticaManager::extractPayload( const QString& filename, const QString& resolverId ) const
|
|
||||||
{
|
|
||||||
// uses QuaZip to extract the temporary zip file to the user's tomahawk data/resolvers directory
|
|
||||||
QuaZip zipFile( filename );
|
|
||||||
if ( !zipFile.open( QuaZip::mdUnzip ) )
|
|
||||||
{
|
|
||||||
tLog() << "Failed to QuaZip open:" << zipFile.getZipError();
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !zipFile.goToFirstFile() )
|
|
||||||
{
|
|
||||||
tLog() << "Failed to go to first file in zip archive: " << zipFile.getZipError();
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
QDir resolverDir = TomahawkUtils::appDataDir();
|
|
||||||
if ( !resolverDir.mkpath( QString( "atticaresolvers/%1" ).arg( resolverId ) ) )
|
|
||||||
{
|
|
||||||
tLog() << "Failed to mkdir resolver save dir: " << TomahawkUtils::appDataDir().absoluteFilePath( QString( "atticaresolvers/%1" ).arg( resolverId ) );
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
resolverDir.cd( QString( "atticaresolvers/%1" ).arg( resolverId ) );
|
|
||||||
tDebug() << "Installing resolver to:" << resolverDir.absolutePath();
|
|
||||||
|
|
||||||
QuaZipFile fileInZip( &zipFile );
|
|
||||||
do
|
|
||||||
{
|
|
||||||
QuaZipFileInfo info;
|
|
||||||
zipFile.getCurrentFileInfo( &info );
|
|
||||||
|
|
||||||
if ( !fileInZip.open( QIODevice::ReadOnly ) )
|
|
||||||
{
|
|
||||||
tLog() << "Failed to open file inside zip archive:" << info.name << zipFile.getZipName() << "with error:" << zipFile.getZipError();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QFile out( resolverDir.absoluteFilePath( fileInZip.getActualFileName() ) );
|
|
||||||
|
|
||||||
QStringList parts = fileInZip.getActualFileName().split( "/" );
|
|
||||||
if ( parts.size() > 1 )
|
|
||||||
{
|
|
||||||
QStringList dirs = parts.mid( 0, parts.size() - 1 );
|
|
||||||
QString dirPath = dirs.join( "/" ); // QDir translates / to \ internally if necessary
|
|
||||||
resolverDir.mkpath( dirPath );
|
|
||||||
}
|
|
||||||
|
|
||||||
// make dir if there is one needed
|
|
||||||
QDir d( fileInZip.getActualFileName() );
|
|
||||||
|
|
||||||
tDebug() << "Writing to output file..." << out.fileName();
|
|
||||||
if ( !out.open( QIODevice::WriteOnly ) )
|
|
||||||
{
|
|
||||||
tLog() << "Failed to open resolver extract file:" << out.errorString() << info.name;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
out.write( fileInZip.readAll() );
|
|
||||||
out.close();
|
|
||||||
fileInZip.close();
|
|
||||||
|
|
||||||
} while ( zipFile.goToNextFile() );
|
|
||||||
|
|
||||||
return resolverDir.absolutePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
AtticaManager::uninstallResolver( const QString& pathToResolver )
|
AtticaManager::uninstallResolver( const QString& pathToResolver )
|
||||||
{
|
{
|
||||||
|
@@ -391,6 +391,7 @@ IF( APPLE )
|
|||||||
infosystem/infoplugins/mac/Adium.mm
|
infosystem/infoplugins/mac/Adium.mm
|
||||||
infosystem/infoplugins/mac/AdiumPlugin.cpp
|
infosystem/infoplugins/mac/AdiumPlugin.cpp
|
||||||
utils/TomahawkUtils_Mac.mm
|
utils/TomahawkUtils_Mac.mm
|
||||||
|
mac/FileHelpers.mm
|
||||||
thirdparty/Qocoa/qsearchfield_mac.mm )
|
thirdparty/Qocoa/qsearchfield_mac.mm )
|
||||||
|
|
||||||
SET_SOURCE_FILES_PROPERTIES(utils/TomahawkUtils_Mac.mm PROPERTIES COMPILE_FLAGS "-fvisibility=default")
|
SET_SOURCE_FILES_PROPERTIES(utils/TomahawkUtils_Mac.mm PROPERTIES COMPILE_FLAGS "-fvisibility=default")
|
||||||
@@ -400,10 +401,11 @@ IF( APPLE )
|
|||||||
# System
|
# System
|
||||||
${COREAUDIO_LIBRARY}
|
${COREAUDIO_LIBRARY}
|
||||||
${COREFOUNDATION_LIBRARY}
|
${COREFOUNDATION_LIBRARY}
|
||||||
${FOUNDATION_LIBRARY}
|
${FOUNDATION_LIBRARY}
|
||||||
${SCRIPTINGBRIDGE_LIBRARY}
|
${SCRIPTINGBRIDGE_LIBRARY}
|
||||||
|
|
||||||
/System/Library/Frameworks/AppKit.framework
|
/System/Library/Frameworks/AppKit.framework
|
||||||
|
/System/Library/Frameworks/Security.framework
|
||||||
)
|
)
|
||||||
ELSE( APPLE )
|
ELSE( APPLE )
|
||||||
SET( libGuiSources ${libGuiSources} thirdparty/Qocoa/qsearchfield.cpp )
|
SET( libGuiSources ${libGuiSources} thirdparty/Qocoa/qsearchfield.cpp )
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||||
*
|
*
|
||||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||||
|
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||||
*
|
*
|
||||||
* Tomahawk is free software: you can redistribute it and/or modify
|
* Tomahawk is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||||
*
|
*
|
||||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||||
|
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||||
*
|
*
|
||||||
* Tomahawk is free software: you can redistribute it and/or modify
|
* Tomahawk is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -39,6 +39,9 @@
|
|||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
|
|
||||||
|
#include <quazip.h>
|
||||||
|
#include <quazipfile.h>
|
||||||
|
|
||||||
#ifdef Q_WS_WIN
|
#ifdef Q_WS_WIN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
@@ -49,6 +52,10 @@
|
|||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef QCA2_FOUND
|
||||||
|
#include <QtCrypto>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace TomahawkUtils
|
namespace TomahawkUtils
|
||||||
{
|
{
|
||||||
static quint64 s_infosystemRequestId = 0;
|
static quint64 s_infosystemRequestId = 0;
|
||||||
@@ -676,4 +683,160 @@ SharedTimeLine::disconnectNotify( const char* signal )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
verifyFile( const QString &filePath, const QString &signature )
|
||||||
|
{
|
||||||
|
QCA::Initializer init;
|
||||||
|
|
||||||
|
if( !QCA::isSupported( "sha1" ) )
|
||||||
|
{
|
||||||
|
qWarning() << "SHA1 not supported by QCA, aborting.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The signature for the resolver.zip was created like so:
|
||||||
|
// openssl dgst -sha1 -binary < "#{tarball}" | openssl dgst -dss1 -sign "#{ARGV[2]}" | openssl enc -base64
|
||||||
|
// which means we need to decode it with QCA's DSA public key signature verification tools
|
||||||
|
// The input data is:
|
||||||
|
// file -> SHA1 binary format -> DSS1/DSA signed -> base64 encoded.
|
||||||
|
|
||||||
|
// Step 1: Load the public key
|
||||||
|
// Public key is in :/data/misc/tomahawk_pubkey.pem
|
||||||
|
QFile f( ":/data/misc/tomahawk_pubkey.pem" );
|
||||||
|
if ( !f.open( QIODevice::ReadOnly ) )
|
||||||
|
{
|
||||||
|
qWarning() << "Unable to read public key from resources!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString pubkeyData = QString::fromUtf8( f.readAll() );
|
||||||
|
QCA::ConvertResult conversionResult;
|
||||||
|
QCA::PublicKey publicKey = QCA::PublicKey::fromPEM( pubkeyData, &conversionResult );
|
||||||
|
if ( QCA::ConvertGood != conversionResult)
|
||||||
|
{
|
||||||
|
qWarning() << "Public key reading/loading failed! Tried to load public key:" << pubkeyData;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !publicKey.canVerify() )
|
||||||
|
{
|
||||||
|
qWarning() << "Loaded Tomahawk public key but cannot use it to verify! What is up....";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: Get the SHA1 of the file contents
|
||||||
|
QFile toVerify( filePath );
|
||||||
|
if ( !toVerify.exists() || !toVerify.open( QIODevice::ReadOnly ) )
|
||||||
|
{
|
||||||
|
qWarning() << "Failed to open file we are trying to verify!" << filePath;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCA::Hash fileHash = QCA::Hash( "sha1 ");
|
||||||
|
//QCA::SecureArray fileData( toVerify.readAll() );
|
||||||
|
//fileHash.update( fileData );
|
||||||
|
const QByteArray fileHashData = QCA::Hash( "sha1" ).hash( toVerify.readAll() ).toByteArray();
|
||||||
|
toVerify.close();
|
||||||
|
|
||||||
|
// Step 3: Base64 decode the signature
|
||||||
|
QCA::Base64 decoder( QCA::Decode );
|
||||||
|
const QByteArray decodedSignature = decoder.decode( QCA::SecureArray( signature.trimmed().toUtf8() ) ).toByteArray();
|
||||||
|
if ( decodedSignature.isEmpty() )
|
||||||
|
{
|
||||||
|
qWarning() << "Got empty signature after we tried to decode it from Base64:" << signature.trimmed().toUtf8() << decodedSignature.toBase64();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4: Do the actual verifying!
|
||||||
|
const bool result = publicKey.verifyMessage( fileHashData, decodedSignature, QCA::EMSA1_SHA1, QCA::DERSequence );
|
||||||
|
if ( !result )
|
||||||
|
{
|
||||||
|
qWarning() << "File" << filePath << "FAILED VERIFICATION against our input signature!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "Successfully verified signature of downloaded file:" << filePath;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString
|
||||||
|
extractScriptPayload( const QString& filename, const QString& resolverId )
|
||||||
|
{
|
||||||
|
// uses QuaZip to extract the temporary zip file to the user's tomahawk data/resolvers directory
|
||||||
|
QuaZip zipFile( filename );
|
||||||
|
if ( !zipFile.open( QuaZip::mdUnzip ) )
|
||||||
|
{
|
||||||
|
tLog() << "Failed to QuaZip open:" << zipFile.getZipError();
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !zipFile.goToFirstFile() )
|
||||||
|
{
|
||||||
|
tLog() << "Failed to go to first file in zip archive: " << zipFile.getZipError();
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QDir resolverDir = appDataDir();
|
||||||
|
if ( !resolverDir.mkpath( QString( "atticaresolvers/%1" ).arg( resolverId ) ) )
|
||||||
|
{
|
||||||
|
tLog() << "Failed to mkdir resolver save dir: " << TomahawkUtils::appDataDir().absoluteFilePath( QString( "atticaresolvers/%1" ).arg( resolverId ) );
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
resolverDir.cd( QString( "atticaresolvers/%1" ).arg( resolverId ) );
|
||||||
|
tDebug() << "Installing resolver to:" << resolverDir.absolutePath();
|
||||||
|
|
||||||
|
QuaZipFile fileInZip( &zipFile );
|
||||||
|
do
|
||||||
|
{
|
||||||
|
QuaZipFileInfo info;
|
||||||
|
zipFile.getCurrentFileInfo( &info );
|
||||||
|
|
||||||
|
if ( !fileInZip.open( QIODevice::ReadOnly ) )
|
||||||
|
{
|
||||||
|
tLog() << "Failed to open file inside zip archive:" << info.name << zipFile.getZipName() << "with error:" << zipFile.getZipError();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile out( resolverDir.absoluteFilePath( fileInZip.getActualFileName() ) );
|
||||||
|
|
||||||
|
QStringList parts = fileInZip.getActualFileName().split( "/" );
|
||||||
|
if ( parts.size() > 1 )
|
||||||
|
{
|
||||||
|
QStringList dirs = parts.mid( 0, parts.size() - 1 );
|
||||||
|
QString dirPath = dirs.join( "/" ); // QDir translates / to \ internally if necessary
|
||||||
|
resolverDir.mkpath( dirPath );
|
||||||
|
}
|
||||||
|
|
||||||
|
// make dir if there is one needed
|
||||||
|
QDir d( fileInZip.getActualFileName() );
|
||||||
|
|
||||||
|
tDebug() << "Writing to output file..." << out.fileName();
|
||||||
|
if ( !out.open( QIODevice::WriteOnly ) )
|
||||||
|
{
|
||||||
|
tLog() << "Failed to open resolver extract file:" << out.errorString() << info.name;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
out.write( fileInZip.readAll() );
|
||||||
|
out.close();
|
||||||
|
fileInZip.close();
|
||||||
|
|
||||||
|
} while ( zipFile.goToNextFile() );
|
||||||
|
|
||||||
|
return resolverDir.absolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(Q_OS_MAC) // && !defined(Q_OS_WIN)
|
||||||
|
void
|
||||||
|
extractBinaryResolver( const QString& zipFilename, const QString& resolverId, QObject* )
|
||||||
|
{
|
||||||
|
// No support for binary resolvers on linux! Shouldn't even have been allowed to see/install..
|
||||||
|
Q_ASSERT( false );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // ns
|
} // ns
|
||||||
|
@@ -137,6 +137,13 @@ namespace TomahawkUtils
|
|||||||
DLLEXPORT QString md5( const QByteArray& data );
|
DLLEXPORT QString md5( const QByteArray& data );
|
||||||
DLLEXPORT bool removeDirectory( const QString& dir );
|
DLLEXPORT bool removeDirectory( const QString& dir );
|
||||||
|
|
||||||
|
DLLEXPORT bool verifyFile( const QString& filePath, const QString& signature );
|
||||||
|
DLLEXPORT QString extractScriptPayload( const QString& filename, const QString& resolverId );
|
||||||
|
|
||||||
|
// Extracting may be asynchronous, pass in a receiver object with the following slots:
|
||||||
|
// extractSucceeded( const QString& path ) and extractFailed() to be notified/
|
||||||
|
DLLEXPORT void extractBinaryResolver( const QString& zipFilename, const QString& resolverId, QObject* receiver );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This helper is designed to help "update" an existing playlist with a newer revision of itself.
|
* This helper is designed to help "update" an existing playlist with a newer revision of itself.
|
||||||
* To avoid re-loading the whole playlist and re-resolving tracks that are the same in the old playlist,
|
* To avoid re-loading the whole playlist and re-resolving tracks that are the same in the old playlist,
|
||||||
|
37
src/libtomahawk/utils/TomahawkUtils_Mac.h
Normal file
37
src/libtomahawk/utils/TomahawkUtils_Mac.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||||
|
*
|
||||||
|
* Copyright 2012, Leo Franchi <lfranchi@kde.org
|
||||||
|
*
|
||||||
|
* Tomahawk is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Tomahawk is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TOMAHAWKUTILS_MAC_H
|
||||||
|
#define TOMAHAWKUTILS_MAC_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#import "mac/FileHelpers.h"
|
||||||
|
|
||||||
|
@interface MoveDelegate : NSObject
|
||||||
|
{
|
||||||
|
QObject* receiver;
|
||||||
|
QString path;
|
||||||
|
}
|
||||||
|
- (void)setReceiver:(QObject*)receiver;
|
||||||
|
- (void)setMoveTo:(QString)path;
|
||||||
|
- (void)moveFinished;
|
||||||
|
- (void)moveFailedWithError:(NSError *)error;
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif // TOMAHAWKUTILS_MAC_H
|
@@ -1,6 +1,54 @@
|
|||||||
|
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||||
|
*
|
||||||
|
* Copyright 2012, Leo Franchi <lfranchi@kde.org
|
||||||
|
*
|
||||||
|
* Tomahawk is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Tomahawk is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "TomahawkUtils.h"
|
#include "TomahawkUtils.h"
|
||||||
|
|
||||||
|
#include "TomahawkUtils_Mac.h"
|
||||||
|
#include "mac/FileHelpers.h"
|
||||||
|
|
||||||
|
#include <QTemporaryFile>
|
||||||
|
|
||||||
#import <AppKit/NSApplication.h>
|
#import <AppKit/NSApplication.h>
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@implementation MoveDelegate
|
||||||
|
|
||||||
|
|
||||||
|
-(void) setReceiver:(QObject*) object
|
||||||
|
{
|
||||||
|
receiver = object;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) setMoveTo:(QString) p
|
||||||
|
{
|
||||||
|
path = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)moveFinished
|
||||||
|
{
|
||||||
|
QMetaObject::invokeMethod(receiver, "installSucceeded", Qt::DirectConnection, Q_ARG(QString, path));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)moveFailedWithError:(NSError *)error
|
||||||
|
{
|
||||||
|
QMetaObject::invokeMethod(receiver, "installFailed", Qt::DirectConnection);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
namespace TomahawkUtils
|
namespace TomahawkUtils
|
||||||
{
|
{
|
||||||
@@ -10,4 +58,35 @@ bringToFront() {
|
|||||||
[NSApp activateIgnoringOtherApps:YES];
|
[NSApp activateIgnoringOtherApps:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
extractBinaryResolver( const QString& zipFilename, const QString& resolverId, QObject* receiver )
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
On OS X, we have to do the following:
|
||||||
|
2) Extract file in temporary location
|
||||||
|
3) Authenticate to be able to have write access to the /Applications folder
|
||||||
|
4) Copy the contents of the zipfile to the Tomahawk.app/Contents/MacOS/ folder
|
||||||
|
5) Call result slots on receiver object
|
||||||
|
*/
|
||||||
|
|
||||||
|
MoveDelegate* del = [[MoveDelegate alloc] init];
|
||||||
|
[del setReceiver: receiver];
|
||||||
|
|
||||||
|
// Unzip in temporary folder and copy the contents to MacOS/
|
||||||
|
NSError* err = NULL;
|
||||||
|
NSFileManager *manager = [[[NSFileManager alloc] init] autorelease];
|
||||||
|
NSURL* tempDir = [manager URLForDirectory:NSCachesDirectory inDomain:NSUserDomainMask appropriateForURL:NULL create:YES error:&err];
|
||||||
|
if ( err )
|
||||||
|
{
|
||||||
|
qDebug() << "GOT ERROR trying to create temp dir to unzip in...:" << err;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "Using temporary directory:" << [tempDir absoluteString];
|
||||||
|
|
||||||
|
|
||||||
|
// [del setMoveTo: to];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -121,7 +121,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|||||||
int
|
int
|
||||||
main( int argc, char *argv[] )
|
main( int argc, char *argv[] )
|
||||||
{
|
{
|
||||||
#ifdef Q_WS_MAC
|
#ifdef Q_WS_MAC
|
||||||
// Do Mac specific startup to get media keys working.
|
// Do Mac specific startup to get media keys working.
|
||||||
// This must go before QApplication initialisation.
|
// This must go before QApplication initialisation.
|
||||||
Tomahawk::macMain();
|
Tomahawk::macMain();
|
||||||
|
Reference in New Issue
Block a user