Hello community,

here is the log from the commit of package amarok for openSUSE:Factory checked 
in at 2017-08-29 11:42:29
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/amarok (Old)
 and      /work/SRC/openSUSE:Factory/.amarok.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "amarok"

Tue Aug 29 11:42:29 2017 rev:106 rq:518864 version:2.8.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/amarok/amarok.changes    2016-12-26 
21:41:58.324735386 +0100
+++ /work/SRC/openSUSE:Factory/.amarok.new/amarok.changes       2017-08-29 
11:42:32.209381869 +0200
@@ -1,0 +2,6 @@
+Thu Aug 24 10:41:10 UTC 2017 - [email protected]
+
+- Add Fix-crash-during-musicbrainz-search.patch to fix a possible
+  crash when looking up metadata on MusicBrainz (kde#328359)
+
+-------------------------------------------------------------------

New:
----
  Fix-crash-during-musicbrainz-search.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ amarok.spec ++++++
--- /var/tmp/diff_new_pack.Jc8g9L/_old  2017-08-29 11:42:35.612902049 +0200
+++ /var/tmp/diff_new_pack.Jc8g9L/_new  2017-08-29 11:42:35.624900357 +0200
@@ -61,8 +61,10 @@
 Patch110:       amarok-ffmpeg3.0.patch
 # PATCH-FIX-UPSTREAM Fix-for-infinite-loop-with-some-Audio-CDs.patch 
kde#339190 -- Fix for the infinite loop in case a home-burned or old audio CD 
is inserted
 Patch111:       Fix-for-infinite-loop-with-some-Audio-CDs.patch
-# PATCH-FIX-UPSTREAM Fix-MPRIS2-DesktopEntry-value.patch, nec essary for 
working media controls in taskbar plsama 5.7 -- kde#565275
+# PATCH-FIX-UPSTREAM Fix-MPRIS2-DesktopEntry-value.patch, necessary for 
working media controls in taskbar plasma 5.7 -- kde#565275
 Patch112:       Fix-MPRIS2-DesktopEntry-value.patch
+# PATCH-FIX-UPSTREAM Fix-crash-during-musicbrainz-search.patch kde#328359 -- 
Fix a possible crash when looking up metadata on MusicBrainz
+Patch113:       Fix-crash-during-musicbrainz-search.patch
 # Required for the fdupes macro
 BuildRequires:  fdupes
 BuildRequires:  gdk-pixbuf-devel
@@ -140,6 +142,7 @@
 %patch110 -p0
 %patch111 -p1
 %patch112 -p1
+%patch113 -p1
 
 # Remove build time references so build-compare can do its work
 FAKE_BUILDDATE=$(LC_ALL=C date -u -r %{SOURCE99} '+%%b %%e %%Y')

++++++ Fix-crash-during-musicbrainz-search.patch ++++++
>From 88ee85a8333cf54dc123fef5e07a1c92ab9f7261 Mon Sep 17 00:00:00 2001
From: Sergey Ivanov <[email protected]>
Date: Sun, 20 Aug 2017 11:25:57 +0300
Subject: Fix crash during musicbrainz search.

BUG: 328359
REVIEW: 130232
---
 ChangeLog                                |   3 +-
 src/musicbrainz/MusicBrainzFinder.cpp    |   6 +-
 src/musicbrainz/MusicBrainzFinder.h      |   3 +-
 src/musicbrainz/MusicBrainzTagsItem.cpp  | 188 +++++++++++--------------------
 src/musicbrainz/MusicBrainzTagsItem.h    |   6 +-
 src/musicbrainz/MusicBrainzTagsModel.cpp |  66 +++++++++--
 src/musicbrainz/MusicBrainzTagsModel.h   |   2 +
 src/musicbrainz/MusicBrainzXmlParser.cpp |   3 +-
 src/musicbrainz/MusicBrainzXmlParser.h   |   2 +-
 9 files changed, 141 insertions(+), 138 deletions(-)

diff --git a/src/musicbrainz/MusicBrainzFinder.cpp 
b/src/musicbrainz/MusicBrainzFinder.cpp
index 9a1b3bb..2598a0b 100644
--- a/src/musicbrainz/MusicBrainzFinder.cpp
+++ b/src/musicbrainz/MusicBrainzFinder.cpp
@@ -132,8 +132,7 @@ MusicBrainzFinder::sendNewRequest()
 }
 
 void
-MusicBrainzFinder::gotAuthenticationRequest( const QNetworkReply *reply,
-                                             QAuthenticator *authenticator ) 
const
+MusicBrainzFinder::gotAuthenticationRequest( const QNetworkReply *reply, 
QAuthenticator *authenticator )
 {
     if( reply->url().host() == mb_host )
     {
@@ -644,8 +643,9 @@ MusicBrainzFinder::compileRequest( QUrl &url )
     url.setPort( mb_port );
 
     QNetworkRequest req( url );
-    req.setRawHeader( "User-Agent" , "Amarok" );
+    req.setRawHeader( "Accept", "application/xml");
     req.setRawHeader( "Connection", "Keep-Alive" );
+    req.setRawHeader( "User-Agent" , "Amarok" );
 
     if( !m_timer->isActive() )
         m_timer->start();
diff --git a/src/musicbrainz/MusicBrainzFinder.h 
b/src/musicbrainz/MusicBrainzFinder.h
index beb1551..4dbd4a5 100644
--- a/src/musicbrainz/MusicBrainzFinder.h
+++ b/src/musicbrainz/MusicBrainzFinder.h
@@ -51,8 +51,7 @@ class MusicBrainzFinder : public QObject
 
     private slots:
         void sendNewRequest();
-        void gotAuthenticationRequest( const QNetworkReply *reply,
-                                       QAuthenticator *authenticator ) const;
+        void gotAuthenticationRequest( const QNetworkReply *reply, 
QAuthenticator *authenticator );
         void gotReplyError( QNetworkReply::NetworkError code );
         void gotReply( QNetworkReply *reply );
 
diff --git a/src/musicbrainz/MusicBrainzTagsItem.cpp 
b/src/musicbrainz/MusicBrainzTagsItem.cpp
index 0941a90..6430392 100644
--- a/src/musicbrainz/MusicBrainzTagsItem.cpp
+++ b/src/musicbrainz/MusicBrainzTagsItem.cpp
@@ -65,146 +65,75 @@ MusicBrainzTagsItem::child( const int row ) const
 void
 MusicBrainzTagsItem::appendChild( MusicBrainzTagsItem *newItem )
 {
-    DEBUG_BLOCK
+    QWriteLocker lock( &m_childrenLock );
+    m_childItems.append( newItem );
+    newItem->setParent( this );
 
-    if( newItem->track().isNull() )
+    if( !newItem->data().isEmpty() )
     {
-        delete newItem;
-        return;
-    }
+        newItem->recalcSimilarityRate();
 
-    if( m_track.isNull() )
-    {
-        // Root item.
-        bool found = false;
+#define MAKE_DATA_LIST( k ) { QVariantList list; if( newItem->dataContains( k 
) ) list.append( newItem->dataValue( k ) ); newItem->dataInsert( k, list ); }
 
-        /*
-         * A write lock is required, because with a read lock two or more 
threads
-         * referencing the same track could search for a matching item at the 
same time,
-         * fail, and queue up to create a new one, thus resulting in 
duplicates.
-         */
-        QWriteLocker lock( &m_childrenLock );
-        foreach( MusicBrainzTagsItem *item, m_childItems )
-        {
-            if( item->track() == newItem->track() )
-            {
-                found = true;
-                if( !newItem->data().isEmpty() )
-                    item->appendChild( newItem );
-                break;
-            }
-        }
+        MAKE_DATA_LIST( MusicBrainz::TRACKID );
+        MAKE_DATA_LIST( MusicBrainz::ARTISTID );
+        MAKE_DATA_LIST( MusicBrainz::RELEASEID );
 
-        if( !found )
-        {
-            MusicBrainzTagsItem *newChild = new MusicBrainzTagsItem( this, 
newItem->track() );
-            if( !newItem->data().isEmpty() )
-                newChild->appendChild( newItem );
-            m_childItems.append( newChild );
-        }
-    }
-    else
-    {
-        if( m_track != newItem->track() )
-        {
-            debug() << "Trying to insert track data to the wrong tree branch.";
-            delete newItem;
-            return;
-        }
-
-        bool found = false;
-        newItem->setParent( this );
-
-        // Already locked in parent call (the same logic applies).
-        foreach( MusicBrainzTagsItem *item, m_childItems )
-        {
-            if( newItem == item )
-            {
-                found = true;
-                // Merge the two matching results.
-                debug() << "Track" << newItem->dataValue( MusicBrainz::TRACKID 
).toString() << "already in the tree.";
-                item->mergeWith( newItem );
-                delete newItem;
-                break;
-            }
-        }
-
-        if( !found )
-        {
-            newItem->dataInsert( MusicBrainz::SIMILARITY,
-                                 newItem->dataValue( MusicBrainz::MUSICBRAINZ 
).toFloat() +
-                                 newItem->dataValue( MusicBrainz::MUSICDNS 
).toFloat() );
-
-            QVariantList trackList;
-            QVariantList artistList;
-            QVariantList releaseList;
-            if( newItem->dataContains( MusicBrainz::TRACKID ) )
-                trackList.append( newItem->dataValue( MusicBrainz::TRACKID ) );
-            if( newItem->dataContains( MusicBrainz::ARTISTID ) )
-                artistList.append( newItem->dataValue( MusicBrainz::ARTISTID ) 
);
-            if( newItem->dataContains( MusicBrainz::RELEASEID ) )
-                releaseList.append( newItem->dataValue( MusicBrainz::RELEASEID 
) );
-            newItem->dataInsert( MusicBrainz::TRACKID, trackList );
-            newItem->dataInsert( MusicBrainz::ARTISTID, artistList );
-            newItem->dataInsert( MusicBrainz::RELEASEID, releaseList );
-
-            m_childItems.append( newItem );
-        }
+#undef MAKE_DATA_LIST
     }
 }
 
 void
-MusicBrainzTagsItem::mergeWith( MusicBrainzTagsItem *item )
+MusicBrainzTagsItem::mergeData( const QVariantMap &tags )
 {
-    /*
-     * The lock is inherited from appendChild(). This method is not supposed 
to be called
-     * elsewhere.
-     */
+    if( tags.isEmpty() )
+        return;
 
+    MusicBrainzTagsItem fakeItem( this, m_track, tags );
     // Calculate the future score of the result when merged.
-    if( !item->dataContains( MusicBrainz::MUSICBRAINZ ) &&
-        dataContains( MusicBrainz::MUSICBRAINZ ) )
-        item->dataInsert( MusicBrainz::MUSICBRAINZ,
-                          dataValue( MusicBrainz::MUSICBRAINZ ) );
-    if( !item->dataContains( MusicBrainz::MUSICDNS ) &&
-        dataContains( MusicBrainz::MUSICDNS ) )
-        item->dataInsert( MusicBrainz::MUSICDNS,
-                          dataValue( MusicBrainz::MUSICDNS ) );
-    item->dataInsert( MusicBrainz::SIMILARITY,
-                      item->dataValue( MusicBrainz::MUSICBRAINZ ).toFloat() +
-                      item->dataValue( MusicBrainz::MUSICDNS ).toFloat() );
+    if( !fakeItem.dataContains( MusicBrainz::MUSICBRAINZ ) && dataContains( 
MusicBrainz::MUSICBRAINZ ) )
+        fakeItem.dataInsert( MusicBrainz::MUSICBRAINZ, dataValue( 
MusicBrainz::MUSICBRAINZ ) );
+
+    if( !fakeItem.dataContains( MusicBrainz::MUSICDNS ) && dataContains( 
MusicBrainz::MUSICDNS ) )
+        fakeItem.dataInsert( MusicBrainz::MUSICDNS, dataValue( 
MusicBrainz::MUSICDNS ) );
+
+    fakeItem.recalcSimilarityRate();
 
     QVariantList trackList = dataValue( MusicBrainz::TRACKID ).toList();
     QVariantList artistList = dataValue( MusicBrainz::ARTISTID ).toList();
     QVariantList releaseList = dataValue( MusicBrainz::RELEASEID ).toList();
-    if( item->score() > score() )
+    if( fakeItem.score() > score() )
     {
         // Update the score.
-        if( item->dataContains( MusicBrainz::MUSICBRAINZ ) )
-            dataInsert( MusicBrainz::MUSICBRAINZ,
-                        item->dataValue( MusicBrainz::MUSICBRAINZ ) );
-        if( item->dataContains( MusicBrainz::MUSICDNS ) )
-            dataInsert( MusicBrainz::MUSICDNS,
-                        item->dataValue( MusicBrainz::MUSICDNS ) );
-        dataInsert( MusicBrainz::SIMILARITY,
-                    item->dataValue( MusicBrainz::SIMILARITY ) );
-
-        if( item->dataContains( MusicBrainz::TRACKID ) )
-            trackList.prepend( item->dataValue( MusicBrainz::TRACKID ) );
-        if( item->dataContains( MusicBrainz::ARTISTID ) )
-            artistList.prepend( item->dataValue( MusicBrainz::ARTISTID ) );
-        if( item->dataContains( MusicBrainz::RELEASEID ) )
-            releaseList.prepend( item->dataValue( MusicBrainz::RELEASEID ) );
+        if( fakeItem.dataContains( MusicBrainz::MUSICBRAINZ ) )
+            dataInsert( MusicBrainz::MUSICBRAINZ, fakeItem.dataValue( 
MusicBrainz::MUSICBRAINZ ) );
+
+        if( fakeItem.dataContains( MusicBrainz::MUSICDNS ) )
+            dataInsert( MusicBrainz::MUSICDNS, fakeItem.dataValue( 
MusicBrainz::MUSICDNS ) );
+
+        recalcSimilarityRate();
+
+        if( fakeItem.dataContains( MusicBrainz::TRACKID ) )
+            trackList.prepend( fakeItem.dataValue( MusicBrainz::TRACKID ) );
+
+        if( fakeItem.dataContains( MusicBrainz::ARTISTID ) )
+            artistList.prepend( fakeItem.dataValue( MusicBrainz::ARTISTID ) );
+
+        if( fakeItem.dataContains( MusicBrainz::RELEASEID ) )
+            releaseList.prepend( fakeItem.dataValue( MusicBrainz::RELEASEID ) 
);
     }
     else
     {
-        if( item->dataContains( MusicBrainz::TRACKID ) )
-            trackList.append( item->dataValue( MusicBrainz::TRACKID ) );
-        if( item->dataContains( MusicBrainz::ARTISTID ) )
-            artistList.append( item->dataValue( MusicBrainz::ARTISTID ) );
-        if( item->dataContains( MusicBrainz::RELEASEID ) )
-            releaseList.append( item->dataValue( MusicBrainz::RELEASEID ) );
+        if( fakeItem.dataContains( MusicBrainz::TRACKID ) )
+            trackList.append( fakeItem.dataValue( MusicBrainz::TRACKID ) );
+
+        if( fakeItem.dataContains( MusicBrainz::ARTISTID ) )
+            artistList.append( fakeItem.dataValue( MusicBrainz::ARTISTID ) );
+
+        if( fakeItem.dataContains( MusicBrainz::RELEASEID ) )
+            releaseList.append( fakeItem.dataValue( MusicBrainz::RELEASEID ) );
     }
+
     dataInsert( MusicBrainz::TRACKID, trackList );
     dataInsert( MusicBrainz::ARTISTID, artistList );
     dataInsert( MusicBrainz::RELEASEID, releaseList );
@@ -476,10 +405,11 @@ MusicBrainzTagsItem::clearChoices()
 }
 
 bool
-MusicBrainzTagsItem::operator==( const MusicBrainzTagsItem* item ) const
+MusicBrainzTagsItem::isSimilar( const QVariantMap &tags ) const
 {
     QReadLocker lock( &m_dataLock );
-#define MATCH( k, t ) dataValue( k ).t() == item->dataValue( k ).t()
+    QVariant empty;
+#define MATCH( k, t ) ( dataValue( k ).t() == ( tags.contains( k ) ? 
tags.value( k ) : empty ).t() )
     /*
      * This is the information shown to the user: he will never be able to
      * distinguish between two tracks with the same information.
@@ -494,3 +424,21 @@ MusicBrainzTagsItem::operator==( const 
MusicBrainzTagsItem* item ) const
            MATCH( Meta::Field::TRACKNUMBER, toInt );
 #undef MATCH
 }
+
+bool
+MusicBrainzTagsItem::operator==( const MusicBrainzTagsItem* item ) const
+{
+    return isSimilar( item->data() );
+}
+
+bool
+MusicBrainzTagsItem::operator==( const Meta::TrackPtr &track) const
+{
+    return m_track == track;
+}
+
+void
+MusicBrainzTagsItem::recalcSimilarityRate()
+{
+    dataInsert( MusicBrainz::SIMILARITY, dataValue( MusicBrainz::MUSICBRAINZ 
).toFloat() + dataValue( MusicBrainz::MUSICDNS ).toFloat() );
+}
diff --git a/src/musicbrainz/MusicBrainzTagsItem.h 
b/src/musicbrainz/MusicBrainzTagsItem.h
index 6852c9f..11efb52 100644
--- a/src/musicbrainz/MusicBrainzTagsItem.h
+++ b/src/musicbrainz/MusicBrainzTagsItem.h
@@ -42,6 +42,7 @@ class MusicBrainzTagsItem
         QVariantMap data() const;
         QVariant data( const int column ) const;
         void setData( const QVariantMap &tags );
+        void mergeData( const QVariantMap &tags );
         bool dataContains( const QString &key ) const;
         QVariant dataValue( const QString &key ) const;
 
@@ -52,12 +53,15 @@ class MusicBrainzTagsItem
         bool chooseBestMatchFromRelease( const QStringList &releases );
         void clearChoices();
 
+        bool isSimilar( const QVariantMap &tags ) const;
+
         bool operator==( const MusicBrainzTagsItem *item ) const;
+        bool operator==( const Meta::TrackPtr &track) const;
 
     private:
         void setParent( MusicBrainzTagsItem *parent );
-        void mergeWith( MusicBrainzTagsItem *item );
         void dataInsert( const QString &key, const QVariant &value );
+        void recalcSimilarityRate();
 
         MusicBrainzTagsItem *m_parent;
         QList<MusicBrainzTagsItem *> m_childItems;
diff --git a/src/musicbrainz/MusicBrainzTagsModel.cpp 
b/src/musicbrainz/MusicBrainzTagsModel.cpp
index 0ffb284..e7bde4c 100644
--- a/src/musicbrainz/MusicBrainzTagsModel.cpp
+++ b/src/musicbrainz/MusicBrainzTagsModel.cpp
@@ -204,7 +204,10 @@ MusicBrainzTagsModel::setData( const QModelIndex &index, 
const QVariant &value,
 Qt::ItemFlags
 MusicBrainzTagsModel::flags( const QModelIndex &index ) const
 {
-    if( !index.isValid() || !parent( index ).isValid() )
+    if( !index.isValid() )
+        return QAbstractItemModel::flags( index );
+
+    if( !parent( index ).isValid() )
         // Disable items with no children.
         return QAbstractItemModel::flags( index ) ^
                ( ( !static_cast<MusicBrainzTagsItem *>( 
index.internalPointer() )->childCount() )?
@@ -248,22 +251,67 @@ MusicBrainzTagsModel::columnCount( const QModelIndex 
&parent ) const
 void
 MusicBrainzTagsModel::addTrack( const Meta::TrackPtr track, const QVariantMap 
tags )
 {
-    QModelIndex parent;
-    int row = rowCount();
-    for( int i = 0; i < m_rootItem->childCount(); i++ )
+    DEBUG_BLOCK
+
+    if( track.isNull() )
+        return;
+
+    QMutexLocker lock( &m_modelLock );
+
+    MusicBrainzTagsItem *trackItem = NULL;
+    QModelIndex trackIndex;
+    for( int i = 0; i < m_rootItem->childCount(); ++i )
     {
         MusicBrainzTagsItem *item = m_rootItem->child( i );
         if( track == item->track() )
         {
-            parent = index( i, 0 );
-            row = rowCount( parent );
+            trackItem = item;
+            trackIndex = index( i, 0 );
+
+            break;
+        }
+    }
+
+    if( !trackItem )
+    {
+        trackItem = new MusicBrainzTagsItem( m_rootItem, track );
+
+        beginInsertRows( QModelIndex(), m_rootItem->childCount(), 
m_rootItem->childCount() );
+        m_rootItem->appendChild( trackItem );
+        endInsertRows();
+
+        trackIndex = index( m_rootItem->childCount() - 1, 0 );
+    }
+
+    if( tags.isEmpty() )
+    {
+        warning() << "Search result contains no data for track: " << 
track->prettyName();
+        return;
+    }
+
+    MusicBrainzTagsItem *similarItem = NULL;
+    for( int i = 0; i < trackItem->childCount(); ++i )
+    {
+        MusicBrainzTagsItem *item = trackItem->child( i );
+        if( item->isSimilar( tags ) )
+        {
+            similarItem = item;
+
+            item->mergeData( tags );
+            emit dataChanged( index( i, 0, trackIndex ), index(i, 
columnCount() - 1, trackIndex ) );
+
             break;
         }
     }
 
-    beginInsertRows( parent, row, row );
-    m_rootItem->appendChild( new MusicBrainzTagsItem( m_rootItem, track, tags 
) );
-    endInsertRows();
+    if( !similarItem )
+    {
+        MusicBrainzTagsItem *item = new MusicBrainzTagsItem( trackItem, track, 
tags );
+
+        beginInsertRows( trackIndex, trackItem->childCount(), 
trackItem->childCount() );
+        trackItem->appendChild( item );
+        endInsertRows();
+    }
 }
 
 QMap<Meta::TrackPtr, QVariantMap>
diff --git a/src/musicbrainz/MusicBrainzTagsModel.h 
b/src/musicbrainz/MusicBrainzTagsModel.h
index eaee7f8..3ea2fd2 100644
--- a/src/musicbrainz/MusicBrainzTagsModel.h
+++ b/src/musicbrainz/MusicBrainzTagsModel.h
@@ -21,6 +21,7 @@
 #include "core/meta/forward_declarations.h"
 
 #include <QAbstractItemModel>
+#include <QMutex>
 
 class MusicBrainzTagsItem;
 
@@ -69,6 +70,7 @@ class MusicBrainzTagsModel : public QAbstractItemModel
 
     private:
         MusicBrainzTagsItem *m_rootItem;
+        mutable QMutex m_modelLock;
 };
 
 #endif // MUSICBRAINZTAGSMDOEL_H
diff --git a/src/musicbrainz/MusicBrainzXmlParser.cpp 
b/src/musicbrainz/MusicBrainzXmlParser.cpp
index 290a275..40d36a3 100644
--- a/src/musicbrainz/MusicBrainzXmlParser.cpp
+++ b/src/musicbrainz/MusicBrainzXmlParser.cpp
@@ -26,7 +26,7 @@
 #include <QStringList>
 #include <QVariantList>
 
-MusicBrainzXmlParser::MusicBrainzXmlParser( QString &doc )
+MusicBrainzXmlParser::MusicBrainzXmlParser( const QString &doc )
     : ThreadWeaver::Job()
     , m_doc( "musicbrainz" )
     , m_type( 0 )
@@ -38,6 +38,7 @@ void
 MusicBrainzXmlParser::run()
 {
     DEBUG_BLOCK
+
     QDomElement docElem = m_doc.documentElement();
     parseElement( docElem );
 }
diff --git a/src/musicbrainz/MusicBrainzXmlParser.h 
b/src/musicbrainz/MusicBrainzXmlParser.h
index c7f9e72..7b2876b 100644
--- a/src/musicbrainz/MusicBrainzXmlParser.h
+++ b/src/musicbrainz/MusicBrainzXmlParser.h
@@ -34,7 +34,7 @@ class MusicBrainzXmlParser : public ThreadWeaver::Job
             ReleaseGroup
         };
 
-        explicit MusicBrainzXmlParser( QString &doc );
+        explicit MusicBrainzXmlParser( const QString &doc );
 
         void run();
 
-- 
cgit v0.11.2


Reply via email to