From 27eb1b51f15218f54e631a1e8dc0be7c033fc842 Mon Sep 17 00:00:00 2001 From: Leo Franchi Date: Sun, 13 May 2012 17:05:37 -0400 Subject: [PATCH] Enable move-with-authentication for osx binary resolvers --- src/libtomahawk/AtticaManager.cpp | 6 +- src/libtomahawk/utils/Closure.h | 3 +- src/libtomahawk/utils/TomahawkUtils.cpp | 99 ++++++++++++++++------ src/libtomahawk/utils/TomahawkUtils.h | 5 ++ src/libtomahawk/utils/TomahawkUtils_Mac.mm | 43 +++++----- 5 files changed, 102 insertions(+), 54 deletions(-) diff --git a/src/libtomahawk/AtticaManager.cpp b/src/libtomahawk/AtticaManager.cpp index b8636f4b6..4be683ea1 100644 --- a/src/libtomahawk/AtticaManager.cpp +++ b/src/libtomahawk/AtticaManager.cpp @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -357,6 +358,7 @@ AtticaManager::binaryResolversList( BaseJob* j ) if ( !c.attribute( "typeid" ).isEmpty() && c.attribute( "typeid" ) == platform ) { // We have a binary resolver for this platform + qDebug() << "WE GOT A BINARY RESOLVER:" << c.id() << c.name() << c.attribute( "signature" ); m_resolvers.append( c ); if ( !m_resolverStates.contains( c.id() ) ) { @@ -528,10 +530,8 @@ AtticaManager::payloadFetched() qWarning() << "FILE SIGNATURE FAILED FOR BINARY RESOLVER! WARNING! :" << f.fileName() << signature; return; } -#ifdef Q_OS_MAC -#elif Q_OS_WIN -#endif + TomahawkUtils::extractBinaryResolver( f.fileName(), resolverId, 0 ); } else { diff --git a/src/libtomahawk/utils/Closure.h b/src/libtomahawk/utils/Closure.h index f071c0e28..591712358 100644 --- a/src/libtomahawk/utils/Closure.h +++ b/src/libtomahawk/utils/Closure.h @@ -1,5 +1,6 @@ -/* This file is part of Clementine. +/* This file is part of Tomabawk. Copyright 2011, David Sansome + Copyright 2012, Leo Franchi Clementine is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/libtomahawk/utils/TomahawkUtils.cpp b/src/libtomahawk/utils/TomahawkUtils.cpp index c2cc93b18..7c3256861 100644 --- a/src/libtomahawk/utils/TomahawkUtils.cpp +++ b/src/libtomahawk/utils/TomahawkUtils.cpp @@ -42,7 +42,7 @@ #include #include -#ifdef Q_WS_WIN +#ifdef Q_OS_WIN #include #include #endif @@ -732,9 +732,6 @@ verifyFile( const QString &filePath, const QString &signature ) 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(); @@ -765,18 +762,6 @@ 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 ) ) ) @@ -785,7 +770,38 @@ extractScriptPayload( const QString& filename, const QString& resolverId ) return QString(); } resolverDir.cd( QString( "atticaresolvers/%1" ).arg( resolverId ) ); - tDebug() << "Installing resolver to:" << resolverDir.absolutePath(); + + + if ( !unzipFileInFolder( filename, resolverDir ) ) + { + qWarning() << "Failed to unzip resolver. Ooops."; + return QString(); + } + + return resolverDir.absolutePath(); +} + + +bool +TomahawkUtils::unzipFileInFolder( const QString &zipFileName, const QDir &folder ) +{ + Q_ASSERT( !zipFileName.isEmpty() ); + Q_ASSERT( folder.exists() ); + + QuaZip zipFile( zipFileName ); + if ( !zipFile.open( QuaZip::mdUnzip ) ) + { + qWarning() << "Failed to QuaZip open:" << zipFile.getZipError(); + return false; + } + + if ( !zipFile.goToFirstFile() ) + { + tLog() << "Failed to go to first file in zip archive: " << zipFile.getZipError(); + return false; + } + + tDebug() << "Unzipping files to:" << folder.absolutePath(); QuaZipFile fileInZip( &zipFile ); do @@ -799,23 +815,21 @@ extractScriptPayload( const QString& filename, const QString& resolverId ) continue; } - QFile out( resolverDir.absoluteFilePath( fileInZip.getActualFileName() ) ); + QFile out( folder.absoluteFilePath( fileInZip.getActualFileName() ) ); + // make dir if there is one needed 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 ); + folder.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; + tLog() << "Failed to open zip extract file:" << out.errorString() << info.name; continue; } @@ -826,17 +840,50 @@ extractScriptPayload( const QString& filename, const QString& resolverId ) } while ( zipFile.goToNextFile() ); - return resolverDir.absolutePath(); + return true; } -#if !defined(Q_OS_MAC) // && !defined(Q_OS_WIN) void extractBinaryResolver( const QString& zipFilename, const QString& resolverId, QObject* ) { +#if !defined(Q_OS_MAC) && !defined (Q_OS_WIN) + Q_ASSERT( false ); + qWarning() << "NO SUPPORT YET FOR LINUX BINARY RESOLVERS!"; + return; +#endif + + // Unzip the file. + QFileInfo info( zipFilename ); + QDir tmpDir = QDir::tempPath(); + if ( !tmpDir.mkdir( info.baseName() ) ) + { + qWarning() << "Failed to create temporary directory to unzip in:" << tmpDir.absolutePath(); + return; + } + tmpDir.cd( info.baseName() ); + TomahawkUtils::unzipFileInFolder( info.absoluteFilePath(), tmpDir ); + + // Platform-specific handling of resolver payload now. We know it's good and we unzipped it +#ifdef Q_OS_MAC + // On OSX it just contains 1 file, the resolver executable itself. For now. We just copy it to + // the Tomahawk.app/Contents/MacOS/ folder alongside the Tomahawk executable. + const QString dest = QCoreApplication::applicationDirPath(); + // Find the filename + const QDir toList( tmpDir.absolutePath() ); + const QStringList files = toList.entryList( QStringList(), QDir::Files ); + Q_ASSERT( files.size() == 1 ); + + const QString src = toList.absoluteFilePath( files.first() ); + qDebug() << "OS X: Copying binary resolver from to:" << src << dest; + + copyWithAuthentication( src, dest, 0 ); +#elif Q_OS_WIN +#endif + // No support for binary resolvers on linux! Shouldn't even have been allowed to see/install.. Q_ASSERT( false ); } -#endif + } // ns diff --git a/src/libtomahawk/utils/TomahawkUtils.h b/src/libtomahawk/utils/TomahawkUtils.h index 93f73cc5d..83441a3fd 100644 --- a/src/libtomahawk/utils/TomahawkUtils.h +++ b/src/libtomahawk/utils/TomahawkUtils.h @@ -139,11 +139,16 @@ namespace TomahawkUtils DLLEXPORT bool verifyFile( const QString& filePath, const QString& signature ); DLLEXPORT QString extractScriptPayload( const QString& filename, const QString& resolverId ); + DLLEXPORT bool unzipFileInFolder( const QString& zipFileName, const QDir& folder ); + // 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 ); + // Used by the above, not exported + void copyWithAuthentication( const QString& srcFile, const QDir dest, QObject* receiver ); + /** * 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, diff --git a/src/libtomahawk/utils/TomahawkUtils_Mac.mm b/src/libtomahawk/utils/TomahawkUtils_Mac.mm index 5bb6558e5..4c22f2589 100644 --- a/src/libtomahawk/utils/TomahawkUtils_Mac.mm +++ b/src/libtomahawk/utils/TomahawkUtils_Mac.mm @@ -21,6 +21,7 @@ #include "TomahawkUtils_Mac.h" #include "mac/FileHelpers.h" +#include #include #import @@ -41,12 +42,14 @@ - (void)moveFinished { - QMetaObject::invokeMethod(receiver, "installSucceeded", Qt::DirectConnection, Q_ARG(QString, path)); + if ( receiver ) + QMetaObject::invokeMethod(receiver, "installSucceeded", Qt::DirectConnection, Q_ARG(QString, path)); } - (void)moveFailedWithError:(NSError *)error { - QMetaObject::invokeMethod(receiver, "installFailed", Qt::DirectConnection); + if ( receiver ) + QMetaObject::invokeMethod(receiver, "installFailed", Qt::DirectConnection); } @end @@ -58,35 +61,27 @@ bringToFront() { [NSApp activateIgnoringOtherApps:YES]; } - void -extractBinaryResolver( const QString& zipFilename, const QString& resolverId, QObject* receiver ) +copyWithAuthentication( const QString& srcFile, const QDir dest, 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 - */ + /** + On OS X, we have to do the following: + 1) Authenticate to be able to have write access to the /Applications folder + 2) Copy file to dest + 5) Call result slots on receiver object + */ MoveDelegate* del = [[MoveDelegate alloc] init]; [del setReceiver: receiver]; + [del setMoveTo: dest.absolutePath()]; - // 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; - } + const QFileInfo info( srcFile ); + const QString destPath = dest.absoluteFilePath( info.fileName() ); - qDebug() << "Using temporary directory:" << [tempDir absoluteString]; - - -// [del setMoveTo: to]; + NSString* src = [[NSString alloc] initWithBytes: srcFile.toUtf8() length: srcFile.length() encoding: NSUTF8StringEncoding]; + NSString* destStr = [[NSString alloc] initWithBytes: destPath.toUtf8() length: destPath.length() encoding: NSUTF8StringEncoding]; + [FileHelpers moveFile:src to:destStr withDelegate:del]; } + }