1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-12 17:14:00 +02:00

Add liblastfm2 and make tomahawk build against it

This commit is contained in:
Jeff Mitchell
2011-03-24 19:18:42 -04:00
parent 1780781e12
commit b7a1cb8d99
114 changed files with 14711 additions and 3 deletions

View File

@@ -0,0 +1,113 @@
/*
Copyright 2009 Last.fm Ltd.
- Primarily authored by Max Howell, Jono Cole and Doug Mansell
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#include "InternetConnectionMonitor.h"
#include "linux/LNetworkConnectionMonitor.h"
#include "mac/MNetworkConnectionMonitor.h"
#include "win/WNetworkConnectionMonitor.h"
#include "NetworkConnectionMonitor.h"
#include "ws.h"
lastfm::InternetConnectionMonitor::InternetConnectionMonitor( QObject *parent )
: QObject( parent )
, m_up( true )
{
m_networkMonitor = createNetworkConnectionMonitor();
if ( m_networkMonitor )
{
connect( m_networkMonitor, SIGNAL( networkUp() ), this, SLOT( onNetworkUp() ) );
connect( m_networkMonitor, SIGNAL( networkDown() ), this, SLOT( onNetworkDown() ) );
}
connect( lastfm::nam(), SIGNAL( finished( QNetworkReply* ) ), this, SLOT( onFinished( QNetworkReply* ) ) );
}
void
lastfm::InternetConnectionMonitor::onFinished( QNetworkReply* reply )
{
switch( reply->error() )
{
case QNetworkReply::NoError:
if ( !m_up )
{
m_up = true;
emit up();
emit connectivityChanged( m_up );
}
break;
case QNetworkReply::HostNotFoundError:
case QNetworkReply::TimeoutError:
case QNetworkReply::ProxyConnectionRefusedError:
case QNetworkReply::ProxyConnectionClosedError:
case QNetworkReply::ProxyNotFoundError:
case QNetworkReply::ProxyTimeoutError:
case QNetworkReply::ProxyAuthenticationRequiredError:
if ( m_up )
{
m_up = false;
emit down();
emit connectivityChanged( m_up );
}
break;
default:
break;
}
}
void
lastfm::InternetConnectionMonitor::onNetworkUp()
{
#ifdef Q_OS_MAC
// We don't need to check on mac as the
// check is done as part of the reach api
m_up = true;
emit up();
emit connectivityChanged( m_up );
#else
qDebug() << "Network seems to be up again. Let's try if there's internet connection!";
lastfm::nam()->head( QNetworkRequest( QUrl( tr( "http://www.last.fm/" ) ) ) );
#endif
}
void
lastfm::InternetConnectionMonitor::onNetworkDown()
{
qDebug() << "Internet is down :( boo!!";
m_up = false;
emit down();
emit connectivityChanged( m_up );
}
NetworkConnectionMonitor*
lastfm::InternetConnectionMonitor::createNetworkConnectionMonitor()
{
NetworkConnectionMonitor* ncm = 0;
#ifdef Q_WS_X11
ncm = new LNetworkConnectionMonitor( this );
#elif defined(Q_WS_WIN)
ncm = new WNetworkConnectionMonitor( this );
#elif defined(Q_WS_MAC)
ncm = new MNetworkConnectionMonitor( this );
#endif
return ncm;
}

View File

@@ -0,0 +1,80 @@
/*
Copyright 2009 Last.fm Ltd.
- Primarily authored by Max Howell, Jono Cole and Doug Mansell
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LASTFM_CONNECTION_MONITOR_H
#define LASTFM_CONNECTION_MONITOR_H
#include <lastfm/global.h>
#include <QObject>
class NetworkConnectionMonitor;
#ifdef Q_WS_X11
class LNetworkConnectionMonitor;
#endif
namespace lastfm {
class LASTFM_DLLEXPORT InternetConnectionMonitor : public QObject
{
Q_OBJECT
enum NMState
{
Unknown,
Asleep,
Connecting,
Connected,
Disconnected
};
public:
/** if internet is unavailable you will get a down() signal soon, otherwise
* you won't get a signal until the net goes down */
InternetConnectionMonitor( QObject *parent = 0 );
bool isDown() const { return !m_up; }
bool isUp() const { return m_up; }
NetworkConnectionMonitor* createNetworkConnectionMonitor();
signals:
/** yay! internet has returned */
void up( const QString& connectionName = "" );
/** we think the internet is unavailable, but well, still try, but show
* an unhappy face in the statusbar or something */
void down( const QString& connectionName = "" );
/** emitted after the above */
void connectivityChanged( bool );
private slots:
void onFinished( QNetworkReply* reply );
void onNetworkUp();
void onNetworkDown();
private:
bool m_up;
NetworkConnectionMonitor* m_networkMonitor;
};
} //namespace lastfm
#endif

View File

@@ -0,0 +1,159 @@
/*
Copyright 2009 Last.fm Ltd.
- Primarily authored by Max Howell, Jono Cole and Doug Mansell
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#include "NetworkAccessManager.h"
#include "InternetConnectionMonitor.h"
#include <lastfm/ws.h>
#include <lastfm/misc.h>
#include <QCoreApplication>
#include <QNetworkRequest>
#ifdef WIN32
#include "win/IeSettings.h"
#include "win/Pac.h"
#endif
#ifdef __APPLE__
#include "mac/ProxyDict.h"
#endif
static struct NetworkAccessManagerInit
{
// We do this upfront because then our Firehose QTcpSocket will have a proxy
// set by default. As well as any plain QNetworkAcessManager stuff, and the
// scrobbler
// In theory we should do this every request in case the configuration
// changes but that is fairly unlikely use case, init? Maybe we should
// anyway..
NetworkAccessManagerInit()
{
#ifdef WIN32
IeSettings s;
// if it's autodetect, we determine the proxy everytime in proxy()
// we don't really want to do a PAC lookup here, as it times out
// at two seconds, so that hangs startup
if (!s.fAutoDetect && s.lpszProxy)
{
QUrl url( QString::fromUtf16(s.lpszProxy) );
QNetworkProxy proxy( QNetworkProxy::HttpProxy );
proxy.setHostName( url.host() );
proxy.setPort( url.port() );
QNetworkProxy::setApplicationProxy( proxy );
}
#endif
#ifdef __APPLE__
ProxyDict dict;
if (dict.isProxyEnabled())
{
QNetworkProxy proxy( QNetworkProxy::HttpProxy );
proxy.setHostName( dict.host );
proxy.setPort( dict.port );
QNetworkProxy::setApplicationProxy( proxy );
}
#endif
}
} init;
namespace lastfm
{
LASTFM_DLLEXPORT QByteArray UserAgent;
}
lastfm::NetworkAccessManager::NetworkAccessManager( QObject* parent )
: QNetworkAccessManager( parent )
#ifdef WIN32
, m_pac( 0 )
, m_monitor( 0 )
#endif
{
// can't be done in above init, as applicationName() won't be set
if (lastfm::UserAgent.isEmpty())
{
QByteArray name = QCoreApplication::applicationName().toUtf8();
QByteArray version = QCoreApplication::applicationVersion().toUtf8();
if (version.size()) version.prepend( ' ' );
lastfm::UserAgent = name + version + " (" + lastfm::platform() + ")";
}
}
lastfm::NetworkAccessManager::~NetworkAccessManager()
{
#ifdef WIN32
delete m_pac;
#endif
}
QNetworkProxy
lastfm::NetworkAccessManager::proxy( const QNetworkRequest& request )
{
Q_UNUSED( request );
#ifdef WIN32
IeSettings s;
if (s.fAutoDetect)
{
if (!m_pac) {
m_pac = new Pac;
if ( !m_monitor )
{
m_monitor = new InternetConnectionMonitor( this );
connect( m_monitor, SIGNAL( connectivityChanged( bool ) ), SLOT( onConnectivityChanged( bool ) ) );
}
}
return m_pac->resolve( request, s.lpszAutoConfigUrl );
}
#endif
return QNetworkProxy::applicationProxy();
}
QNetworkReply*
lastfm::NetworkAccessManager::createRequest( Operation op, const QNetworkRequest& request_, QIODevice* outgoingData )
{
QNetworkRequest request = request_;
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
request.setRawHeader( "User-Agent", lastfm::UserAgent );
#ifdef WIN32
// PAC proxies can vary by domain, so we have to check everytime :(
QNetworkProxy proxy = this->proxy( request );
if (proxy.type() != QNetworkProxy::NoProxy)
QNetworkAccessManager::setProxy( proxy );
#endif
return QNetworkAccessManager::createRequest( op, request, outgoingData );
}
void
lastfm::NetworkAccessManager::onConnectivityChanged( bool up )
{
Q_UNUSED( up );
#ifdef WIN32
if (up && m_pac) m_pac->resetFailedState();
#endif
}

View File

@@ -0,0 +1,66 @@
/*
Copyright 2009 Last.fm Ltd.
- Primarily authored by Max Howell, Jono Cole and Doug Mansell
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LASTFM_WS_ACCESS_MANAGER_H
#define LASTFM_WS_ACCESS_MANAGER_H
#include <lastfm/global.h>
#include <QtNetwork/QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkProxy>
namespace lastfm {
/** Sets useragent and proxy. Auto detecting the proxy where possible. */
class LASTFM_DLLEXPORT NetworkAccessManager : public QNetworkAccessManager
{
Q_OBJECT
#ifdef Q_WS_WIN
class Pac *m_pac;
class InternetConnectionMonitor* m_monitor;
#endif
public:
NetworkAccessManager( QObject *parent = 0 );
~NetworkAccessManager();
/** PAC allows different proxy configurations depending on the request
* URL and even UserAgent! Thus we allow you to pass that in, we
* automatically configure the proxy for every request through
* WsAccessManager */
QNetworkProxy proxy( const QNetworkRequest& = QNetworkRequest() );
protected:
virtual QNetworkReply* createRequest( Operation, const QNetworkRequest&, QIODevice* outgoingdata = 0 );
private slots:
void onConnectivityChanged( bool );
private:
/** this function calls QNetworkAccessManager::setProxy, and thus
* configures the proxy correctly for the next request created by
* createRequest. This is necessary due */
void applyProxy( const QNetworkRequest& );
};
} //namespace lastfm
#endif

View File

@@ -0,0 +1,51 @@
/*
Copyright 2010 Last.fm Ltd.
- Primarily authored by Max Howell, Jono Cole and Doug Mansell
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#include "NetworkConnectionMonitor.h"
NetworkConnectionMonitor::NetworkConnectionMonitor( QObject* /*parent*/ )
: m_connected( true )
{
}
NetworkConnectionMonitor::~NetworkConnectionMonitor()
{
}
bool
NetworkConnectionMonitor::isConnected() const
{
return m_connected;
}
void
NetworkConnectionMonitor::setConnected( bool connected )
{
if ( m_connected != connected )
{
m_connected = connected;
if ( connected )
emit networkUp();
else
emit networkDown();
}
}

View File

@@ -0,0 +1,46 @@
/*
Copyright 2010 Last.fm Ltd.
- Primarily authored by Jono Cole, Michael Coffey, and William Viana
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NETWORK_CONNECTION_MONITOR_H
#define NETWORK_CONNECTION_MONITOR_H
#include <lastfm/global.h>
#include <QObject>
class LASTFM_DLLEXPORT NetworkConnectionMonitor : public QObject
{
Q_OBJECT
public:
NetworkConnectionMonitor( QObject *parent = 0 );
~NetworkConnectionMonitor();
bool isConnected() const;
signals:
void networkUp();
void networkDown();
protected:
void setConnected( bool connected );
private:
bool m_connected;
};
#endif // NETWORK_CONNECTION_MONITOR_H

View File

@@ -0,0 +1,54 @@
/*
Copyright 2010 Last.fm Ltd.
- Primarily authored by Max Howell, Jono Cole and Doug Mansell
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LNETWORK_CONNECTION_MONITOR_H
#define LNETWORK_CONNECTION_MONITOR_H
#include "../NetworkConnectionMonitor.h"
#include <lastfm/global.h>
#include <QObject>
class QDBusConnection;
class QDBusInterface;
class LNetworkConnectionMonitor : public NetworkConnectionMonitor
{
Q_OBJECT
enum NMState
{
Unknown=1,
Asleep,
Connected,
Disconnected
};
public:
LNetworkConnectionMonitor( QObject* parent = 0 );
~LNetworkConnectionMonitor();
private slots:
void onStateChange( uint newState );
private:
QDBusInterface* m_nmInterface;
};
#endif // LNETWORK_CONNECTION_MONITOR_H

View File

@@ -0,0 +1,86 @@
/*
Copyright 2010 Last.fm Ltd.
- Primarily authored by Max Howell, Jono Cole and Doug Mansell
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#include "LNetworkConnectionMonitor.h"
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusReply>
LNetworkConnectionMonitor::LNetworkConnectionMonitor( QObject* parent ) :
NetworkConnectionMonitor( parent )
{
m_nmInterface = new QDBusInterface( QString( "org.freedesktop.NetworkManager" ),
QString( "/org/freedesktop/NetworkManager" ),
QString( "org.freedesktop.NetworkManager" ),
QDBusConnection::systemBus(),
this );
//get current connection state
QDBusInterface* dbusInterface = new QDBusInterface( QString( "org.freedesktop.NetworkManager" ),
QString( "/org/freedesktop/NetworkManager" ),
QString( "org.freedesktop.DBus.Properties" ),
QDBusConnection::systemBus(),
this );
QDBusReply<QVariant> reply = dbusInterface->call( "Get", "org.freedesktop.NetworkManager", "state" );
if ( reply.isValid() )
{
if ( reply.value() == Connected )
{
setConnected( true );
}
else if ( reply.value() == Disconnected )
{
setConnected( false );
}
}
else
{
qDebug() << "Error: " << reply.error();
}
delete dbusInterface;
//connect network manager signals
connect( m_nmInterface, SIGNAL( StateChange( uint ) ), this, SLOT( onStateChange( uint ) ) );
}
LNetworkConnectionMonitor::~LNetworkConnectionMonitor()
{
delete m_nmInterface;
}
void
LNetworkConnectionMonitor::onStateChange( uint newState )
{
qDebug() << "Networkmanager state change!";
if ( newState == Disconnected )
{
setConnected( false );
}
else if ( newState == Connected )
{
setConnected( true );
}
}

View File

@@ -0,0 +1,52 @@
/*
Copyright 2009 Last.fm Ltd.
- Primarily authored by Jono Cole and Michael Coffey
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MNETWORK_CONNECTION_MONITOR_H
#define MNETWORK_CONNECTION_MONITOR_H
#include "../NetworkConnectionMonitor.h"
#include <lastfm/global.h>
#include <QObject>
#ifdef Q_WS_MAC
#include <SystemConfiguration/SCNetwork.h> //TODO remove
#include <SystemConfiguration/SCNetworkReachability.h>
#endif
class __SCNetworkReachability;
class MNetworkConnectionMonitor : public NetworkConnectionMonitor
{
Q_OBJECT
public:
MNetworkConnectionMonitor( QObject* parent = 0 );
~MNetworkConnectionMonitor();
private slots:
private:
#ifdef Q_WS_MAC
static void callback( SCNetworkReachabilityRef target,
SCNetworkConnectionFlags flags,
void *info );
#endif
};
#endif // MNETWORK_CONNECTION_MONITOR_H

View File

@@ -0,0 +1,71 @@
/*
Copyright 2009 Last.fm Ltd.
- Primarily authored by Jono Cole and Michael Coffey
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#include "MNetworkConnectionMonitor.h"
#include "ws/ws.h"
#include <QPointer>
#include <SystemConfiguration/SCNetworkReachability.h>
MNetworkConnectionMonitor* context = 0;
MNetworkConnectionMonitor::MNetworkConnectionMonitor( QObject* parent ) :
NetworkConnectionMonitor( parent )
{
context = this;
SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName( NULL, LASTFM_WS_HOSTNAME );
SCNetworkReachabilityScheduleWithRunLoop( ref, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode );
SCNetworkReachabilitySetCallback( ref, callback, NULL );
CFRelease( ref );
}
MNetworkConnectionMonitor::~MNetworkConnectionMonitor()
{
}
void
MNetworkConnectionMonitor::callback( SCNetworkReachabilityRef target,
SCNetworkConnectionFlags flags,
void * )
{
static bool up = true;
// I couldn't find any diffinitive usage examples for these flags
// so I had to guess, since I can't test, eg. dial up :(
bool b;
if (flags & kSCNetworkFlagsConnectionRequired)
b = false;
else
b = flags & (kSCNetworkFlagsReachable | kSCNetworkFlagsTransientConnection | kSCNetworkFlagsConnectionAutomatic);
qDebug() << "Can reach " LASTFM_WS_HOSTNAME ":" << b << ", flags:" << flags;
// basically, avoids telling everyone that we're up already on startup
if (up == b)
return;
up = b;
context->setConnected(b);
}

View File

@@ -0,0 +1,75 @@
/*
Copyright 2009 Last.fm Ltd.
- Primarily authored by Max Howell, Jono Cole and Doug Mansell
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#include <SystemConfiguration/SystemConfiguration.h>
struct ProxyDict
{
ProxyDict();
int port;
QString host;
bool isProxyEnabled() const { return port > 0 && host.size(); }
};
inline ProxyDict::ProxyDict() : port( 0 )
{
// Get the dictionary.
CFDictionaryRef proxyDict = SCDynamicStoreCopyProxies( NULL );
bool result = (proxyDict != NULL);
// Get the enable flag. This isn't a CFBoolean, but a CFNumber.
CFNumberRef enableNum;
int enable;
if (result) {
enableNum = (CFNumberRef) CFDictionaryGetValue( proxyDict, kSCPropNetProxiesHTTPEnable );
result = (enableNum != NULL) && (CFGetTypeID(enableNum) == CFNumberGetTypeID());
}
if (result)
result = CFNumberGetValue( enableNum, kCFNumberIntType, &enable ) && (enable != 0);
// Get the proxy host. DNS names must be in ASCII. If you
// put a non-ASCII character in the "Secure Web Proxy"
// field in the Network preferences panel, the CFStringGetCString
// function will fail and this function will return false.
CFStringRef hostStr;
if (result) {
hostStr = (CFStringRef) CFDictionaryGetValue( proxyDict, kSCPropNetProxiesHTTPProxy );
result = (hostStr != NULL) && (CFGetTypeID(hostStr) == CFStringGetTypeID());
}
if (result)
host = lastfm::CFStringToQString( hostStr );
// get the proxy port
CFNumberRef portNum;
if (result) {
portNum = (CFNumberRef) CFDictionaryGetValue( proxyDict, kSCPropNetProxiesHTTPPort );
result = (portNum != NULL) && (CFGetTypeID(portNum) == CFNumberGetTypeID());
}
if (result)
result = CFNumberGetValue( portNum, kCFNumberIntType, &port );
// clean up.
if (proxyDict != NULL)
CFRelease( proxyDict );
}

View File

@@ -0,0 +1,63 @@
/*
Copyright 2009 Last.fm Ltd.
- Primarily authored by Max Howell, Jono Cole and Doug Mansell
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _WIN32_WINNT
// bring in CoInitializeSecurity from objbase.h
#define _WIN32_WINNT 0x0400
#endif
#include <objbase.h>
#include <atlbase.h>
#include <atlcom.h>
/** @brief WsConnectionMonitor needs Com to work as early as possible so we do this
* @author <doug@last.fm>
*/
class ComSetup
{
public:
ComSetup()
{
HRESULT hr = CoInitialize(0);
m_bComInitialised = SUCCEEDED(hr);
_ASSERT(m_bComInitialised);
if (m_bComInitialised) {
setupSecurity();
}
}
void setupSecurity()
{
CSecurityDescriptor sd;
sd.InitializeFromThreadToken();
HRESULT hr = CoInitializeSecurity(sd, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
_ASSERT(SUCCEEDED(hr));
}
~ComSetup()
{
if (m_bComInitialised) {
CoUninitialize();
}
}
private:
bool m_bComInitialised;
};

View File

@@ -0,0 +1,43 @@
/*
Copyright 2009 Last.fm Ltd.
- Primarily authored by Max Howell, Jono Cole and Doug Mansell
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#include <windows.h>
#include <winhttp.h>
/** @brief memory managing wrapper for WINHTTP_CURRENT_USER_IE_PROXY_CONFIG
* @author <doug@last.fm>
*/
struct IeSettings : WINHTTP_CURRENT_USER_IE_PROXY_CONFIG
{
IeSettings()
{
if (!WinHttpGetIEProxyConfigForCurrentUser(this)) {
fAutoDetect = FALSE;
lpszAutoConfigUrl = lpszProxy = lpszProxyBypass = 0;
}
}
~IeSettings()
{
if (lpszAutoConfigUrl) GlobalFree(lpszAutoConfigUrl);
if (lpszProxy) GlobalFree(lpszProxy);
if (lpszProxyBypass) GlobalFree(lpszProxyBypass);
}
};

View File

@@ -0,0 +1,87 @@
/*
Copyright 2009 Last.fm Ltd.
- Primarily authored by Max Howell, Jono Cole and Doug Mansell
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#include "NdisEvents.h"
#include "WmiSink.h"
// see http://msdn.microsoft.com/en-us/magazine/cc301850.aspx for
// more about Ndis and wmi and getting these events
// Link to wbemuuid.lib to resolve IWbemObjectSink and IWbemClassObject
// interface definitions.
NdisEvents::NdisEvents()
: m_pSink(0)
{}
NdisEvents::~NdisEvents()
{
if (m_pSink)
m_pSink->disconnect();
if (m_pServices && m_pSink)
m_pServices->CancelAsyncCall(m_pSink);
// and reference counting will take care of the WmiSink object
}
HRESULT
NdisEvents::registerForNdisEvents()
{
HRESULT hr = m_pLocator.CoCreateInstance(CLSID_WbemLocator);
if (FAILED(hr))
return hr;
// Connect to the root\wmi namespace with the current user.
hr = m_pLocator->ConnectServer(CComBSTR("ROOT\\WMI"), // strNetworkResource
NULL, // strUser
NULL, // strPassword
NULL, // strLocale
0, // lSecurityFlags
CComBSTR(""), // strAuthority
NULL, // pCtx
&m_pServices
);
if (FAILED(hr))
return hr;
m_pSink = new WmiSink(this);
//////////////////////////
// other notifications we're not interested in right now include...
// MSNdis_NotifyAdapterArrival \DEVICE\<guid>
// MSNdis_NotifyAdapterRemoval
// MSNdis_StatusLinkSpeedChange
// MSNdis_NotifyVcArrival
// MSNdis_NotifyVcRemoval
// MSNdis_StatusResetStart
// MSNdis_StatusResetEnd
// MSNdis_StatusProtocolBind
// MSNdis_StatusProtocolUnbind
// MSNdis_StatusMediaSpecificIndication
CComBSTR wql("WQL");
CComBSTR query("SELECT * FROM MSNdis_StatusMediaDisconnect");
hr = m_pServices->ExecNotificationQueryAsync(wql, query, 0, 0, m_pSink);
query = "SELECT * FROM MSNdis_StatusMediaConnect";
hr = m_pServices->ExecNotificationQueryAsync(wql, query, 0, 0, m_pSink);
return S_OK;
}

View File

@@ -0,0 +1,44 @@
/*
Copyright 2009 Last.fm Ltd.
- Primarily authored by Max Howell, Jono Cole and Doug Mansell
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NDIS_EVENTS_H
#define NDIS_EVENTS_H
#include <windows.h>
#include <atlbase.h>
#include <WbemCli.h>
class NdisEvents
{
public:
NdisEvents();
~NdisEvents();
HRESULT registerForNdisEvents();
virtual void onConnectionUp(BSTR name) = 0;
virtual void onConnectionDown(BSTR name) = 0;
private:
CComPtr<IWbemLocator> m_pLocator;
CComPtr<IWbemServices> m_pServices;
class WmiSink *m_pSink;
};
#endif

128
thirdparty/liblastfm2/src/ws/win/Pac.cpp vendored Normal file
View File

@@ -0,0 +1,128 @@
/*
Copyright 2009 Last.fm Ltd.
- Primarily authored by Max Howell, Jono Cole and Doug Mansell
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Pac.h"
#include <QNetworkRequest>
#include <QStringList>
#include <QUrl>
#include <atlbase.h>
#include <atlconv.h>
static bool
parsePacServer(const QString &s, QNetworkProxy &p)
{
// remove optional leading "scheme=" portion
int start = s.indexOf('=');
QUrl url(s.mid(start+1), QUrl::TolerantMode);
if (url.isValid())
{
p.setHostName(url.host());
p.setPort(url.port());
return true;
}
return false;
}
static QList<QNetworkProxy>
parsePacResult(const QString &pacResult)
{
// msdn says: "The proxy server list contains one or more of the
// following strings separated by semicolons or whitespace."
// ([<scheme>=][<scheme>"://"]<server>[":"<port>])
QList<QNetworkProxy> result;
QStringList proxies = pacResult.split(QRegExp("[\\s;]"), QString::SkipEmptyParts);
foreach(const QString &s, proxies)
{
QNetworkProxy proxy( QNetworkProxy::HttpProxy );
if (parsePacServer(s, proxy))
{
result << proxy;
}
}
return result;
}
////////////////
lastfm::Pac::Pac()
: m_bFailed( false )
, m_hSession( 0 )
{}
lastfm::Pac::~Pac()
{
if (m_hSession)
WinHttpCloseHandle(m_hSession);
}
QNetworkProxy
lastfm::Pac::resolve(const QNetworkRequest &request, const wchar_t* pacUrl)
{
QNetworkProxy out;
if (m_bFailed) return out;
if (!m_hSession)
{
QByteArray user_agent = request.rawHeader("user-agent");
m_hSession = WinHttpOpen(CA2W(user_agent), WINHTTP_ACCESS_TYPE_NO_PROXY, 0, 0, WINHTTP_FLAG_ASYNC);
}
if (m_hSession)
{
WINHTTP_PROXY_INFO info;
WINHTTP_AUTOPROXY_OPTIONS opts;
memset(&opts, 0, sizeof(opts));
if (pacUrl)
{
opts.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
opts.lpszAutoConfigUrl = pacUrl;
}
else
{
opts.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
opts.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
}
opts.fAutoLogonIfChallenged = TRUE;
if (WinHttpGetProxyForUrl(m_hSession, request.url().toString().utf16(), &opts, &info)) {
if (info.lpszProxy)
{
QList<QNetworkProxy> proxies = parsePacResult(QString::fromUtf16(info.lpszProxy));
if (!proxies.empty())
{
out = proxies.at(0);
}
GlobalFree(info.lpszProxy);
}
if (info.lpszProxyBypass)
{
GlobalFree(info.lpszProxyBypass);
}
} else {
m_bFailed = true;
}
}
return out;
}

52
thirdparty/liblastfm2/src/ws/win/Pac.h vendored Normal file
View File

@@ -0,0 +1,52 @@
/*
Copyright 2009 Last.fm Ltd.
- Primarily authored by Max Howell, Jono Cole and Doug Mansell
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WS_AUTOPROXY_H
#define WS_AUTOPROXY_H
#include <QNetworkProxy>
#include <windows.h>
#include <winhttp.h>
class QNetworkRequest;
namespace lastfm
{
/** @brief simple wrapper to do per url automatic proxy detection
* @author <doug@last.fm>
*/
class Pac
{
HINTERNET m_hSession;
bool m_bFailed;
public:
Pac();
~Pac();
QNetworkProxy resolve( const QNetworkRequest& url, const wchar_t* pacUrl );
void resetFailedState() { m_bFailed = false; }
private:
Pac( const Pac& ); //undefined
Pac operator=( const Pac& ); //undefined
};
}
#endif

View File

@@ -0,0 +1,44 @@
/*
Copyright 2010 Last.fm Ltd.
- Primarily authored by Jono Cole, Michael Coffey, and William Viana
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WNETWORK_CONNECTION_MONITOR_H
#define WNETWORK_CONNECTION_MONITOR_H
#include "../NetworkConnectionMonitor.h"
#include <lastfm/global.h>
#include <QObject>
namespace lastfm { class NdisEventsProxy; }
class WNetworkConnectionMonitor : public NetworkConnectionMonitor
{
Q_OBJECT
public:
friend class lastfm::NdisEventsProxy;
WNetworkConnectionMonitor( QObject* parent = 0 );
~WNetworkConnectionMonitor();
private:
lastfm::NdisEventsProxy* m_ndisEventsProxy;
};
#endif // WNETWORK_CONNECTION_MONITOR_H

View File

@@ -0,0 +1,67 @@
/*
Copyright 2010 Last.fm Ltd.
- Primarily authored by Jono Cole, Michael Coffey, and William Viana
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#include "WNetworkConnectionMonitor.h"
// WsAccessManager needs special init (on Windows), and it needs to be done
// early, so be careful about moving this
#include "../win/ComSetup.h" //must be first header or compile fail results!
#include "../win/NdisEvents.h"
static ComSetup com_setup;
namespace lastfm {
// bounce NdisEvents signals through here so we don't have to expose the
// NdisEvents interface in InternetConnectionMonitor :)
class NdisEventsProxy : public NdisEvents
{
public:
NdisEventsProxy(WNetworkConnectionMonitor* icm)
:m_icm(icm)
{
}
// WmiSink callbacks:
void onConnectionUp( BSTR /*name*/ )
{
m_icm->setConnected( true );
}
void onConnectionDown( BSTR /*name*/ )
{
m_icm->setConnected( false );
}
WNetworkConnectionMonitor* m_icm;
};
}
WNetworkConnectionMonitor::WNetworkConnectionMonitor( QObject* parent ) :
NetworkConnectionMonitor( parent )
{
m_ndisEventsProxy = new lastfm::NdisEventsProxy( this );
m_ndisEventsProxy->registerForNdisEvents();
}
WNetworkConnectionMonitor::~WNetworkConnectionMonitor()
{
delete m_ndisEventsProxy;
}

View File

@@ -0,0 +1,202 @@
/*
Copyright 2009 Last.fm Ltd.
- Primarily authored by Max Howell, Jono Cole and Doug Mansell
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#include "WmiSink.h"
#include "NdisEvents.h"
WmiSink::WmiSink(NdisEvents *callback)
: m_cRef(1)
, m_callback(callback)
{}
WmiSink::~WmiSink()
{}
void
WmiSink::disconnect()
{
m_callback = 0;
}
STDMETHODIMP
WmiSink::QueryInterface(REFIID riid, LPVOID * ppv)
{
*ppv = 0;
if (IID_IUnknown==riid || IID_IWbemObjectSink == riid)
{
*ppv = (IWbemObjectSink *) this;
AddRef();
return NOERROR;
}
return E_NOINTERFACE;
}
ULONG
WmiSink::AddRef()
{
return ++m_cRef;
}
ULONG
WmiSink::Release()
{
if (0 != --m_cRef)
return m_cRef;
delete this;
return 0;
}
// This method receives notification objects.
HRESULT
WmiSink::Indicate(long lObjectCount, IWbemClassObject** ppObjArray)
{
// For each object in the array, extract the object and display the
// information in the object.
for (long i=0; i<lObjectCount; i++)
{
CComVariant vt, vtClass;
ppObjArray[i]->Get(L"InstanceName", 0, &vt, NULL, NULL);
ppObjArray[i]->Get(L"__Class", 0, &vtClass, NULL, NULL);
if (!wcscmp (vtClass.bstrVal, L"MSNdis_StatusMediaDisconnect"))
{
if (m_callback) m_callback->onConnectionDown(vt.bstrVal);
}
else if (!wcscmp (vtClass.bstrVal, L"MSNdis_StatusMediaConnect"))
{
if (m_callback) m_callback->onConnectionUp(vt.bstrVal);
}
// notifications we aren't interested in right now:
//
//else if (!wcscmp (vtClass.bstrVal, L"MSNdis_NotifyAdapterRemoval"))
//{
// bstrLog = (_bstr_t) vt.bstrVal;
// VariantClear (&vt);
// ppObjArray[i]->Get (L"DeviceName", 0, &vt, NULL, NULL);
// bstrLog += (_bstr_t) _T(": ") + (_bstr_t) vt.bstrVal + (_bstr_t) _T(" has been removed");
// displayDlg.LogEvent (bstrLog);
//}
//else if (!wcscmp (vtClass.bstrVal, L"MSNdis_NotifyAdapterArrival"))
//{
// bstrLog = (_bstr_t) vt.bstrVal;
// VariantClear (&vt);
// ppObjArray[i]->Get(L"DeviceName", 0, &vt, NULL, NULL);
// bstrLog += (_bstr_t) _T(": ") + (_bstr_t) vt.bstrVal + (_bstr_t) _T(" has been added");
// displayDlg.LogEvent (bstrLog);
//}
//else if (!wcscmp (vtClass.bstrVal, L"MSNdis_StatusResetStart"))
//{
// bstrLog = (_bstr_t) vt.bstrVal + (_bstr_t) _T(" has begun a reset");
// displayDlg.LogEvent (bstrLog);
//}
//else if (!wcscmp (vtClass.bstrVal, L"MSNdis_StatusResetEnd"))
//{
// bstrLog = (_bstr_t) vt.bstrVal + (_bstr_t) _T(" has finished a reset");
// displayDlg.LogEvent (bstrLog);
//}
//else if (!wcscmp (vtClass.bstrVal, L"MSNdis_NotifyVcArrival"))
//{
// bstrLog = (_bstr_t) _T("VC arrival: ") + (_bstr_t) vt.bstrVal;
// displayDlg.LogEvent (bstrLog);
//}
//else if (!wcscmp (vtClass.bstrVal, L"MSNdis_NotifyVcRemoval"))
//{
// bstrLog = (_bstr_t) _T("VC removal: ") + (_bstr_t) vt.bstrVal;
// displayDlg.LogEvent (bstrLog);
//}
//else if (!wcscmp (vtClass.bstrVal, L"MSNdis_StatusMediaSpecificIndication"))
//{
// ATLTRACE (_T("Media specific indication: %s\n"), (TCHAR *) (_bstr_t) vt.bstrVal);
// VariantClear (&vt);
// ppObjArray[i]->Get (L"NdisStatusMediaSpecificIndication", 0, &vt, NULL, NULL);
// LONG lLowerBound, lUpperBound, j;
// UCHAR ch;
// SafeArrayGetLBound (V_ARRAY (&vt), 1, &lLowerBound);
// SafeArrayGetUBound (V_ARRAY (&vt), 1, &lUpperBound);
// ATLTRACE (" ");
// for (j = lLowerBound; j<= lUpperBound; j++ )
// {
// SafeArrayGetElement (V_ARRAY (&vt), &j, &ch);
// ATLTRACE (_T("%4i"), ch);
// if (((j - lLowerBound) % 8 == 7) && (j <= lUpperBound))
// ATLTRACE (_T("\n"));
// }
//}
//else if (!wcscmp (vtClass.bstrVal, L"MSNdis_StatusProtocolBind"))
//{
// bstrLog = (_bstr_t) vt.bstrVal;
// VariantClear (&vt);
// ppObjArray[i]->Get (L"Transport", 0, &vt, NULL, NULL);
// bstrLog += (_bstr_t) _T(" is now bound to ") + (_bstr_t) vt.bstrVal;
// displayDlg.LogEvent (bstrLog);
//}
//else if (!wcscmp (vtClass.bstrVal, L"MSNdis_StatusProtocolBind"))
//{
// bstrLog = (_bstr_t) vt.bstrVal;
// VariantClear (&vt);
// ppObjArray[i]->Get(L"Transport", 0, &vt, NULL, NULL);
// bstrLog += (_bstr_t) _T(" was unbound from ") + (_bstr_t) vt.bstrVal;
// displayDlg.LogEvent (bstrLog);
//}
//else if (!wcscmp (vtClass.bstrVal, L"MSNdis_StatusLinkSpeedChange"))
//{
// IWbemClassObject* pWMIObj=NULL;
// bstrLog = (_bstr_t) _T("Link speed change ") + (_bstr_t) vt.bstrVal;
// VariantClear (&vt);
// ppObjArray[i]->Get (L"NdisStatusLinkSpeedChange", 0, &vt, NULL, NULL);
// if SUCCEEDED (vt.punkVal->QueryInterface (IID_IWbemClassObject, (void**)&pWMIObj))
// {
// TCHAR szNum[50];
// pWMIObj->Get (L"Inbound", 0, &vt2, NULL, NULL);
// _stprintf (szNum, _T(" Inbound = %u "), vt2.lVal);
// bstrLog += (_bstr_t) szNum;
// VariantClear (&vt2);
// pWMIObj->Get (L"Outbound", 0, &vt2, NULL, NULL);
// _stprintf (szNum, _T(" Outbound = %u "), vt2.lVal);
// bstrLog += (_bstr_t) szNum;
// VariantClear (&vt2);
// pWMIObj->Release ();
// pWMIObj = NULL;
// }
// displayDlg.LogEvent (bstrLog);
//}
VariantClear (&vtClass);
VariantClear (&vt);
}
return WBEM_NO_ERROR;
}
// Misc. status codes sent by sink.
HRESULT
WmiSink::SetStatus(long lFlags, HRESULT hResult, BSTR strParam, IWbemClassObject __RPC_FAR *pObjParam)
{
lFlags;
hResult;
strParam;
pObjParam;
return WBEM_NO_ERROR;
}

View File

@@ -0,0 +1,49 @@
/*
Copyright 2009 Last.fm Ltd.
- Primarily authored by Max Howell, Jono Cole and Doug Mansell
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WMISINK_WIN_H
#define WMISINK_WIN_H
#include "WbemCli.h"
// Sink object for WMI NDIS notifications
class WmiSink : public IWbemObjectSink
{
UINT m_cRef;
public:
WmiSink(class NdisEvents *callback);
~WmiSink();
// IUnknown members
STDMETHODIMP QueryInterface(REFIID, LPVOID *);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
// IWbemObjectSink
STDMETHODIMP Indicate(long, IWbemClassObject**);
STDMETHODIMP SetStatus(long, HRESULT, BSTR, IWbemClassObject *);
void disconnect();
private:
class NdisEvents *m_callback;
};
#endif

268
thirdparty/liblastfm2/src/ws/ws.cpp vendored Normal file
View File

@@ -0,0 +1,268 @@
/*
Copyright 2009 Last.fm Ltd.
- Primarily authored by Max Howell, Jono Cole and Doug Mansell
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ws.h"
#include "../core/misc.h"
#include "NetworkAccessManager.h"
#include <QCoreApplication>
#include <QDomDocument>
#include <QDomElement>
#include <QLocale>
#include <QStringList>
#include <QUrl>
static QNetworkAccessManager* nam = 0;
QString
lastfm::ws::host()
{
QStringList const args = QCoreApplication::arguments();
if (args.contains( "--debug"))
return "ws.staging.audioscrobbler.com";
int const n = args.indexOf( "--host" );
if (n != -1 && args.count() > n+1)
return args[n+1];
return LASTFM_WS_HOSTNAME;
}
static QUrl url()
{
QUrl url;
url.setScheme( "http" );
url.setHost( lastfm::ws::host() );
url.setPath( "/2.0/" );
return url;
}
static QString iso639()
{
return QLocale().name().left( 2 ).toLower();
}
void autograph( QMap<QString, QString>& params )
{
params["api_key"] = lastfm::ws::ApiKey;
params["lang"] = iso639();
}
static void sign( QMap<QString, QString>& params, bool sk = true )
{
autograph( params );
// it's allowed for sk to be null if we this is an auth call for instance
if (sk && lastfm::ws::SessionKey.size())
params["sk"] = lastfm::ws::SessionKey;
QString s;
QMapIterator<QString, QString> i( params );
while (i.hasNext()) {
i.next();
s += i.key() + i.value();
}
s += lastfm::ws::SharedSecret;
params["api_sig"] = lastfm::md5( s.toUtf8() );
}
QNetworkReply*
lastfm::ws::get( QMap<QString, QString> params )
{
sign( params );
QUrl url = ::url();
// Qt setQueryItems doesn't encode a bunch of stuff, so we do it manually
QMapIterator<QString, QString> i( params );
while (i.hasNext()) {
i.next();
QByteArray const key = QUrl::toPercentEncoding( i.key() );
QByteArray const value = QUrl::toPercentEncoding( i.value() );
url.addEncodedQueryItem( key, value );
}
qDebug() << url;
return nam()->get( QNetworkRequest(url) );
}
QNetworkReply*
lastfm::ws::post( QMap<QString, QString> params, bool sk )
{
sign( params, sk );
QByteArray query;
QMapIterator<QString, QString> i( params );
while (i.hasNext()) {
i.next();
query += QUrl::toPercentEncoding( i.key() )
+ '='
+ QUrl::toPercentEncoding( i.value() )
+ '&';
}
return nam()->post( QNetworkRequest(url()), query );
}
QByteArray
lastfm::ws::parse( QNetworkReply* reply ) throw( ParseError )
{
try
{
QByteArray data = reply->readAll();
if (!data.size())
throw MalformedResponse;
QDomDocument xml;
xml.setContent( data );
QDomElement lfm = xml.documentElement();
if (lfm.isNull())
throw MalformedResponse;
QString const status = lfm.attribute( "status" );
QDomElement error = lfm.firstChildElement( "error" );
uint const n = lfm.childNodes().count();
// no elements beyond the lfm is perfectably acceptable <-- wtf?
// if (n == 0) // nothing useful in the response
if (status == "failed" || (n == 1 && !error.isNull()) )
throw error.isNull()
? MalformedResponse
: Error( error.attribute( "code" ).toUInt() );
switch (reply->error())
{
case QNetworkReply::RemoteHostClosedError:
case QNetworkReply::ConnectionRefusedError:
case QNetworkReply::TimeoutError:
case QNetworkReply::ContentAccessDenied:
case QNetworkReply::ContentOperationNotPermittedError:
case QNetworkReply::UnknownContentError:
case QNetworkReply::ProtocolInvalidOperationError:
case QNetworkReply::ProtocolFailure:
throw TryAgainLater;
case QNetworkReply::NoError:
default:
break;
}
//FIXME pretty wasteful to parse XML document twice..
return data;
}
catch (Error e)
{
switch (e)
{
case OperationFailed:
case InvalidApiKey:
case InvalidSessionKey:
// NOTE will never be received during the LoginDialog stage
// since that happens before this slot is registered with
// QMetaObject in App::App(). Neat :)
QMetaObject::invokeMethod( qApp, "onWsError", Q_ARG( lastfm::ws::Error, e ) );
default:
throw ParseError(e);
}
}
// bit dodgy, but prolly for the best
reply->deleteLater();
}
QNetworkAccessManager*
lastfm::nam()
{
if (!::nam) ::nam = new NetworkAccessManager( qApp );
return ::nam;
}
void
lastfm::setNetworkAccessManager( QNetworkAccessManager* nam )
{
delete ::nam;
::nam = nam;
nam->setParent( qApp ); // ensure it isn't deleted out from under us
}
/** This useful function, fromHttpDate, comes from QNetworkHeadersPrivate
* in qnetworkrequest.cpp. Qt copyright and license apply. */
static QDateTime QByteArrayToHttpDate(const QByteArray &value)
{
// HTTP dates have three possible formats:
// RFC 1123/822 - ddd, dd MMM yyyy hh:mm:ss "GMT"
// RFC 850 - dddd, dd-MMM-yy hh:mm:ss "GMT"
// ANSI C's asctime - ddd MMM d hh:mm:ss yyyy
// We only handle them exactly. If they deviate, we bail out.
int pos = value.indexOf(',');
QDateTime dt;
if (pos == -1) {
// no comma -> asctime(3) format
dt = QDateTime::fromString(QString::fromLatin1(value), Qt::TextDate);
} else {
// eat the weekday, the comma and the space following it
QString sansWeekday = QString::fromLatin1(value.constData() + pos + 2);
QLocale c = QLocale::c();
if (pos == 3)
// must be RFC 1123 date
dt = c.toDateTime(sansWeekday, QLatin1String("dd MMM yyyy hh:mm:ss 'GMT"));
else
// must be RFC 850 date
dt = c.toDateTime(sansWeekday, QLatin1String("dd-MMM-yy hh:mm:ss 'GMT'"));
}
if (dt.isValid())
dt.setTimeSpec(Qt::UTC);
return dt;
}
QDateTime
lastfm::ws::expires( QNetworkReply* reply )
{
return QByteArrayToHttpDate( reply->rawHeader( "Expires" ) );
}
namespace lastfm
{
namespace ws
{
QString SessionKey;
QString Username;
/** we leave these unset as you can't use the webservices without them
* so lets make the programmer aware of it during testing by crashing */
const char* SharedSecret;
const char* ApiKey;
/** if this is found set to "" we conjure ourselves a suitable one */
const char* UserAgent = 0;
}
}
QDebug operator<<( QDebug, lastfm::ws::Error );

161
thirdparty/liblastfm2/src/ws/ws.h vendored Normal file
View File

@@ -0,0 +1,161 @@
/*
Copyright 2009 Last.fm Ltd.
- Primarily authored by Max Howell, Jono Cole and Doug Mansell
This file is part of liblastfm.
liblastfm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liblastfm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LASTFM_WS_H
#define LASTFM_WS_H
#include <lastfm/global.h>
#include <QDateTime>
#include <QMap>
#include <QNetworkReply>
#include <stdexcept>
#ifdef Q_CC_MSVC
// ms admits its lousy compiler doesn't care about throw declarations
#pragma warning( disable : 4290 )
#endif
namespace lastfm
{
/** if you don't set one, we create our own, our own is pretty good
* for instance, it auto detects proxy settings on windows and mac
* We take ownership of the NAM, do not delete it out from underneath us!
* So don't keep any other pointers to this around in case you accidently
* call delete on them :P */
LASTFM_DLLEXPORT void setNetworkAccessManager( QNetworkAccessManager* nam );
LASTFM_DLLEXPORT QNetworkAccessManager* nam();
namespace ws
{
/** both of these are provided when you register at http://last.fm/api */
LASTFM_DLLEXPORT extern const char* SharedSecret;
LASTFM_DLLEXPORT extern const char* ApiKey;
/** you need to set this for scrobbling to work (for now)
* Also the AuthenticatedUser class uses it */
LASTFM_DLLEXPORT extern QString Username;
/** Some webservices require authentication. See the following
* documentation:
* http://www.last.fm/api/authentication
* http://www.last.fm/api/desktopauth
* You have to authenticate and then assign to SessionKey, liblastfm does
* not do that for you. Also we do not store this. You should store this!
* You only need to authenticate once, and that key lasts forever!
*/
LASTFM_DLLEXPORT extern QString SessionKey;
enum Error
{
NoError = 1, // because last.fm error numbers start at 2
/** numbers follow those at http://last.fm/api/ */
InvalidService = 2,
InvalidMethod,
AuthenticationFailed,
InvalidFormat,
InvalidParameters,
InvalidResourceSpecified,
OperationFailed,
InvalidSessionKey,
InvalidApiKey,
ServiceOffline,
SubscribersOnly,
Reserved13,
Reserved14,
Reserved15,
/** Last.fm sucks.
* There may be an error in networkError(), or this may just be some
* internal error completing your request.
* Advise the user to try again in a _few_minutes_.
* For some cases, you may want to try again yourself, at this point
* in the API you will have to. Eventually we will discourage this and
* do it for you, as we don't want to strain Last.fm's servers
*/
TryAgainLater = 16,
Reserved17,
Reserved18,
Reserved19,
NotEnoughContent = 20,
NotEnoughMembers,
NotEnoughFans,
NotEnoughNeighbours,
/** Last.fm fucked up, or something mangled the response on its way */
MalformedResponse = 100,
/** call QNetworkReply::error() as it's nothing to do with us */
UnknownError
};
LASTFM_DLLEXPORT QString host();
/** the map needs a method entry, as per http://last.fm/api */
LASTFM_DLLEXPORT QNetworkReply* get( QMap<QString, QString> );
/** generates api sig, includes api key, and posts, don't add the api
* key yourself as well--it'll break */
LASTFM_DLLEXPORT QNetworkReply* post( QMap<QString, QString>, bool sessionKey = true );
class ParseError : public std::runtime_error
{
Error e;
public:
explicit ParseError(Error e) : std::runtime_error("lastfm::ws::Error"), e(e)
{}
Error enumValue() const { return e; }
};
/** Generally you don't use this, eg. if you called Artist::getInfo(),
* use the Artist::getInfo( QNetworkReply* ) function to get the
* results, you have to pass a QDomDocument because QDomElements stop
* existing when the parent DomDocument is deleted.
*
* The QByteArray is basically reply->readAll(), so all this function
* does is sanity check the response and throw if it is bad.
*
* Thus if you don't care about errors just do: reply->readAll()
*
* Not caring about errors is often fine with Qt as you just get null
* strings and that instead, and you can handle those as you go.
*
* The QByteArray is an XML document. You can parse it with QDom or
* use our much more convenient lastfm::XmlQuery.
*/
LASTFM_DLLEXPORT QByteArray parse( QNetworkReply* reply ) throw( ParseError );
/** returns the expiry date of this HTTP response */
LASTFM_DLLEXPORT QDateTime expires( QNetworkReply* );
}
}
inline QDebug operator<<( QDebug d, QNetworkReply::NetworkError e )
{
return d << lastfm::qMetaEnumString<QNetworkReply>( e, "NetworkError" );
}
#define LASTFM_WS_HOSTNAME "ws.audioscrobbler.com"
#endif