diff --git a/src/playlistparsers/asxparser.cpp b/src/playlistparsers/asxparser.cpp index 63f3b1cc8..bd6a9e3a7 100644 --- a/src/playlistparsers/asxparser.cpp +++ b/src/playlistparsers/asxparser.cpp @@ -16,12 +16,14 @@ #include "asxparser.h" +#include #include #include #include #include #include #include +#include ASXParser::ASXParser(QObject* parent) : XMLParser(parent) @@ -29,9 +31,27 @@ ASXParser::ASXParser(QObject* parent) } SongList ASXParser::Load(QIODevice *device, const QDir&) const { + // We have to load everything first so we can munge the "XML". + QByteArray data = device->readAll(); + + // (thanks Amarok...) + // ASX looks a lot like xml, but doesn't require tags to be case sensitive, + // meaning we have to accept things like: ... + // We use a dirty way to achieve this: we make all tags lower case + QRegExp ex("(<[/]?[^>]*[A-Z]+[^>]*>)"); + ex.setCaseSensitivity(Qt::CaseInsensitive); + int index = 0; + while ((index = ex.indexIn(data, index)) != -1) { + data.replace(ex.cap(1).toLocal8Bit(), ex.cap(1).toLower().toLocal8Bit()); + index += ex.matchedLength(); + } + + QBuffer buffer(&data); + buffer.open(QIODevice::ReadOnly); + SongList ret; - QXmlStreamReader reader(device); + QXmlStreamReader reader(&buffer); if (!ParseUntilElement(&reader, "asx")) { return ret; } @@ -51,6 +71,7 @@ Song ASXParser::ParseTrack(QXmlStreamReader* reader) const { QString title, artist, album; while (!reader->atEnd()) { QXmlStreamReader::TokenType type = reader->readNext(); + switch (type) { case QXmlStreamReader::StartElement: { QStringRef name = reader->name(); @@ -79,6 +100,7 @@ Song ASXParser::ParseTrack(QXmlStreamReader* reader) const { song.Init(title, artist, album, -1); return song; } + break; } default: break; diff --git a/src/playlistparsers/xmlparser.cpp b/src/playlistparsers/xmlparser.cpp index 558c03610..8b5f3850f 100644 --- a/src/playlistparsers/xmlparser.cpp +++ b/src/playlistparsers/xmlparser.cpp @@ -34,8 +34,6 @@ bool XMLParser::ParseUntilElement(QXmlStreamReader* reader, const QString& name) case QXmlStreamReader::StartElement: if (reader->name() == name) { return true; - } else { - IgnoreElement(reader); } break; default: diff --git a/tests/asxparser_test.cpp b/tests/asxparser_test.cpp index f6558b890..0963ab3ee 100644 --- a/tests/asxparser_test.cpp +++ b/tests/asxparser_test.cpp @@ -88,3 +88,16 @@ TEST_F(ASXParserTest, SavesSong) { EXPECT_THAT(data.constData(), HasSubstr("foo")); EXPECT_THAT(data.constData(), HasSubstr("bar")); } + +TEST_F(ASXParserTest, ParsesSomaFM) { + QFile somafm(":/testdata/secretagent.asx"); + somafm.open(QIODevice::ReadOnly); + + ASXParser parser; + SongList songs = parser.Load(&somafm); + + ASSERT_EQ(4, songs.count()); + EXPECT_EQ("SomaFM: Secret Agent", songs[0].title()); + EXPECT_EQ("Keep us on the air! Click Support SomaFM above!", songs[0].artist()); + EXPECT_EQ("http://streamer-ntc-aa03.somafm.com:80/stream/1021", songs[0].filename()); +} diff --git a/tests/data/secretagent.asx b/tests/data/secretagent.asx new file mode 100644 index 000000000..b6da2bb3b --- /dev/null +++ b/tests/data/secretagent.asx @@ -0,0 +1,39 @@ + + + + + + + Loading: Secret Agent from SomaFM.com + SomaFM: Secret Agent + Keep us on the air! Click Support SomaFM above! + + + + + + + Loading: Secret Agent from SomaFM.com + SomaFM: Secret Agent + Keep us on the air! Click Support SomaFM above! + + + + + + + Loading: Secret Agent from SomaFM.com + SomaFM: Secret Agent + Keep us on the air! Click Support SomaFM above! + + + + + + Loading firewall friendly stream: Secret Agent from SomaFM.com + SomaFM: Secret Agent + Keep us on the air! Click Support SomaFM above! + + + + diff --git a/tests/data/testdata.qrc b/tests/data/testdata.qrc index 7b8c6d4a6..a7f6b75d3 100644 --- a/tests/data/testdata.qrc +++ b/tests/data/testdata.qrc @@ -12,5 +12,6 @@ test.m3u test.xspf test.asx + secretagent.asx