File indexing completed on 2025-02-23 04:27:36

0001 /****************************************************************************************
0002  * Copyright (c) 2006 Ian Monroe <ian@monroe.nu>                                        *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) version 3 or        *
0007  * any later version accepted by the membership of KDE e.V. (or its successor approved  *
0008  * by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of  *
0009  * version 3 of the license.                                                            *
0010  *                                                                                      *
0011  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0012  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0013  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0014  *                                                                                      *
0015  * You should have received a copy of the GNU General Public License along with         *
0016  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0017  ****************************************************************************************/
0018 
0019 #include "contentfetcher.h"
0020 #include "core/support/Debug.h"
0021 #include "hasher.h"
0022 #include "network/NetworkAccessManagerProxy.h"
0023 
0024 #include <QBuffer>
0025 #include <QByteArray>
0026 #include <QNetworkReply>
0027 
0028 #include <KCodecs>
0029 #include <KCompressionDevice>
0030 
0031 using namespace Daap;
0032 int ContentFetcher::s_requestId = 10;
0033 
0034 ContentFetcher::ContentFetcher( const QString & hostname, quint16 port, const QString& password, QObject * parent, const char * name )
0035  : QObject(parent)
0036  , m_reply( nullptr )
0037  , m_hostname( hostname )
0038  , m_port( port )
0039  , m_selfDestruct( false )
0040 {
0041     setObjectName( name );
0042     QByteArray pass = password.toUtf8();
0043     if( !password.isNull() )
0044     {
0045         m_authorize = "Basic " + KCodecs::base64Encode( "none:" + pass );
0046     }
0047 }
0048 
0049 ContentFetcher::~ContentFetcher()
0050 { }
0051 
0052 QByteArray
0053 ContentFetcher::results()
0054 {
0055     return m_lastResult;
0056 }
0057 
0058 void
0059 ContentFetcher::getDaap( const QString &command, QIODevice* musicFile /*= 0*/ )
0060 {
0061     QUrl url( command );
0062     url.setHost( m_hostname );
0063     url.setPort( m_port );
0064     QNetworkRequest request( url );
0065     char hash[33] = {0};
0066     const char *cmd = command.toLatin1();
0067     GenerateHash(3, reinterpret_cast<const unsigned char*>( cmd ), 2, reinterpret_cast<unsigned char*>(hash), 0 /*s_requestId*/);
0068 
0069     if( !m_authorize.isEmpty() )
0070     {
0071         request.setRawHeader( "Authorization", m_authorize );
0072     }
0073 
0074     request.setRawHeader( "Client-DAAP-Request-ID", "0"/*QString::number( s_requestId )*/ );
0075     request.setRawHeader( "Client-DAAP-Access-Index", "2" );
0076     request.setRawHeader( "Client-DAAP-Validation", hash );
0077     request.setRawHeader( "Client-DAAP-Version", "3.0" );
0078     request.setRawHeader( "User-Agent", "iTunes/4.6 (Windows; N)" );
0079     request.setRawHeader( "Accept", "*/*" );
0080     request.setRawHeader( "Accept-Encoding", "gzip" );
0081 
0082     m_reply = The::networkAccessManager()->sendCustomRequest( request, "GET", musicFile );
0083 
0084     if( m_reply->isFinished() )
0085         onFinished();
0086     else
0087         connect( m_reply, &QNetworkReply::finished, this, &ContentFetcher::onFinished );
0088 }
0089 
0090 void
0091 ContentFetcher::onFinished()
0092 {
0093     if( !m_reply )
0094         return;
0095 
0096     if( !m_selfDestruct && m_reply->error() )
0097     {
0098         if( m_reply->error() == QNetworkReply::AuthenticationRequiredError )
0099         {
0100             Q_EMIT loginRequired();
0101             return;
0102         }
0103 
0104         debug() << "there is an error? " << m_reply->error() << " " << m_reply->errorString();
0105         m_selfDestruct = true;
0106         Q_EMIT httpError( m_reply->errorString() );
0107     }
0108 
0109     QByteArray read = m_reply->readAll();
0110     if( m_reply->rawHeader( "Content-Encoding" ) == "gzip" )
0111     {
0112         QBuffer* bytes = new QBuffer( &read );
0113         KCompressionDevice *stream = new KCompressionDevice( bytes, true, KCompressionDevice::GZip );
0114         if ( stream->open( QIODevice::ReadOnly ) )
0115             m_lastResult = stream->readAll();
0116         else
0117             m_lastResult = read;
0118 
0119         delete stream;
0120     }
0121     else
0122         m_lastResult = read;
0123 
0124     Q_EMIT finished();
0125     m_reply->deleteLater();
0126     m_reply = nullptr;
0127 }
0128 
0129 
0130