mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-07-31 19:30:21 +02:00
Merge remote-tracking branch 'origin/master' into spotifyplaylists
Conflicts: admin/mac/macdeploy.py
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
<<<<<<< HEAD
|
||||||
# This file is part of Tomahawk.
|
# This file is part of Tomahawk.
|
||||||
# It was inspired in large part by the macdeploy script in Clementine.
|
# It was inspired in large part by the macdeploy script in Clementine.
|
||||||
#
|
#
|
||||||
@@ -249,7 +250,7 @@ frameworks_dir = os.path.join(bundle_dir, 'Contents', 'Frameworks')
|
|||||||
commands.append(['mkdir', '-p', frameworks_dir])
|
commands.append(['mkdir', '-p', frameworks_dir])
|
||||||
resources_dir = os.path.join(bundle_dir, 'Contents', 'Resources')
|
resources_dir = os.path.join(bundle_dir, 'Contents', 'Resources')
|
||||||
commands.append(['mkdir', '-p', resources_dir])
|
commands.append(['mkdir', '-p', resources_dir])
|
||||||
plugins_dir = os.path.join(bundle_dir, 'Contents', 'plugins')
|
plugins_dir = os.path.join(bundle_dir, 'Contents', 'PlugIns')
|
||||||
binary = os.path.join(bundle_dir, 'Contents', 'MacOS', bundle_name)
|
binary = os.path.join(bundle_dir, 'Contents', 'MacOS', bundle_name)
|
||||||
|
|
||||||
fixed_libraries = []
|
fixed_libraries = []
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 8.6 KiB |
@@ -160,7 +160,7 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg
|
|||||||
{
|
{
|
||||||
const QString plid = msg.value( "playlistid" ).toString();
|
const QString plid = msg.value( "playlistid" ).toString();
|
||||||
// We should already be syncing this playlist if we get updates for it
|
// We should already be syncing this playlist if we get updates for it
|
||||||
Q_ASSERT( m_updaters.contains( plid ) );
|
// Q_ASSERT( m_updaters.contains( plid ) );
|
||||||
|
|
||||||
if ( !m_updaters.contains( plid ) )
|
if ( !m_updaters.contains( plid ) )
|
||||||
return;
|
return;
|
||||||
@@ -179,7 +179,7 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg
|
|||||||
{
|
{
|
||||||
const QString plid = msg.value( "playlistid" ).toString();
|
const QString plid = msg.value( "playlistid" ).toString();
|
||||||
// We should already be syncing this playlist if we get updates for it
|
// We should already be syncing this playlist if we get updates for it
|
||||||
Q_ASSERT( m_updaters.contains( plid ) );
|
// Q_ASSERT( m_updaters.contains( plid ) );
|
||||||
|
|
||||||
if ( !m_updaters.contains( plid ) )
|
if ( !m_updaters.contains( plid ) )
|
||||||
return;
|
return;
|
||||||
@@ -187,7 +187,7 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg
|
|||||||
SpotifyPlaylistUpdater* updater = m_updaters[ plid ];
|
SpotifyPlaylistUpdater* updater = m_updaters[ plid ];
|
||||||
Q_ASSERT( updater->sync() );
|
Q_ASSERT( updater->sync() );
|
||||||
|
|
||||||
const QVariantList tracksList = msg.value( "tracks" ).toList();
|
const QVariantList tracksList = msg.value( "trackPositions" ).toList();
|
||||||
const QString newRev = msg.value( "revid" ).toString();
|
const QString newRev = msg.value( "revid" ).toString();
|
||||||
const QString oldRev = msg.value( "oldRev" ).toString();
|
const QString oldRev = msg.value( "oldRev" ).toString();
|
||||||
|
|
||||||
@@ -206,7 +206,7 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg
|
|||||||
SpotifyPlaylistUpdater* updater = m_updaters[ plid ];
|
SpotifyPlaylistUpdater* updater = m_updaters[ plid ];
|
||||||
Q_ASSERT( updater->sync() );
|
Q_ASSERT( updater->sync() );
|
||||||
|
|
||||||
const QVariantList tracksList = msg.value( "tracks" ).toList();
|
const QVariantList tracksList = msg.value( "trackPositions" ).toList();
|
||||||
const QString newRev = msg.value( "revid" ).toString();
|
const QString newRev = msg.value( "revid" ).toString();
|
||||||
const QString oldRev = msg.value( "oldRev" ).toString();
|
const QString oldRev = msg.value( "oldRev" ).toString();
|
||||||
|
|
||||||
|
@@ -40,6 +40,12 @@ SpotifyUpdaterFactory::create( const Tomahawk::playlist_ptr& pl )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( !m_account )
|
||||||
|
{
|
||||||
|
qWarning() << "Found a spotify updater with no spotify account... ignoreing for now!!";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Register the updater with the account
|
// Register the updater with the account
|
||||||
const QString spotifyId = QString( "playlistupdaters/%1" ).arg( pl->guid() );
|
const QString spotifyId = QString( "playlistupdaters/%1" ).arg( pl->guid() );
|
||||||
Q_ASSERT( !spotifyId.isEmpty() );
|
Q_ASSERT( !spotifyId.isEmpty() );
|
||||||
@@ -143,49 +149,53 @@ SpotifyPlaylistUpdater::spotifyTracksAdded( const QVariantList& tracks, int star
|
|||||||
// Q_ASSERT( m_latestRev == oldRev );
|
// Q_ASSERT( m_latestRev == oldRev );
|
||||||
// m_latestRev = newRev;
|
// m_latestRev = newRev;
|
||||||
|
|
||||||
//NOTE: remove 1 from the position, as spotify gives the *newly inserted* position, not the index to insert at
|
if ( startPos > playlist()->entries().size() )
|
||||||
startPos--;
|
startPos = playlist()->entries().size();
|
||||||
|
|
||||||
|
m_plRevisionBeforeUpdate = playlist()->currentrevision();
|
||||||
|
|
||||||
playlist()->insertEntries( queries, startPos, playlist()->currentrevision() );
|
playlist()->insertEntries( queries, startPos, playlist()->currentrevision() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SpotifyPlaylistUpdater::spotifyTracksRemoved( const QVariantList& tracks, const QString& newRev, const QString& oldRev )
|
SpotifyPlaylistUpdater::spotifyTracksRemoved( const QVariantList& trackPositions, const QString& newRev, const QString& oldRev )
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO << "remove tracks in middle of tomahawk playlist, from spotify command!" << tracks << newRev << oldRev;
|
qDebug() << Q_FUNC_INFO << "remove tracks in middle of tomahawk playlist, from spotify command!" << trackPositions << newRev << oldRev;
|
||||||
// Uh oh, dont' want to get out of sync!!
|
// Uh oh, dont' want to get out of sync!!
|
||||||
// Q_ASSERT( m_latestRev == oldRev );
|
// Q_ASSERT( m_latestRev == oldRev );
|
||||||
// m_latestRev = newRev;
|
// m_latestRev = newRev;
|
||||||
|
|
||||||
QList< plentry_ptr > entries = playlist()->entries();
|
QList< plentry_ptr > entries = playlist()->entries();
|
||||||
|
|
||||||
// FIXME UGH have to do a manual lookup for each track we want to remove... any ideas?
|
// Collect list of tracks to remove (can't remove in-place as that might modify the indices)
|
||||||
foreach( const QVariant& blob, tracks )
|
QList<plentry_ptr> toRemove;
|
||||||
|
foreach( const QVariant posV, trackPositions )
|
||||||
{
|
{
|
||||||
const QVariantMap trackMap = blob.toMap();
|
bool ok;
|
||||||
for ( QList<plentry_ptr>::iterator iter = entries.begin(); iter != entries.end(); ++iter )
|
const int pos = posV.toInt( &ok );
|
||||||
|
if ( !ok || pos < 0 || pos >= entries.size() )
|
||||||
{
|
{
|
||||||
const QString trackId = iter->data()->query()->property( "spotifytrackid" ).toString();
|
qWarning() << Q_FUNC_INFO << "Tried to get track position to remove, but either couldn't convert to int, or out of bounds:" << ok << pos << entries.size() << entries << trackPositions;
|
||||||
// easy case, we have a track id on both sides, so we're sure
|
continue;
|
||||||
if ( trackId.isEmpty() && trackId == trackMap.value( "id" ).toString() )
|
|
||||||
{
|
|
||||||
iter = entries.erase( iter );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fuzzy case, check metadata
|
|
||||||
if ( iter->data()->query()->track() == trackMap[ "track" ].toString() &&
|
|
||||||
iter->data()->query()->artist() == trackMap[ "artist" ].toString() &&
|
|
||||||
iter->data()->query()->album() == trackMap[ "album" ].toString() )
|
|
||||||
{
|
|
||||||
iter = entries.erase( iter );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toRemove << entries.at(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "We were asked to delete:" << tracks.size() << "tracks from the playlist, and we deleted:" << ( playlist()->entries().size() - entries.size() );
|
|
||||||
|
// Now remove them all
|
||||||
|
foreach( const plentry_ptr& torm, toRemove )
|
||||||
|
entries.removeAll( torm );
|
||||||
|
|
||||||
|
|
||||||
|
m_plRevisionBeforeUpdate = playlist()->currentrevision();
|
||||||
|
|
||||||
|
qDebug() << "We were asked to delete:" << trackPositions.size() << "tracks from the playlist, and we deleted:" << ( playlist()->entries().size() - entries.size() );
|
||||||
|
if ( trackPositions.size() != ( playlist()->entries().size() - entries.size() ) )
|
||||||
|
qWarning() << "========================= Failed to delete all the tracks we were asked for!! Didn't find some indicesss... ===================";
|
||||||
|
|
||||||
|
|
||||||
playlist()->createNewRevision( uuid(), playlist()->currentrevision(), entries );
|
playlist()->createNewRevision( uuid(), playlist()->currentrevision(), entries );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,6 +210,12 @@ SpotifyPlaylistUpdater::spotifyTracksMoved( const QVariantList& tracks, const QS
|
|||||||
void
|
void
|
||||||
SpotifyPlaylistUpdater::tomahawkTracksInserted( const QList< plentry_ptr >& tracks, int pos )
|
SpotifyPlaylistUpdater::tomahawkTracksInserted( const QList< plentry_ptr >& tracks, int pos )
|
||||||
{
|
{
|
||||||
|
if ( playlist()->currentrevision() == m_plRevisionBeforeUpdate )
|
||||||
|
{
|
||||||
|
// We did the insert. Don't get in an infinite loop!
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Notify the resolver that we've updated
|
// Notify the resolver that we've updated
|
||||||
qDebug() << Q_FUNC_INFO << "updating spotify resolver with inserted tracks at:" << pos << tracks;
|
qDebug() << Q_FUNC_INFO << "updating spotify resolver with inserted tracks at:" << pos << tracks;
|
||||||
QVariantMap msg;
|
QVariantMap msg;
|
||||||
|
@@ -74,6 +74,7 @@ private:
|
|||||||
|
|
||||||
Tomahawk::Accounts::SpotifyAccount* m_spotify;
|
Tomahawk::Accounts::SpotifyAccount* m_spotify;
|
||||||
QString m_latestRev, m_spotifyId;
|
QString m_latestRev, m_spotifyId;
|
||||||
|
QString m_plRevisionBeforeUpdate;
|
||||||
bool m_sync;
|
bool m_sync;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -43,9 +43,10 @@ ACLRegistry::ACLRegistry( QObject* parent )
|
|||||||
: QObject( parent )
|
: QObject( parent )
|
||||||
{
|
{
|
||||||
s_instance = this;
|
s_instance = this;
|
||||||
qRegisterMetaType< ACLRegistry::ACL >("ACLRegistry::ACL");
|
qRegisterMetaType< ACLRegistry::ACL >( "ACLRegistry::ACL" );
|
||||||
|
qRegisterMetaType< ACLRegistry::User >( "ACLRegistry::User" );
|
||||||
|
|
||||||
m_cache = TomahawkSettings::instance()->aclEntries();
|
load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -55,174 +56,77 @@ ACLRegistry::~ACLRegistry()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ACLRegistry::isAuthorizedPeer( const QString& dbid, ACLRegistry::ACL globalType, const QString &username )
|
ACLRegistry::isAuthorizedUser( const QString& dbid, const QString &username, ACLRegistry::ACL globalType )
|
||||||
{
|
{
|
||||||
if ( QThread::currentThread() != TOMAHAWK_APPLICATION::instance()->thread() )
|
if ( QThread::currentThread() != TOMAHAWK_APPLICATION::instance()->thread() )
|
||||||
{
|
{
|
||||||
emit aclResult( dbid, globalType );
|
emit aclResult( dbid, username, globalType );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Current cache keys =" << m_cache.keys();
|
bool found = false;
|
||||||
if( m_cache.contains( dbid ) )
|
QMutableListIterator< ACLRegistry::User > i( m_cache );
|
||||||
|
while ( i.hasNext() )
|
||||||
{
|
{
|
||||||
QVariantHash peerHash = m_cache[ dbid ].toHash();
|
ACLRegistry::User user = i.next();
|
||||||
if( peerHash.contains( "global" ) )
|
foreach ( QString knowndbid, user.knownDbids )
|
||||||
{
|
{
|
||||||
registerAlias( dbid, username );
|
if ( dbid == knowndbid )
|
||||||
emit aclResult( dbid, ACLRegistry::ACL( peerHash[ "global" ].toInt() ) );
|
{
|
||||||
|
if ( !user.knownAccountIds.contains( username ) )
|
||||||
|
user.knownAccountIds.append( username );
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ( QString knownaccountid, user.knownAccountIds )
|
||||||
|
{
|
||||||
|
if ( username == knownaccountid )
|
||||||
|
{
|
||||||
|
if ( !user.knownDbids.contains( dbid ) )
|
||||||
|
user.knownDbids.append( dbid );
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( found )
|
||||||
|
{
|
||||||
|
emit aclResult( dbid, username, user.acl );
|
||||||
|
i.setValue( user );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// User was not found, create a new user entry
|
||||||
|
ACLRegistry::User user;
|
||||||
|
user.knownDbids.append( dbid );
|
||||||
|
user.knownAccountIds.append( username );
|
||||||
|
if ( globalType != ACLRegistry::NotFound )
|
||||||
|
user.acl = globalType;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ACLRegistry::ACL acl = globalType;
|
||||||
|
tDebug( LOGVERBOSE ) << "ACL is intially" << acl;
|
||||||
|
#ifndef ENABLE_HEADLESS
|
||||||
|
acl = getUserDecision( username );
|
||||||
|
tDebug( LOGVERBOSE ) << "after getUserDecision acl is" << acl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( acl == ACLRegistry::NotFound )
|
||||||
|
{
|
||||||
|
emit aclResult( dbid, username, acl );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( globalType == ACLRegistry::NotFound )
|
user.acl = acl;
|
||||||
{
|
|
||||||
emit aclResult( dbid, globalType );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
peerHash[ "global" ] = int( globalType );
|
|
||||||
m_cache[ dbid ] = peerHash;
|
|
||||||
save();
|
|
||||||
registerAlias( dbid, username );
|
|
||||||
emit aclResult( dbid, globalType );
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ACLRegistry::ACL acl = globalType;
|
m_cache.append( user );
|
||||||
tDebug( LOGVERBOSE ) << "ACL is intially" << acl;
|
emit aclResult( dbid, username, user.acl );
|
||||||
#ifndef ENABLE_HEADLESS
|
|
||||||
acl = getUserDecision( username );
|
|
||||||
tDebug( LOGVERBOSE ) << "after getUserDecision acl is" << acl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( acl == ACLRegistry::NotFound || acl == ACLRegistry::AllowOnce || acl == ACLRegistry::DenyOnce )
|
|
||||||
{
|
|
||||||
emit aclResult( dbid, acl );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantHash peerHash;
|
|
||||||
peerHash[ "global" ] = int( acl );
|
|
||||||
m_cache[ dbid ] = peerHash;
|
|
||||||
save();
|
|
||||||
registerAlias( dbid, username );
|
|
||||||
emit aclResult( dbid, acl );
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ACLRegistry::registerPeer( const QString& dbid, ACLRegistry::ACL globalType, const QString &username )
|
|
||||||
{
|
|
||||||
if ( QThread::currentThread() != TOMAHAWK_APPLICATION::instance()->thread() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ( globalType == ACLRegistry::NotFound || globalType == ACLRegistry::DenyOnce || globalType == ACLRegistry::AllowOnce )
|
|
||||||
return;
|
|
||||||
|
|
||||||
QVariantHash peerHash;
|
|
||||||
if ( m_cache.contains( dbid ) )
|
|
||||||
peerHash = m_cache[ dbid ].toHash();
|
|
||||||
peerHash[ "global" ] = int( globalType );
|
|
||||||
m_cache[ dbid ] = peerHash;
|
|
||||||
save();
|
|
||||||
registerAlias( dbid, username );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QPair< QString, ACLRegistry::ACL >
|
|
||||||
ACLRegistry::isAuthorizedUser( const QString &username, ACLRegistry::ACL globalType )
|
|
||||||
{
|
|
||||||
if ( QThread::currentThread() != TOMAHAWK_APPLICATION::instance()->thread() )
|
|
||||||
return QPair< QString, ACLRegistry::ACL >( QString(), ACLRegistry::NotFound );
|
|
||||||
|
|
||||||
qDebug() << "Current cache keys =" << m_cache.keys();
|
|
||||||
foreach ( QString dbid, m_cache.keys() )
|
|
||||||
{
|
|
||||||
// qDebug() << "Looking up dbid";
|
|
||||||
QVariantHash peerHash = m_cache[ dbid ].toHash();
|
|
||||||
if ( !peerHash.contains( "usernames" ) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ( !peerHash[ "usernames" ].toStringList().contains( username ) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ( globalType != ACLRegistry::NotFound )
|
|
||||||
{
|
|
||||||
peerHash[ "global" ] = int( globalType );
|
|
||||||
m_cache[ dbid ] = peerHash;
|
|
||||||
save();
|
|
||||||
return QPair< QString, ACLRegistry::ACL >( dbid, globalType );
|
|
||||||
}
|
|
||||||
|
|
||||||
return QPair< QString, ACLRegistry::ACL >( dbid, ACLRegistry::ACL( peerHash[ "global" ].toInt() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
return QPair< QString, ACLRegistry::ACL >( QString(), ACLRegistry::NotFound );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ACLRegistry::registerAlias( const QString& dbid, const QString &username )
|
|
||||||
{
|
|
||||||
if ( QThread::currentThread() != TOMAHAWK_APPLICATION::instance()->thread() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ( dbid.isEmpty() || username.isEmpty() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ( !m_cache.contains( dbid ) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
QVariantHash peerHash = m_cache[ dbid ].toHash();
|
|
||||||
if ( !peerHash.contains( "usernames" ) )
|
|
||||||
peerHash[ "usernames" ] = QStringList( username );
|
|
||||||
else if ( !peerHash[ "usernames" ].toStringList().contains( username ) )
|
|
||||||
peerHash[ "usernames" ] = peerHash[ "usernames" ].toStringList() + QStringList( username );
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_cache[ dbid ] = peerHash;
|
|
||||||
save();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ACLRegistry::ACL
|
|
||||||
// ACLRegistry::isAuthorizedPath( const QString& dbid, const QString& path )
|
|
||||||
// {
|
|
||||||
// QMutexLocker locker( &m_cacheMutex );
|
|
||||||
//
|
|
||||||
// if( !m_cache.contains( dbid ) )
|
|
||||||
// return ACLRegistry::NotFound;
|
|
||||||
//
|
|
||||||
// QHash< QString, ACL > peerHash = m_cache[dbid];
|
|
||||||
// if( !peerHash.contains( path ) )
|
|
||||||
// {
|
|
||||||
// if( peerHash.contains( "global" ) )
|
|
||||||
// return peerHash["global"];
|
|
||||||
// else
|
|
||||||
// return ACLRegistry::Deny;
|
|
||||||
// }
|
|
||||||
// return peerHash[path];
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// void
|
|
||||||
// ACLRegistry::authorizePath( const QString& dbid, const QString& path, ACLRegistry::ACL type )
|
|
||||||
// {
|
|
||||||
// TomahawkSettings *s = TomahawkSettings::instance();
|
|
||||||
// if( !s->scannerPaths().contains( path ) )
|
|
||||||
// {
|
|
||||||
// qDebug() << "path selected is not in our scanner path!";
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// QMutexLocker locker( &m_cacheMutex );
|
|
||||||
// QHash< QString, ACLRegistry::ACL > peerHash;
|
|
||||||
// if ( m_cache.contains( dbid ) )
|
|
||||||
// peerHash = m_cache[dbid];
|
|
||||||
// peerHash[path] = type;
|
|
||||||
// m_cache[dbid] = peerHash;
|
|
||||||
// }
|
|
||||||
|
|
||||||
#ifndef ENABLE_HEADLESS
|
#ifndef ENABLE_HEADLESS
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
@@ -230,14 +134,13 @@ ACLRegistry::registerAlias( const QString& dbid, const QString &username )
|
|||||||
ACLRegistry::ACL
|
ACLRegistry::ACL
|
||||||
ACLRegistry::getUserDecision( const QString &username )
|
ACLRegistry::getUserDecision( const QString &username )
|
||||||
{
|
{
|
||||||
|
return ACLRegistry::Stream;
|
||||||
QMessageBox msgBox;
|
QMessageBox msgBox;
|
||||||
msgBox.setIcon( QMessageBox::Question );
|
msgBox.setIcon( QMessageBox::Question );
|
||||||
msgBox.setText( tr( "Connect to Peer?" ) );
|
msgBox.setText( tr( "Connect to Peer?" ) );
|
||||||
msgBox.setInformativeText( tr( "Another Tomahawk instance that claims to be owned by %1 is attempting to connect to you. Select whether to allow or deny this connection.\n\nRemember: Only allow peers to connect if you trust who they are and if you have the legal right for them to stream music from you.").arg( username ) );
|
msgBox.setInformativeText( tr( "Another Tomahawk instance that claims to be owned by %1 is attempting to connect to you. Select whether to allow or deny this connection.\n\nRemember: Only allow peers to connect if you trust who they are and if you have the legal right for them to stream music from you.").arg( username ) );
|
||||||
QPushButton *denyButton = msgBox.addButton( tr( "Deny" ), QMessageBox::HelpRole );
|
QPushButton *denyButton = msgBox.addButton( tr( "Deny" ), QMessageBox::YesRole );
|
||||||
QPushButton *alwaysDenyButton = msgBox.addButton( tr( "Always Deny" ), QMessageBox::YesRole );
|
QPushButton *allowButton = msgBox.addButton( tr( "Allow" ), QMessageBox::ActionRole );
|
||||||
QPushButton *allowButton = msgBox.addButton( tr( "Allow" ), QMessageBox::NoRole );
|
|
||||||
QPushButton *alwaysAllowButton = msgBox.addButton( tr( "Always Allow" ), QMessageBox::ActionRole );
|
|
||||||
|
|
||||||
msgBox.setDefaultButton( allowButton );
|
msgBox.setDefaultButton( allowButton );
|
||||||
msgBox.setEscapeButton( denyButton );
|
msgBox.setEscapeButton( denyButton );
|
||||||
@@ -245,13 +148,9 @@ ACLRegistry::getUserDecision( const QString &username )
|
|||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
|
|
||||||
if( msgBox.clickedButton() == denyButton )
|
if( msgBox.clickedButton() == denyButton )
|
||||||
return ACLRegistry::DenyOnce;
|
|
||||||
else if( msgBox.clickedButton() == alwaysDenyButton )
|
|
||||||
return ACLRegistry::Deny;
|
return ACLRegistry::Deny;
|
||||||
else if( msgBox.clickedButton() == allowButton )
|
else if( msgBox.clickedButton() == allowButton )
|
||||||
return ACLRegistry::AllowOnce;
|
return ACLRegistry::Stream;
|
||||||
else if( msgBox.clickedButton() == alwaysAllowButton )
|
|
||||||
return ACLRegistry::Allow;
|
|
||||||
|
|
||||||
//How could we get here?
|
//How could we get here?
|
||||||
tDebug( LOGVERBOSE ) << "ERROR: returning NotFound";
|
tDebug( LOGVERBOSE ) << "ERROR: returning NotFound";
|
||||||
@@ -261,8 +160,26 @@ ACLRegistry::getUserDecision( const QString &username )
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ACLRegistry::load()
|
||||||
|
{
|
||||||
|
QVariantList entryList = TomahawkSettings::instance()->aclEntries();
|
||||||
|
foreach ( QVariant entry, entryList )
|
||||||
|
{
|
||||||
|
if ( !entry.isValid() || !entry.canConvert< ACLRegistry::User >() )
|
||||||
|
continue;
|
||||||
|
ACLRegistry::User entryUser = entry.value< ACLRegistry::User >();
|
||||||
|
m_cache.append( entryUser );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ACLRegistry::save()
|
ACLRegistry::save()
|
||||||
{
|
{
|
||||||
TomahawkSettings::instance()->setAclEntries( m_cache );
|
QVariantList entryList;
|
||||||
|
foreach ( ACLRegistry::User user, m_cache )
|
||||||
|
entryList.append( QVariant::fromValue< ACLRegistry::User >( user ) );
|
||||||
|
TomahawkSettings::instance()->setAclEntries( entryList );
|
||||||
}
|
}
|
@@ -39,46 +39,35 @@ public:
|
|||||||
static ACLRegistry* instance();
|
static ACLRegistry* instance();
|
||||||
|
|
||||||
enum ACL {
|
enum ACL {
|
||||||
Allow = 0,
|
NotFound = 0,
|
||||||
Deny = 1,
|
Deny = 1,
|
||||||
NotFound = 2,
|
Read = 2,
|
||||||
AllowOnce = 3,
|
Stream = 3
|
||||||
DenyOnce = 4
|
};
|
||||||
|
|
||||||
|
struct User {
|
||||||
|
QString uuid;
|
||||||
|
QStringList knownDbids;
|
||||||
|
QStringList knownAccountIds;
|
||||||
|
ACL acl;
|
||||||
|
|
||||||
|
User()
|
||||||
|
: uuid( QUuid::createUuid().toString() )
|
||||||
|
{}
|
||||||
|
|
||||||
|
User( QString p_uuid, QStringList p_knownDbids, QStringList p_knownAccountIds, ACL p_acl )
|
||||||
|
: uuid( p_uuid )
|
||||||
|
, knownDbids( p_knownDbids )
|
||||||
|
, knownAccountIds( p_knownAccountIds )
|
||||||
|
, acl( p_acl )
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
ACLRegistry( QObject *parent = 0 );
|
ACLRegistry( QObject *parent = 0 );
|
||||||
~ACLRegistry();
|
~ACLRegistry();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Registers the global ACL value for this peer
|
|
||||||
*
|
|
||||||
* @param dbid DBID of peer
|
|
||||||
* @param globalType Global ACL to use for this peer. ACLRegistry::NotFound is invalid and will return immediately.
|
|
||||||
* @param username If not empty, will store the given username along with the new ACL value. Defaults to QString().
|
|
||||||
* @return void
|
|
||||||
**/
|
|
||||||
void registerPeer( const QString &dbid, ACLRegistry::ACL globalType, const QString &username = QString() );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks if peer is authorized, using the username. Optionally, can change authorization of the peer, but only if the peer is found.
|
|
||||||
*
|
|
||||||
* @param username Username for the peer
|
|
||||||
* @param globalType Global ACL to store if peer is found; if ACLRegistry::NotFound, does not change the ACL. Defaults to ACLRegistry::NotFound.
|
|
||||||
* @return QPair< QString, ACLRegistry::ACL >
|
|
||||||
**/
|
|
||||||
QPair< QString, ACLRegistry::ACL > isAuthorizedUser( const QString &username, ACLRegistry::ACL globalType = ACLRegistry::NotFound );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Registers an alias for a known peer. If you do not know the DBID, you can retrieve it via isAuthorizedUser first.
|
|
||||||
*
|
|
||||||
* @param dbid DBID of peer
|
|
||||||
* @param username Username of the peer to be added to the entry
|
|
||||||
* @return void
|
|
||||||
**/
|
|
||||||
void registerAlias( const QString &dbid, const QString &username );
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void aclResult( QString nodeid, ACLRegistry::ACL peerStatus );
|
void aclResult( QString nodeid, QString username, ACLRegistry::ACL peerStatus );
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/**
|
/**
|
||||||
@@ -89,16 +78,13 @@ public slots:
|
|||||||
* @param username If not empty, will store the given username along with the new ACL value. Defaults to QString().
|
* @param username If not empty, will store the given username along with the new ACL value. Defaults to QString().
|
||||||
* @return ACLRegistry::ACL
|
* @return ACLRegistry::ACL
|
||||||
**/
|
**/
|
||||||
void isAuthorizedPeer( const QString &dbid, ACLRegistry::ACL globalType = ACLRegistry::NotFound, const QString &username = QString() );
|
void isAuthorizedUser( const QString &dbid, const QString &username, ACLRegistry::ACL globalType = ACLRegistry::NotFound );
|
||||||
|
|
||||||
|
|
||||||
#ifndef ENABLE_HEADLESS
|
#ifndef ENABLE_HEADLESS
|
||||||
ACLRegistry::ACL getUserDecision( const QString &username );
|
ACLRegistry::ACL getUserDecision( const QString &username );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ACLRegistry::ACL isAuthorizedPath( const QString &dbid, const QString &path );
|
|
||||||
// void authorizePath( const QString &dbid, const QString &path, ACLRegistry::ACL type );
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* @brief Saves the cache.
|
* @brief Saves the cache.
|
||||||
@@ -107,9 +93,14 @@ private:
|
|||||||
**/
|
**/
|
||||||
void save();
|
void save();
|
||||||
|
|
||||||
QVariantHash m_cache;
|
void load();
|
||||||
|
|
||||||
|
QList< ACLRegistry::User > m_cache;
|
||||||
|
|
||||||
static ACLRegistry* s_instance;
|
static ACLRegistry* s_instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE( ACLRegistry::ACL );
|
||||||
|
Q_DECLARE_METATYPE( ACLRegistry::User );
|
||||||
|
|
||||||
#endif // TOMAHAWK_ACLREGISTRY_H
|
#endif // TOMAHAWK_ACLREGISTRY_H
|
||||||
|
@@ -199,20 +199,20 @@ Connection::checkACL()
|
|||||||
|
|
||||||
QString nodeid = property( "nodeid" ).toString();
|
QString nodeid = property( "nodeid" ).toString();
|
||||||
tDebug( LOGVERBOSE ) << "Checking ACL for" << name();
|
tDebug( LOGVERBOSE ) << "Checking ACL for" << name();
|
||||||
connect( ACLRegistry::instance(), SIGNAL( aclResult( QString, ACLRegistry::ACL ) ), this, SLOT( checkACLResult( QString, ACLRegistry::ACL ) ), Qt::QueuedConnection );
|
connect( ACLRegistry::instance(), SIGNAL( aclResult( QString, QString, ACLRegistry::ACL ) ), this, SLOT( checkACLResult( QString, QString, ACLRegistry::ACL ) ), Qt::QueuedConnection );
|
||||||
QMetaObject::invokeMethod( ACLRegistry::instance(), "isAuthorizedPeer", Qt::QueuedConnection, Q_ARG( QString, nodeid ), Q_ARG( ACLRegistry::ACL, ACLRegistry::NotFound ), Q_ARG( QString, name() ) );
|
QMetaObject::invokeMethod( ACLRegistry::instance(), "isAuthorizedUser", Qt::QueuedConnection, Q_ARG( QString, nodeid ), Q_ARG( QString, name() ), Q_ARG( ACLRegistry::ACL, ACLRegistry::NotFound ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Connection::checkACLResult( const QString &nodeid, ACLRegistry::ACL peerStatus )
|
Connection::checkACLResult( const QString &nodeid, const QString &username, ACLRegistry::ACL peerStatus )
|
||||||
{
|
{
|
||||||
if ( nodeid != property( "nodeid" ).toString() )
|
if ( nodeid != property( "nodeid" ).toString() || username != name() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
disconnect( ACLRegistry::instance(), SIGNAL( aclResult( QString, ACLRegistry::ACL ) ) );
|
disconnect( ACLRegistry::instance(), SIGNAL( aclResult( QString, QString, ACLRegistry::ACL ) ) );
|
||||||
tDebug( LOGVERBOSE ) << "ACL status is" << peerStatus;
|
tDebug( LOGVERBOSE ) << "ACL status is" << peerStatus;
|
||||||
if ( peerStatus == ACLRegistry::Allow || peerStatus == ACLRegistry::AllowOnce )
|
if ( peerStatus == ACLRegistry::Stream )
|
||||||
{
|
{
|
||||||
QTimer::singleShot( 0, this, SLOT( doSetup() ) );
|
QTimer::singleShot( 0, this, SLOT( doSetup() ) );
|
||||||
return;
|
return;
|
||||||
|
@@ -120,7 +120,7 @@ private slots:
|
|||||||
void readyRead();
|
void readyRead();
|
||||||
void doSetup();
|
void doSetup();
|
||||||
void checkACL();
|
void checkACL();
|
||||||
void checkACLResult( const QString &id, ACLRegistry::ACL peerStatus );
|
void checkACLResult( const QString &nodeid, const QString &username, ACLRegistry::ACL peerStatus );
|
||||||
void authCheckTimeout();
|
void authCheckTimeout();
|
||||||
void bytesWritten( qint64 );
|
void bytesWritten( qint64 );
|
||||||
void calcStats();
|
void calcStats();
|
||||||
|
@@ -316,6 +316,10 @@ Playlist::createNewRevision( const QString& newrev, const QString& oldrev, const
|
|||||||
foreach( const plentry_ptr& p, entries )
|
foreach( const plentry_ptr& p, entries )
|
||||||
orderedguids << p->guid();
|
orderedguids << p->guid();
|
||||||
|
|
||||||
|
qDebug() << "INSERTING ORDERED GUIDS:" << orderedguids << "and with new entries:";
|
||||||
|
foreach( const plentry_ptr& p, added )
|
||||||
|
qDebug() << p->guid();
|
||||||
|
|
||||||
// source making the change (local user in this case)
|
// source making the change (local user in this case)
|
||||||
source_ptr author = SourceList::instance()->getLocal();
|
source_ptr author = SourceList::instance()->getLocal();
|
||||||
// command writes new rev to DB and calls setRevision, which emits our signal
|
// command writes new rev to DB and calls setRevision, which emits our signal
|
||||||
@@ -396,20 +400,38 @@ Playlist::setNewRevision( const QString& rev,
|
|||||||
// existing ones, and the ones that have been added
|
// existing ones, and the ones that have been added
|
||||||
QMap<QString, plentry_ptr> entriesmap;
|
QMap<QString, plentry_ptr> entriesmap;
|
||||||
foreach ( const plentry_ptr& p, m_entries )
|
foreach ( const plentry_ptr& p, m_entries )
|
||||||
|
{
|
||||||
|
qDebug() << p->guid() << p->query()->track() << p->query()->artist();
|
||||||
entriesmap.insert( p->guid(), p );
|
entriesmap.insert( p->guid(), p );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QList<plentry_ptr> entries;
|
QList<plentry_ptr> entries;
|
||||||
|
qDebug() << "Going through neworderedguids:" << neworderedguids << neworderedguids.size();
|
||||||
foreach ( const QString& id, neworderedguids )
|
foreach ( const QString& id, neworderedguids )
|
||||||
{
|
{
|
||||||
if ( entriesmap.contains( id ) )
|
if ( entriesmap.contains( id ) )
|
||||||
{
|
{
|
||||||
|
qDebug() << "Adding original entry to entries:" << id;
|
||||||
entries.append( entriesmap.value( id ) );
|
entries.append( entriesmap.value( id ) );
|
||||||
}
|
}
|
||||||
else if ( addedmap.contains( id ) )
|
else if ( addedmap.contains( id ) )
|
||||||
{
|
{
|
||||||
|
qDebug() << "Adding new entry to entries:" << id << addedmap.value( id );
|
||||||
|
if( ! addedmap.value( id ).isNull() ) qDebug() << addedmap.value( id )->query()->track() << addedmap.value( id )->query()->artist();
|
||||||
entries.append( addedmap.value( id ) );
|
entries.append( addedmap.value( id ) );
|
||||||
if ( is_newest_rev )
|
if ( is_newest_rev )
|
||||||
m_entries.append( addedmap.value( id ) );
|
{
|
||||||
|
// We want to insert the new entries into the appropriate place in m_entries, not just at the end. so find the index in neworderedguids, and use that. since we go from 0,
|
||||||
|
// it should be valid
|
||||||
|
int insertIdx = neworderedguids.indexOf( id );
|
||||||
|
if ( insertIdx < 0 || insertIdx > m_entries.size() )
|
||||||
|
{
|
||||||
|
qWarning() << "Trying to insert new track in a playlist, but beyond the end! Appending at end to be safe";
|
||||||
|
insertIdx = m_entries.size();
|
||||||
|
}
|
||||||
|
m_entries.insert( insertIdx, addedmap.value( id ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -423,6 +445,7 @@ Playlist::setNewRevision( const QString& rev,
|
|||||||
Q_ASSERT( false ); // XXX
|
Q_ASSERT( false ); // XXX
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
qDebug() << "and got:" << entries.size() << entries << m_entries.size() << m_entries;
|
||||||
|
|
||||||
PlaylistRevision pr;
|
PlaylistRevision pr;
|
||||||
pr.oldrevisionguid = m_currentrevision;
|
pr.oldrevisionguid = m_currentrevision;
|
||||||
@@ -535,16 +558,24 @@ Playlist::insertEntries( const QList< query_ptr >& queries, const int position,
|
|||||||
QList<plentry_ptr> toInsert = entriesFromQueries( queries, true );
|
QList<plentry_ptr> toInsert = entriesFromQueries( queries, true );
|
||||||
QList<plentry_ptr> entries = m_entries;
|
QList<plentry_ptr> entries = m_entries;
|
||||||
|
|
||||||
Q_ASSERT( position < m_entries.size() );
|
Q_ASSERT( position <= m_entries.size() );
|
||||||
if ( position >= m_entries.size() )
|
if ( position > m_entries.size() )
|
||||||
{
|
{
|
||||||
qWarning() << "ERROR trying to insert tracks past end of playlist! Appending!!";
|
qWarning() << "ERROR trying to insert tracks past end of playlist! Appending!!";
|
||||||
addEntries( queries, oldrev );
|
addEntries( queries, oldrev );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( QList< plentry_ptr >::iterator iter = toInsert.end(); iter != toInsert.begin(); iter-- )
|
qDebug() << "inserting entries. GUIDs before:";
|
||||||
entries.insert( position, *iter );
|
foreach( const plentry_ptr& p, entries )
|
||||||
|
qDebug() << p->guid();
|
||||||
|
|
||||||
|
for ( int i = toInsert.size()-1; i >= 0; --i )
|
||||||
|
entries.insert( position, toInsert.at(i) );
|
||||||
|
|
||||||
|
qDebug() << "inserting entries. GUIDs AFTER:";
|
||||||
|
foreach( const plentry_ptr& p, entries )
|
||||||
|
qDebug() << p->guid();
|
||||||
|
|
||||||
const int prevSize = m_entries.size();
|
const int prevSize = m_entries.size();
|
||||||
qDebug() << "Done inserting playlist entries in the middle of the playlist! Committing...";
|
qDebug() << "Done inserting playlist entries in the middle of the playlist! Committing...";
|
||||||
|
@@ -54,7 +54,6 @@ PlaylistUpdaterInterface::loadForPlaylist( const playlist_ptr& pl )
|
|||||||
|
|
||||||
if ( !updater )
|
if ( !updater )
|
||||||
{
|
{
|
||||||
Q_ASSERT( false );
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
updater->setAutoUpdate( s->value( QString( "%1/autoupdate" ).arg( key ) ).toBool() );
|
updater->setAutoUpdate( s->value( QString( "%1/autoupdate" ).arg( key ) ).toBool() );
|
||||||
|
@@ -91,6 +91,11 @@ PlaylistModel::loadPlaylist( const Tomahawk::playlist_ptr& playlist, bool loadEn
|
|||||||
}
|
}
|
||||||
|
|
||||||
QList<plentry_ptr> entries = playlist->entries();
|
QList<plentry_ptr> entries = playlist->entries();
|
||||||
|
|
||||||
|
qDebug() << "playlist loading entries:";
|
||||||
|
foreach( const plentry_ptr& p, entries )
|
||||||
|
qDebug() << p->guid();
|
||||||
|
|
||||||
append( entries );
|
append( entries );
|
||||||
|
|
||||||
m_isLoading = false;
|
m_isLoading = false;
|
||||||
|
@@ -628,19 +628,19 @@ TomahawkSettings::setProxyDns( bool lookupViaProxy )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QVariantHash
|
QVariantList
|
||||||
TomahawkSettings::aclEntries() const
|
TomahawkSettings::aclEntries() const
|
||||||
{
|
{
|
||||||
QVariant retVal = value( "acl/entries", QVariantHash() );
|
QVariant retVal = value( "acl/entries", QVariantList() );
|
||||||
if ( retVal.isValid() && retVal.canConvert< QVariantHash >() )
|
if ( retVal.isValid() && retVal.canConvert< QVariantList >() )
|
||||||
return retVal.toHash();
|
return retVal.toList();
|
||||||
|
|
||||||
return QVariantHash();
|
return QVariantList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TomahawkSettings::setAclEntries( const QVariantHash &entries )
|
TomahawkSettings::setAclEntries( const QVariantList &entries )
|
||||||
{
|
{
|
||||||
setValue( "acl/entries", entries );
|
setValue( "acl/entries", entries );
|
||||||
}
|
}
|
||||||
|
@@ -163,8 +163,8 @@ public:
|
|||||||
void setProxyDns( bool lookupViaProxy );
|
void setProxyDns( bool lookupViaProxy );
|
||||||
|
|
||||||
/// ACL settings
|
/// ACL settings
|
||||||
QVariantHash aclEntries() const;
|
QVariantList aclEntries() const;
|
||||||
void setAclEntries( const QVariantHash &entries );
|
void setAclEntries( const QVariantList &entries );
|
||||||
|
|
||||||
/// XMPP Component Settings
|
/// XMPP Component Settings
|
||||||
QString xmppBotServer() const;
|
QString xmppBotServer() const;
|
||||||
|
Reference in New Issue
Block a user