mirror of https://github.com/cutefishos/calamares
Merge branch 'shuffle-geoip'
commit
c3754126d0
@ -0,0 +1,183 @@
|
||||
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2019, Adriaan de Groot <groot@kde.org>
|
||||
*
|
||||
* Calamares 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.
|
||||
*
|
||||
* Calamares 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 Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Handler.h"
|
||||
|
||||
#include "GeoIPJSON.h"
|
||||
#if defined(QT_XML_LIB)
|
||||
#include "GeoIPXML.h"
|
||||
#endif
|
||||
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/NamedEnum.h"
|
||||
#include "utils/Variant.h"
|
||||
|
||||
#include <QEventLoop>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include <memory>
|
||||
|
||||
static const NamedEnumTable< CalamaresUtils::GeoIP::Handler::Type >&
|
||||
handlerTypes()
|
||||
{
|
||||
using Type = CalamaresUtils::GeoIP::Handler::Type;
|
||||
|
||||
static const NamedEnumTable<Type> names{
|
||||
{ QStringLiteral( "none" ), Type::None},
|
||||
{ QStringLiteral( "json" ), Type::JSON},
|
||||
{ QStringLiteral( "xml" ), Type::XML}
|
||||
};
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
namespace CalamaresUtils::GeoIP
|
||||
{
|
||||
|
||||
Handler::Handler()
|
||||
: m_type( Type::None )
|
||||
{
|
||||
}
|
||||
|
||||
Handler::Handler( const QString& implementation, const QString& url, const QString& selector )
|
||||
: m_type( Type::None )
|
||||
, m_url( url )
|
||||
, m_selector( selector )
|
||||
{
|
||||
bool ok = false;
|
||||
m_type = handlerTypes().find( implementation, ok );
|
||||
#if !defined(QT_XML_LIB)
|
||||
if ( m_type == Type::XML )
|
||||
{
|
||||
m_type = Type::None;
|
||||
cWarning() << "GeoIP style XML is not supported in this version of Calamares.";
|
||||
}
|
||||
#endif
|
||||
if ( !ok )
|
||||
{
|
||||
cWarning() << "GeoIP Style" << implementation << "is not recognized.";
|
||||
}
|
||||
}
|
||||
|
||||
Handler::~Handler()
|
||||
{
|
||||
}
|
||||
|
||||
static QByteArray
|
||||
synchronous_get( const QString& urlstring )
|
||||
{
|
||||
QUrl url( urlstring );
|
||||
QNetworkAccessManager manager;
|
||||
QEventLoop loop;
|
||||
|
||||
QObject::connect( &manager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit );
|
||||
|
||||
QNetworkRequest request( url );
|
||||
QNetworkReply* reply = manager.get( request );
|
||||
loop.exec();
|
||||
reply->deleteLater();
|
||||
return reply->readAll();
|
||||
}
|
||||
|
||||
static std::unique_ptr< Interface >
|
||||
create_interface( Handler::Type t, const QString& selector )
|
||||
{
|
||||
switch( t )
|
||||
{
|
||||
case Handler::Type::None:
|
||||
return nullptr;
|
||||
case Handler::Type::JSON:
|
||||
return std::make_unique< GeoIPJSON >( selector );
|
||||
case Handler::Type::XML:
|
||||
#if defined(QT_XML_LIB)
|
||||
return std::make_unique< GeoIPXML >( selector );
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
default: // there are no others
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static RegionZonePair
|
||||
do_query( Handler::Type type, const QString& url, const QString& selector )
|
||||
{
|
||||
const auto interface = create_interface( type, selector );
|
||||
if ( !interface )
|
||||
return RegionZonePair();
|
||||
|
||||
return interface->processReply( synchronous_get( url ) );
|
||||
}
|
||||
|
||||
static QString
|
||||
do_raw_query( Handler::Type type, const QString& url, const QString& selector )
|
||||
{
|
||||
const auto interface = create_interface( type, selector );
|
||||
if ( !interface )
|
||||
return QString();
|
||||
|
||||
return interface->rawReply( synchronous_get( url ) );
|
||||
}
|
||||
|
||||
RegionZonePair
|
||||
Handler::get() const
|
||||
{
|
||||
if ( !isValid() )
|
||||
return RegionZonePair();
|
||||
return do_query( m_type, m_url, m_selector );
|
||||
}
|
||||
|
||||
|
||||
QFuture< RegionZonePair >
|
||||
Handler::query() const
|
||||
{
|
||||
Handler::Type type = m_type;
|
||||
QString url = m_url;
|
||||
QString selector = m_selector;
|
||||
|
||||
return QtConcurrent::run( [=]
|
||||
{
|
||||
return do_query( type, url, selector );
|
||||
} );
|
||||
}
|
||||
|
||||
QString
|
||||
Handler::getRaw() const
|
||||
{
|
||||
if ( !isValid() )
|
||||
return QString();
|
||||
return do_raw_query( m_type, m_url, m_selector );
|
||||
}
|
||||
|
||||
|
||||
QFuture< QString >
|
||||
Handler::queryRaw() const
|
||||
{
|
||||
Handler::Type type = m_type;
|
||||
QString url = m_url;
|
||||
QString selector = m_selector;
|
||||
|
||||
return QtConcurrent::run( [=]
|
||||
{
|
||||
return do_raw_query( type, url, selector );
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
@ -0,0 +1,91 @@
|
||||
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2019, Adriaan de Groot <groot@kde.org>
|
||||
*
|
||||
* Calamares 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.
|
||||
*
|
||||
* Calamares 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 Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GEOIP_HANDLER_H
|
||||
#define GEOIP_HANDLER_H
|
||||
|
||||
#include "Interface.h"
|
||||
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
#include <QString>
|
||||
#include <QVariantMap>
|
||||
|
||||
namespace CalamaresUtils {}
|
||||
namespace CalamaresUtils::GeoIP
|
||||
{
|
||||
|
||||
/** @brief Handle one complete GeoIP lookup.
|
||||
*
|
||||
* This class handles one complete GeoIP lookup. Create it with
|
||||
* suitable configuration values, then call get(). This is a
|
||||
* synchronous API and will return an invalid zone pair on
|
||||
* error or if the configuration is not understood. For an
|
||||
* async API, use query().
|
||||
*/
|
||||
class DLLEXPORT Handler
|
||||
{
|
||||
public:
|
||||
enum class Type
|
||||
{
|
||||
None,
|
||||
JSON,
|
||||
XML
|
||||
} ;
|
||||
|
||||
/** @brief An unconfigured handler; this always returns errors. */
|
||||
Handler();
|
||||
/** @brief A handler for a specific GeoIP source.
|
||||
*
|
||||
* The @p implementation name selects an implementation; currently JSON and XML
|
||||
* are supported. The @p url is retrieved by query() and then the @p selector
|
||||
* is used to select something from the data returned by the @url.
|
||||
*/
|
||||
Handler( const QString& implementation, const QString& url, const QString& selector );
|
||||
|
||||
~Handler();
|
||||
|
||||
/** @brief Synchronously get the GeoIP result.
|
||||
*
|
||||
* If the Handler is valid, then do the actual fetching and interpretation
|
||||
* of data and return the result. An invalid Handler will return an
|
||||
* invalid (empty) result.
|
||||
*/
|
||||
RegionZonePair get() const;
|
||||
/// @brief Like get, but don't interpret the contents
|
||||
QString getRaw() const;
|
||||
|
||||
/** @brief Asynchronously get the GeoIP result.
|
||||
*
|
||||
* See get() for the return value.
|
||||
*/
|
||||
QFuture< RegionZonePair > query() const;
|
||||
/// @brief Like query, but don't interpret the contents
|
||||
QFuture< QString > queryRaw() const;
|
||||
|
||||
bool isValid() const { return m_type != Type::None; }
|
||||
Type type() const { return m_type; }
|
||||
|
||||
private:
|
||||
Type m_type;
|
||||
const QString m_url;
|
||||
const QString m_selector;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
#endif
|
||||
|
@ -0,0 +1,98 @@
|
||||
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2018-2019, Adriaan de Groot <groot@kde.org>
|
||||
*
|
||||
* Calamares 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.
|
||||
*
|
||||
* Calamares 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 Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GEOIP_INTERFACE_H
|
||||
#define GEOIP_INTERFACE_H
|
||||
|
||||
#include "DllMacro.h"
|
||||
|
||||
#include <QPair>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
class QByteArray;
|
||||
|
||||
namespace CalamaresUtils {}
|
||||
namespace CalamaresUtils::GeoIP
|
||||
{
|
||||
/** @brief A Region, Zone pair of strings
|
||||
*
|
||||
* A GeoIP lookup returns a timezone, which is represented as a Region,
|
||||
* Zone pair of strings (e.g. "Europe" and "Amsterdam"). Generally,
|
||||
* pasting the strings back together with a "/" is the right thing to
|
||||
* do. The Zone **may** contain a "/" (e.g. "Kentucky/Monticello").
|
||||
*/
|
||||
class DLLEXPORT RegionZonePair : public QPair<QString, QString>
|
||||
{
|
||||
public:
|
||||
/** @brief Construct from an existing pair. */
|
||||
explicit RegionZonePair( const QPair& p ) : QPair(p) { }
|
||||
/** @brief Construct from two strings, like qMakePair(). */
|
||||
RegionZonePair( const QString& region, const QString& zone ) : QPair( region, zone ) { }
|
||||
/** @brief An invalid zone pair (empty strings). */
|
||||
RegionZonePair() : QPair( QString(), QString() ) { }
|
||||
|
||||
bool isValid() const { return !first.isEmpty(); }
|
||||
} ;
|
||||
|
||||
/** @brief Splits a region/zone string into a pair.
|
||||
*
|
||||
* Cleans up the string by removing backslashes (\\)
|
||||
* since some providers return silly-escaped names. Replaces
|
||||
* spaces with _ since some providers return human-readable names.
|
||||
* Splits on the first / in the resulting string, or returns a
|
||||
* pair of empty QStrings if it can't. (e.g. America/North Dakota/Beulah
|
||||
* will return "America", "North_Dakota/Beulah").
|
||||
*/
|
||||
DLLEXPORT RegionZonePair
|
||||
splitTZString( const QString& s );
|
||||
|
||||
/**
|
||||
* @brief Interface for GeoIP retrievers.
|
||||
*
|
||||
* A GeoIP retriever takes a configured URL (from the config file)
|
||||
* and can handle the data returned from its interpretation of that
|
||||
* configured URL, returning a region and zone.
|
||||
*/
|
||||
class DLLEXPORT Interface
|
||||
{
|
||||
public:
|
||||
virtual ~Interface();
|
||||
|
||||
/** @brief Handle a (successful) request by interpreting the data.
|
||||
*
|
||||
* Should return a ( <zone>, <region> ) pair, e.g.
|
||||
* ( "Europe", "Amsterdam" ). This is called **only** if the
|
||||
* request to the fullUrl was successful; the handler
|
||||
* is free to read as much, or as little, data as it
|
||||
* likes. On error, returns a RegionZonePair with empty
|
||||
* strings (e.g. ( "", "" ) ).
|
||||
*/
|
||||
virtual RegionZonePair processReply( const QByteArray& ) = 0;
|
||||
|
||||
/** @brief Get the raw reply data. */
|
||||
virtual QString rawReply( const QByteArray& ) = 0;
|
||||
|
||||
protected:
|
||||
Interface( const QString& e = QString() );
|
||||
|
||||
QString m_element; // string for selecting from data
|
||||
} ;
|
||||
|
||||
} // namespace
|
||||
#endif
|
@ -1,70 +0,0 @@
|
||||
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2018, Adriaan de Groot <groot@kde.org>
|
||||
*
|
||||
* Calamares 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.
|
||||
*
|
||||
* Calamares 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 Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GEOIP_H
|
||||
#define GEOIP_H
|
||||
|
||||
#include <QPair>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
class QByteArray;
|
||||
|
||||
/**
|
||||
* @brief Interface for GeoIP retrievers.
|
||||
*
|
||||
* A GeoIP retriever takes a configured URL (from the config file)
|
||||
* and can handle the data returned from its interpretation of that
|
||||
* configured URL, returning a region and zone.
|
||||
*/
|
||||
class GeoIP
|
||||
{
|
||||
public:
|
||||
using RegionZonePair = QPair<QString, QString>;
|
||||
|
||||
virtual ~GeoIP();
|
||||
|
||||
/** @brief Handle a (successful) request by interpreting the data.
|
||||
*
|
||||
* Should return a ( <zone>, <region> ) pair, e.g.
|
||||
* ( "Europe", "Amsterdam" ). This is called **only** if the
|
||||
* request to the fullUrl was successful; the handler
|
||||
* is free to read as much, or as little, data as it
|
||||
* likes. On error, returns a RegionZonePair with empty
|
||||
* strings (e.g. ( "", "" ) ).
|
||||
*/
|
||||
virtual RegionZonePair processReply( const QByteArray& ) = 0;
|
||||
|
||||
/** @brief Splits a region/zone string into a pair.
|
||||
*
|
||||
* Cleans up the string by removing backslashes (\\)
|
||||
* since some providers return silly-escaped names. Replaces
|
||||
* spaces with _ since some providers return human-readable names.
|
||||
* Splits on the first / in the resulting string, or returns a
|
||||
* pair of empty QStrings if it can't. (e.g. America/North Dakota/Beulah
|
||||
* will return "America", "North_Dakota/Beulah").
|
||||
*/
|
||||
static RegionZonePair splitTZString( const QString& s );
|
||||
|
||||
protected:
|
||||
GeoIP( const QString& e = QString() );
|
||||
|
||||
QString m_element; // string for selecting from data
|
||||
} ;
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue