[libcalamares] Add "raw" support for extracting data from GeoIP

- This is prep-work for getting something other than the
   timezone (e.g. most extended formats also support Country).
This commit is contained in:
Adriaan de Groot 2019-05-09 10:15:53 -04:00
parent 8774b605fa
commit 9931b2df44
6 changed files with 67 additions and 17 deletions

View file

@ -33,6 +33,12 @@ GeoIPJSON::GeoIPJSON(const QString& attribute)
{
}
/** @brief Indexes into a map @m by selectors @p l
*
* Each element of @p l is an index into map @m or a sub-map thereof,
* so that "foo.bar.baz" looks up "baz" in the sub-map "bar" of sub-map
* "foo" of @p m, like a regular JSON lookup would.
*/
static QString
selectMap( const QVariantMap& m, const QStringList& l, int index)
{
@ -51,8 +57,8 @@ selectMap( const QVariantMap& m, const QStringList& l, int index)
}
}
GeoIP::RegionZonePair
GeoIPJSON::processReply( const QByteArray& data )
QString
GeoIPJSON::rawReply( const QByteArray& data )
{
try
{
@ -63,7 +69,7 @@ GeoIPJSON::processReply( const QByteArray& data )
var.isValid() &&
var.type() == QVariant::Map )
{
return splitTZString( selectMap( var.toMap(), m_element.split('.'), 0 ) );
return selectMap( var.toMap(), m_element.split('.'), 0 );
}
else
cWarning() << "Invalid YAML data for GeoIPJSON";
@ -73,7 +79,15 @@ GeoIPJSON::processReply( const QByteArray& data )
CalamaresUtils::explainYamlException( e, data, "GeoIP data");
}
return RegionZonePair( QString(), QString() );
return QString();
}
GeoIP::RegionZonePair
GeoIPJSON::processReply( const QByteArray& data )
{
return splitTZString( rawReply( data ) );
}
} // namespace

View file

@ -42,7 +42,8 @@ public:
*/
explicit GeoIPJSON( const QString& attribute = QString() );
virtual RegionZonePair processReply( const QByteArray& );
virtual RegionZonePair processReply( const QByteArray& ) override;
virtual QString rawReply(const QByteArray & ) override;
} ;
} // namespace

View file

@ -31,35 +31,60 @@ GeoIPXML::GeoIPXML( const QString& element )
{
}
GeoIP::RegionZonePair
GeoIPXML::processReply( const QByteArray& data )
static QStringList
getElementTexts( const QByteArray& data, const QString& tag )
{
QStringList elements;
QString domError;
int errorLine, errorColumn;
QDomDocument doc;
if ( doc.setContent( data, false, &domError, &errorLine, &errorColumn ) )
{
const auto tzElements = doc.elementsByTagName( m_element );
const auto tzElements = doc.elementsByTagName( tag );
cDebug() << "GeoIP found" << tzElements.length() << "elements";
for ( int it = 0; it < tzElements.length(); ++it )
{
auto e = tzElements.at(it).toElement();
auto tz = splitTZString( e.text() );
if ( !tz.first.isEmpty() )
return tz;
auto e_text = e.text();
if ( !e_text.isEmpty() )
elements.append( e_text );
}
// None of them valid
cWarning() << "GeopIP XML had no recognizable timezone";
return RegionZonePair( QString(), QString() );
}
else
{
cWarning() << "GeoIP XML data error:" << domError << "(line" << errorLine << errorColumn << ')';
}
return RegionZonePair( QString(), QString() );
if ( elements.count() < 1 )
cWarning() << "GeopIP XML had no non-empty elements" << tag;
return elements;
}
QString
GeoIPXML::rawReply( const QByteArray& data )
{
for ( const auto& e : getElementTexts( data, m_element ) )
if ( !e.isEmpty() )
return e;
return QString();
}
GeoIP::RegionZonePair
GeoIPXML::processReply( const QByteArray& data )
{
for ( const auto& e : getElementTexts( data, m_element ) )
{
auto tz = splitTZString( e );
if ( !tz.first.isEmpty() )
return tz;
}
return RegionZonePair();
}
} // namespace

View file

@ -42,7 +42,8 @@ public:
*/
explicit GeoIPXML( const QString& element = QString() );
virtual RegionZonePair processReply( const QByteArray& );
virtual RegionZonePair processReply( const QByteArray& ) override;
virtual QString rawReply(const QByteArray & ) override;
} ;
} // namespace

View file

@ -66,12 +66,18 @@ public:
* 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; }

View file

@ -85,6 +85,9 @@ public:
*/
virtual RegionZonePair processReply( const QByteArray& ) = 0;
/** @brief Get the raw reply data. */
virtual QString rawReply( const QByteArray& ) = 0;
protected:
Interface( const QString& e = QString() );