Merge branch 'issue-1419'

When entering the page, en_CA maps to us keyboard, not ca_eng --
this will annoy those people who have that specifically set,
so it needs separation of "setting from GeoIP" and "setting
because system is already like that".

Not touched in the Config class because that's not used yet.

FIXES #1419
This commit is contained in:
Adriaan de Groot 2020-06-03 15:29:42 +02:00
commit b0afcf0c7b
13 changed files with 197 additions and 31 deletions

View File

@ -23,6 +23,7 @@ set( libSources
# GeoIP services
geoip/Interface.cpp
geoip/GeoIPFixed.cpp
geoip/GeoIPJSON.cpp
geoip/Handler.cpp

View File

@ -0,0 +1,47 @@
/* === This file is part of Calamares - <http://github.com/calamares> ===
*
* SPDX-FileCopyrightText: 2020 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/>.
*
* SPDX-License-Identifier: GPL-3.0-or-later
* License-Filename: LICENSE
*/
#include "GeoIPFixed.h"
namespace CalamaresUtils
{
namespace GeoIP
{
GeoIPFixed::GeoIPFixed( const QString& attribute )
: Interface( attribute.isEmpty() ? QStringLiteral( "Europe/Amsterdam" ) : attribute )
{
}
QString
GeoIPFixed::rawReply( const QByteArray& )
{
return m_element;
}
GeoIP::RegionZonePair
GeoIPFixed::processReply( const QByteArray& data )
{
return splitTZString( rawReply( data ) );
}
} // namespace GeoIP
} // namespace CalamaresUtils

View File

@ -0,0 +1,55 @@
/* === This file is part of Calamares - <http://github.com/calamares> ===
*
* SPDX-FileCopyrightText: 2020 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/>.
*
* SPDX-License-Identifier: GPL-3.0-or-later
* License-Filename: LICENSE
*/
#ifndef GEOIP_GEOIPFIXED_H
#define GEOIP_GEOIPFIXED_H
#include "Interface.h"
namespace CalamaresUtils
{
namespace GeoIP
{
/** @brief GeoIP with a fixed return value
*
* The data is ignored entirely and the attribute value is returned unchanged.
* Note that you still need to provide a usable URL for a successful GeoIP
* lookup -- the URL's data is just ignored.
*
* @note This class is an implementation detail.
*/
class GeoIPFixed : public Interface
{
public:
/** @brief Configure the value to return from rawReply()
*
* An empty string, which would not be a valid zone name, is
* translated to "Europe/Amsterdam".
*/
explicit GeoIPFixed( const QString& value = QString() );
virtual RegionZonePair processReply( const QByteArray& ) override;
virtual QString rawReply( const QByteArray& ) override;
};
} // namespace GeoIP
} // namespace CalamaresUtils
#endif

View File

@ -18,6 +18,7 @@
#include "GeoIPTests.h"
#include "GeoIPFixed.h"
#include "GeoIPJSON.h"
#ifdef QT_XML_LIB
#include "GeoIPXML.h"
@ -240,3 +241,35 @@ GeoIPTests::testGet()
CHECK_GET( XML, QString(), "https://geoip.kde.org/v1/ubiquity" ) // Temporary KDE service
#endif
}
void
GeoIPTests::testFixed()
{
{
GeoIPFixed f;
auto tz = f.processReply( QByteArray() );
QCOMPARE( tz.first, QStringLiteral( "Europe" ) );
QCOMPARE( tz.second, QStringLiteral( "Amsterdam" ) );
QCOMPARE( f.processReply( xml_data_ubiquity ), tz );
QCOMPARE( f.processReply( QByteArray( "derp" ) ), tz );
}
{
GeoIPFixed f( QStringLiteral( "America/Vancouver" ) );
auto tz = f.processReply( QByteArray() );
QCOMPARE( tz.first, QStringLiteral( "America" ) );
QCOMPARE( tz.second, QStringLiteral( "Vancouver" ) );
QCOMPARE( f.processReply( xml_data_ubiquity ), tz );
QCOMPARE( f.processReply( QByteArray( "derp" ) ), tz );
}
{
GeoIPFixed f( QStringLiteral( "America/North Dakota/Beulah" ) );
auto tz = f.processReply( QByteArray() );
QCOMPARE( tz.first, QStringLiteral( "America" ) );
QCOMPARE( tz.second, QStringLiteral( "North_Dakota/Beulah" ) );
QCOMPARE( f.processReply( xml_data_ubiquity ), tz );
QCOMPARE( f.processReply( QByteArray( "derp" ) ), tz );
}
}

View File

@ -30,6 +30,7 @@ public:
private Q_SLOTS:
void initTestCase();
void testFixed();
void testJSON();
void testJSONalt();
void testJSONbad();

View File

@ -18,11 +18,13 @@
#include "Handler.h"
#include "GeoIPFixed.h"
#include "GeoIPJSON.h"
#if defined( QT_XML_LIB )
#include "GeoIPXML.h"
#endif
#include "Settings.h"
#include "network/Manager.h"
#include "utils/Logger.h"
#include "utils/NamedEnum.h"
@ -40,7 +42,8 @@ handlerTypes()
static const NamedEnumTable<Type> names{
{ QStringLiteral( "none" ), Type::None },
{ QStringLiteral( "json" ), Type::JSON },
{ QStringLiteral( "xml" ), Type::XML }
{ QStringLiteral( "xml" ), Type::XML },
{ QStringLiteral( "fixed" ), Type::Fixed }
};
// *INDENT-ON*
// clang-format on
@ -73,6 +76,10 @@ Handler::Handler( const QString& implementation, const QString& url, const QStri
{
cWarning() << "GeoIP style *none* does not do anything.";
}
else if ( m_type == Type::Fixed && Calamares::Settings::instance() && !Calamares::Settings::instance()->debugMode() )
{
cWarning() << "GeoIP style *fixed* is not recommended for production.";
}
#if !defined( QT_XML_LIB )
else if ( m_type == Type::XML )
{
@ -99,6 +106,8 @@ create_interface( Handler::Type t, const QString& selector )
#else
return nullptr;
#endif
case Handler::Type::Fixed:
return std::make_unique< GeoIPFixed >( selector );
}
NOTREACHED return nullptr;
}

View File

@ -43,9 +43,10 @@ class DLLEXPORT Handler
public:
enum class Type
{
None,
JSON,
XML
None, // No lookup, returns empty string
JSON, // JSON-formatted data, returns extracted field
XML, // XML-formatted data, returns extracted field
Fixed // Returns selector string verbatim
};
/** @brief An unconfigured handler; this always returns errors. */

View File

@ -98,7 +98,7 @@ public:
virtual QString rawReply( const QByteArray& ) = 0;
protected:
Interface( const QString& e = QString() );
Interface( const QString& element = QString() );
QString m_element; // string for selecting from data
};

View File

@ -22,6 +22,7 @@
#include <iostream>
#include "GeoIPFixed.h"
#include "GeoIPJSON.h"
#ifdef QT_XML_LIB
#include "GeoIPXML.h"
@ -33,27 +34,34 @@ using namespace CalamaresUtils::GeoIP;
int
main( int argc, char** argv )
{
if ( argc != 2 )
if ( ( argc != 2 ) && ( argc != 3 ) )
{
cerr << "Usage: curl url | test_geoip <format>\n";
cerr << "Usage: curl url | test_geoip <format> [selector]\n";
return 1;
}
QString format( argv[ 1 ] );
QString selector = argc == 3 ? QString( argv[ 2 ] ) : QString();
Interface* handler = nullptr;
if ( QStringLiteral( "json" ) == argv[ 1 ] )
if ( QStringLiteral( "json" ) == format )
{
handler = new GeoIPJSON;
handler = new GeoIPJSON( selector );
}
#ifdef QT_XML_LIB
else if ( QStringLiteral( "xml" ) == argv[ 1 ] )
else if ( QStringLiteral( "xml" ) == format )
{
handler = new GeoIPXML;
handler = new GeoIPXML( selector );
}
#endif
else if ( QStringLiteral( "fixed" ) == format )
{
handler = new GeoIPFixed( selector );
}
if ( !handler )
{
cerr << "Unknown format '" << argv[ 1 ] << "'\n";
cerr << "Unknown format '" << format.toLatin1().constData() << "'\n";
return 1;
}

View File

@ -456,7 +456,7 @@ Config::onActivate()
{ "ar_YE", arabic },
{ "ca_ES", "cat_ES" }, /* Catalan */
{ "as_ES", "ast_ES" }, /* Asturian */
{ "en_CA", "eng_CA" }, /* Canadian English */
{ "en_CA", "us" }, /* Canadian English */
{ "el_CY", "gr" }, /* Greek in Cyprus */
{ "el_GR", "gr" }, /* Greek in Greeze */
{ "ig_NG", "igbo_NG" }, /* Igbo in Nigeria */

View File

@ -324,7 +324,7 @@ KeyboardPage::onActivate()
{ "ar_YE", arabic },
{ "ca_ES", "cat_ES" }, /* Catalan */
{ "as_ES", "ast_ES" }, /* Asturian */
{ "en_CA", "eng_CA" }, /* Canadian English */
{ "en_CA", "us" }, /* Canadian English */
{ "el_CY", "gr" }, /* Greek in Cyprus */
{ "el_GR", "gr" }, /* Greek in Greeze */
{ "ig_NG", "igbo_NG" }, /* Igbo in Nigeria */

View File

@ -30,12 +30,16 @@ zone: "New_York"
#
# GeoIP needs a working Internet connection.
# This can be managed from `welcome.conf` by adding
# internet to the list of required conditions.
# internet to the list of required conditions. (The welcome
# module can also do its own GeoIP lookups, independently
# of the lookup done here. The lookup in the welcome module
# is used to establish language; this one is for timezone).
#
# The configuration
# is in three parts: a *style*, which can be "json" or "xml"
# depending on the kind of data returned by the service, and
# a *url* where the data is retrieved, and an optional *selector*
# The configuration is in three parts:
# - a *style*, which can be "json" or "xml" depending on the
# kind of data returned by the service, and
# - a *url* where the data is retrieved, and
# - an optional *selector*
# to pick the right field out of the returned data (e.g. field
# name in JSON or element name in XML).
#
@ -45,8 +49,8 @@ zone: "New_York"
#
# If the service configured via *url* uses
# a different attribute name (e.g. "timezone") in JSON or a
# different element tag (e.g. "<Time_Zone>") in XML, set this
# string to the name or tag to be used.
# different element tag (e.g. "<Time_Zone>") in XML, set the
# selector to the name or tag to be used.
#
# In JSON:
# - if the string contains "." characters, this is used as a
@ -58,7 +62,10 @@ zone: "New_York"
# - all elements with the named tag (e.g. all TimeZone) elements
# from the document are checked; the first one with non-empty
# text value is used.
#
# Special case:
# - the *style* "fixed" is also supported. This ignores the data
# returned from the URL (but the URL must still be valid!)
# and just returns the value of the *selector*.
#
# An HTTP(S) request is made to *url*. The request should return
# valid data in a suitable format, depending on *style*;
@ -67,9 +74,6 @@ zone: "New_York"
# does not follow the conventions of "suitable data" described
# below, *selector* may be used to pick different data.
#
# Note that this example URL works, but the service is shutting
# down in June 2018.
#
# Suitable JSON data looks like
# ```
# {"time_zone":"America/New_York"}
@ -84,9 +88,6 @@ zone: "New_York"
# - backslashes are removed
# - spaces are replaced with _
#
# Legacy settings "geoipStyle", "geoipUrl" and "geoipSelector"
# in the top-level are still supported, but I'd advise against.
#
# To disable GeoIP checking, either comment-out the entire geoip section,
# or set the *style* key to an unsupported format (e.g. `none`).
# Also, note the analogous feature in src/modules/welcome/welcome.conf.
@ -95,3 +96,12 @@ geoip:
style: "json"
url: "https://geoip.kde.org/v1/calamares"
selector: "" # leave blank for the default
# For testing purposes, you could use *fixed* style, to see how Calamares
# behaves in a particular zone:
#
# geoip:
# style: "fixed"
# url: "https://geoip.kde.org/v1/calamares" # Still needs to be valid!
# selector: "America/Vancouver" # this is the selected zone
#

View File

@ -64,7 +64,8 @@ requirements:
#
# To disable GeoIP checking, either comment-out the entire geoip section,
# or set the *style* key to an unsupported format (e.g. `none`).
# Also, note the analogous feature in src/modules/locale/locale.conf.
# Also, note the analogous feature in `src/modules/locale/locale.conf`,
# which is where you will find complete documentation.
#
geoip:
style: "none"