mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-28 05:34:47 +01:00
Fixed WMS 1.1.x support
Added support for HTTP basic authorization
This commit is contained in:
parent
16f2d7ad34
commit
e3e8fdbacf
@ -29,6 +29,13 @@
|
||||
#define TIMEOUT 30 /* s */
|
||||
|
||||
|
||||
Authorization::Authorization(const QString &username, const QString &password)
|
||||
{
|
||||
QString concatenated = username + ":" + password;
|
||||
QByteArray data = concatenated.toLocal8Bit().toBase64();
|
||||
_header = "Basic " + data;
|
||||
}
|
||||
|
||||
class Downloader::ReplyTimeout : public QObject
|
||||
{
|
||||
public:
|
||||
@ -79,7 +86,8 @@ Downloader::Downloader(QObject *parent) : QObject(parent)
|
||||
SLOT(downloadFinished(QNetworkReply*)));
|
||||
}
|
||||
|
||||
bool Downloader::doDownload(const Download &dl, const Redirect *redirect)
|
||||
bool Downloader::doDownload(const Download &dl,
|
||||
const QByteArray &authorization, const Redirect *redirect)
|
||||
{
|
||||
QUrl url(dl.url());
|
||||
|
||||
@ -95,6 +103,8 @@ bool Downloader::doDownload(const Download &dl, const Redirect *redirect)
|
||||
request.setAttribute(ATTR_LEVEL, QVariant(redirect->level()));
|
||||
}
|
||||
request.setRawHeader("User-Agent", USER_AGENT);
|
||||
if (!authorization.isNull())
|
||||
request.setRawHeader("Authorization", authorization);
|
||||
|
||||
QNetworkReply *reply = _manager.get(request);
|
||||
if (reply) {
|
||||
@ -159,7 +169,8 @@ void Downloader::downloadFinished(QNetworkReply *reply)
|
||||
} else {
|
||||
Redirect redirect(origin.isEmpty() ? url : origin, level + 1);
|
||||
Download dl(location, filename);
|
||||
doDownload(dl, &redirect);
|
||||
doDownload(dl, reply->request().rawHeader("Authorization"),
|
||||
&redirect);
|
||||
}
|
||||
} else
|
||||
if (!saveToDisk(filename, reply))
|
||||
@ -173,12 +184,13 @@ void Downloader::downloadFinished(QNetworkReply *reply)
|
||||
emit finished();
|
||||
}
|
||||
|
||||
bool Downloader::get(const QList<Download> &list)
|
||||
bool Downloader::get(const QList<Download> &list,
|
||||
const Authorization &authorization)
|
||||
{
|
||||
bool finishEmitted = false;
|
||||
|
||||
for (int i = 0; i < list.count(); i++)
|
||||
finishEmitted |= doDownload(list.at(i));
|
||||
finishEmitted |= doDownload(list.at(i), authorization.header());
|
||||
|
||||
return finishEmitted;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
#ifndef DOWNLOADER_H
|
||||
#ifndef DOWNLOADER_H
|
||||
#define DOWNLOADER_H
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
@ -11,8 +11,8 @@ class QNetworkReply;
|
||||
class Download
|
||||
{
|
||||
public:
|
||||
Download(const QUrl &url, const QString &file)
|
||||
{_url = url; _file = file;}
|
||||
Download(const QUrl &url, const QString &file) : _url(url), _file(file) {}
|
||||
|
||||
const QUrl& url() const {return _url;}
|
||||
const QString& file() const {return _file;}
|
||||
|
||||
@ -21,6 +21,17 @@ private:
|
||||
QString _file;
|
||||
};
|
||||
|
||||
class Authorization
|
||||
{
|
||||
public:
|
||||
Authorization() {}
|
||||
Authorization(const QString &username, const QString &password);
|
||||
|
||||
const QByteArray &header() const {return _header;}
|
||||
|
||||
private:
|
||||
QByteArray _header;
|
||||
};
|
||||
|
||||
class Downloader : public QObject
|
||||
{
|
||||
@ -29,7 +40,8 @@ class Downloader : public QObject
|
||||
public:
|
||||
Downloader(QObject *parent = 0);
|
||||
|
||||
bool get(const QList<Download> &list);
|
||||
bool get(const QList<Download> &list, const Authorization &authorization
|
||||
= Authorization());
|
||||
void clearErrors() {_errorDownloads.clear();}
|
||||
|
||||
signals:
|
||||
@ -42,7 +54,8 @@ private:
|
||||
class Redirect;
|
||||
class ReplyTimeout;
|
||||
|
||||
bool doDownload(const Download &dl, const Redirect *redirect = 0);
|
||||
bool doDownload(const Download &dl, const QByteArray &authorization,
|
||||
const Redirect *redirect = 0);
|
||||
bool saveToDisk(const QString &filename, QIODevice *data);
|
||||
|
||||
QNetworkAccessManager _manager;
|
||||
|
@ -144,6 +144,12 @@ void MapSource::map(QXmlStreamReader &reader, Config &config)
|
||||
config.yx = (reader.attributes().value("axis") == "yx")
|
||||
? true : false;
|
||||
config.crs = reader.readElementText();
|
||||
} else if (reader.name() == "authorization") {
|
||||
QXmlStreamAttributes attr = reader.attributes();
|
||||
config.authorization = Authorization(
|
||||
attr.value("username").toString(),
|
||||
attr.value("password").toString());
|
||||
reader.skipCurrentElement();
|
||||
} else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
@ -213,10 +219,11 @@ Map *MapSource::loadFile(const QString &path)
|
||||
if (config.type == WMTS)
|
||||
m = new WMTSMap(config.name, WMTS::Setup(config.url, config.layer,
|
||||
config.set, config.style, config.format, config.rest, config.yx,
|
||||
config.dimensions));
|
||||
config.dimensions, config.authorization));
|
||||
else if (config.type == WMS)
|
||||
m = new WMSMap(config.name, WMS::Setup(config.url, config.layer,
|
||||
config.style, config.format, config.crs, config.yx));
|
||||
config.style, config.format, config.crs, config.yx,
|
||||
config.authorization));
|
||||
else
|
||||
m = new OnlineMap(config.name, config.url, config.zooms, config.bounds);
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <QList>
|
||||
#include "common/range.h"
|
||||
#include "common/rectc.h"
|
||||
#include "downloader.h"
|
||||
|
||||
class Map;
|
||||
class QXmlStreamReader;
|
||||
@ -35,6 +36,7 @@ private:
|
||||
bool rest;
|
||||
bool yx;
|
||||
QList<QPair<QString, QString> > dimensions;
|
||||
Authorization authorization;
|
||||
|
||||
Config();
|
||||
};
|
||||
|
@ -33,7 +33,7 @@ void TileLoader::loadTilesAsync(QList<Tile> &list)
|
||||
}
|
||||
|
||||
if (!dl.empty())
|
||||
_downloader->get(dl);
|
||||
_downloader->get(dl, _authorization);
|
||||
}
|
||||
|
||||
void TileLoader::loadTilesSync(QList<Tile> &list)
|
||||
@ -56,7 +56,7 @@ void TileLoader::loadTilesSync(QList<Tile> &list)
|
||||
|
||||
QEventLoop wait;
|
||||
QObject::connect(_downloader, SIGNAL(finished()), &wait, SLOT(quit()));
|
||||
if (_downloader->get(dl))
|
||||
if (_downloader->get(dl, _authorization))
|
||||
wait.exec();
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
|
@ -3,15 +3,15 @@
|
||||
|
||||
#include <QString>
|
||||
#include "tile.h"
|
||||
|
||||
class Downloader;
|
||||
#include "downloader.h"
|
||||
|
||||
class TileLoader
|
||||
{
|
||||
public:
|
||||
TileLoader() {}
|
||||
TileLoader(const QString &url, const QString &dir)
|
||||
: _url(url), _dir(dir) {}
|
||||
TileLoader(const QString &url, const QString &dir,
|
||||
const Authorization &authorization = Authorization())
|
||||
: _url(url), _dir(dir), _authorization(authorization) {}
|
||||
|
||||
void loadTilesAsync(QList<Tile> &list);
|
||||
void loadTilesSync(QList<Tile> &list);
|
||||
@ -27,6 +27,7 @@ private:
|
||||
|
||||
QString _url;
|
||||
QString _dir;
|
||||
Authorization _authorization;
|
||||
|
||||
static Downloader *_downloader;
|
||||
};
|
||||
|
@ -43,20 +43,40 @@ QString WMS::style(QXmlStreamReader &reader)
|
||||
return name;
|
||||
}
|
||||
|
||||
RectC WMS::geographicBoundingBox(QXmlStreamReader &reader)
|
||||
{
|
||||
qreal left, top, right, bottom;
|
||||
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == "westBoundLongitude")
|
||||
left = reader.readElementText().toDouble();
|
||||
else if (reader.name() == "eastBoundLongitude")
|
||||
right = reader.readElementText().toDouble();
|
||||
else if (reader.name() == "northBoundLatitude")
|
||||
top = reader.readElementText().toDouble();
|
||||
else if (reader.name() == "southBoundLatitude")
|
||||
bottom = reader.readElementText().toDouble();
|
||||
else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
return RectC(Coordinates(left, top), Coordinates(right, bottom));
|
||||
}
|
||||
|
||||
void WMS::layer(QXmlStreamReader &reader, CTX &ctx,
|
||||
const QList<QString> &pCRSs, const QList<QString> &pStyles)
|
||||
const QList<QString> &pCRSs, const QList<QString> &pStyles,
|
||||
RangeF &pScaleDenominator, RectC &pBoundingBox)
|
||||
{
|
||||
QString name;
|
||||
QList<QString> CRSs(pCRSs);
|
||||
QList<QString> styles(pStyles);
|
||||
RangeF scaleDenominator(2132.729583849784, 559082264.0287178);
|
||||
QRectF boundingBox;
|
||||
|
||||
RangeF scaleDenominator(pScaleDenominator);
|
||||
RectC boundingBox(pBoundingBox);
|
||||
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == "Name")
|
||||
name = reader.readElementText();
|
||||
else if (reader.name() == "CRS")
|
||||
else if (reader.name() == "CRS" || reader.name() == "SRS")
|
||||
CRSs.append(reader.readElementText());
|
||||
else if (reader.name() == "Style")
|
||||
styles.append(style(reader));
|
||||
@ -64,18 +84,18 @@ void WMS::layer(QXmlStreamReader &reader, CTX &ctx,
|
||||
scaleDenominator.setMin(reader.readElementText().toDouble());
|
||||
else if (reader.name() == "MaxScaleDenominator")
|
||||
scaleDenominator.setMax(reader.readElementText().toDouble());
|
||||
else if (reader.name() == "BoundingBox") {
|
||||
else if (reader.name() == "LatLonBoundingBox") {
|
||||
QXmlStreamAttributes attr = reader.attributes();
|
||||
if (attr.value("CRS") == ctx.setup.crs()) {
|
||||
boundingBox = QRectF(QPointF(
|
||||
boundingBox = RectC(Coordinates(
|
||||
attr.value("minx").toString().toDouble(),
|
||||
attr.value("maxy").toString().toDouble()),
|
||||
QPointF(attr.value("maxx").toString().toDouble(),
|
||||
Coordinates(attr.value("maxx").toString().toDouble(),
|
||||
attr.value("miny").toString().toDouble()));
|
||||
}
|
||||
reader.skipCurrentElement();
|
||||
} else if (reader.name() == "Layer")
|
||||
layer(reader, ctx, CRSs, styles);
|
||||
} else if (reader.name() == "EX_GeographicBoundingBox")
|
||||
boundingBox = geographicBoundingBox(reader);
|
||||
else if (reader.name() == "Layer")
|
||||
layer(reader, ctx, CRSs, styles, scaleDenominator, boundingBox);
|
||||
else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
@ -93,10 +113,12 @@ void WMS::capability(QXmlStreamReader &reader, CTX &ctx)
|
||||
{
|
||||
QList<QString> CRSs;
|
||||
QList<QString> styles;
|
||||
RangeF scaleDenominator(2132.729583849784, 559082264.0287178);
|
||||
RectC boundingBox;
|
||||
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == "Layer")
|
||||
layer(reader, ctx, CRSs, styles);
|
||||
layer(reader, ctx, CRSs, styles, scaleDenominator, boundingBox);
|
||||
else if (reader.name() == "Request")
|
||||
request(reader, ctx);
|
||||
else
|
||||
@ -129,10 +151,11 @@ bool WMS::parseCapabilities(const QString &path, const Setup &setup)
|
||||
|
||||
reader.setDevice(&file);
|
||||
if (reader.readNextStartElement()) {
|
||||
if (reader.name() == "WMS_Capabilities")
|
||||
if (reader.name() == "WMS_Capabilities"
|
||||
|| reader.name() == "WMT_MS_Capabilities")
|
||||
capabilities(reader, ctx);
|
||||
else
|
||||
reader.raiseError("Not a WMS_Capabilities XML file");
|
||||
reader.raiseError("Not a WMS Capabilities XML file");
|
||||
}
|
||||
if (reader.error()) {
|
||||
_errorString = QString("%1:%2: %3").arg(path).arg(reader.lineNumber())
|
||||
@ -176,7 +199,8 @@ bool WMS::parseCapabilities(const QString &path, const Setup &setup)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WMS::getCapabilities(const QString &url, const QString &file)
|
||||
bool WMS::getCapabilities(const QString &url, const QString &file,
|
||||
const Authorization &authorization)
|
||||
{
|
||||
QList<Download> dl;
|
||||
|
||||
@ -184,7 +208,7 @@ bool WMS::getCapabilities(const QString &url, const QString &file)
|
||||
|
||||
QEventLoop wait;
|
||||
QObject::connect(_downloader, SIGNAL(finished()), &wait, SLOT(quit()));
|
||||
if (_downloader->get(dl))
|
||||
if (_downloader->get(dl, authorization))
|
||||
wait.exec();
|
||||
|
||||
if (QFileInfo(file).exists())
|
||||
@ -201,7 +225,7 @@ WMS::WMS(const QString &file, const WMS::Setup &setup) : _valid(false)
|
||||
.arg(setup.url());
|
||||
|
||||
if (!QFileInfo(file).exists())
|
||||
if (!getCapabilities(capaUrl, file))
|
||||
if (!getCapabilities(capaUrl, file, setup.authorization()))
|
||||
return;
|
||||
if (!parseCapabilities(file, setup))
|
||||
return;
|
||||
|
@ -4,10 +4,11 @@
|
||||
#include <QString>
|
||||
#include <QRectF>
|
||||
#include "common/range.h"
|
||||
#include "common/rectc.h"
|
||||
#include "projection.h"
|
||||
#include "downloader.h"
|
||||
|
||||
class QXmlStreamReader;
|
||||
class Downloader;
|
||||
|
||||
class WMS
|
||||
{
|
||||
@ -16,11 +17,13 @@ public:
|
||||
{
|
||||
public:
|
||||
Setup(const QString &url, const QString &layer, const QString &style,
|
||||
const QString &format, const QString &crs, bool yx)
|
||||
const QString &format, const QString &crs, bool yx,
|
||||
const Authorization &authorization = Authorization())
|
||||
: _url(url), _layer(layer), _style(style), _format(format), _crs(crs),
|
||||
_yx(yx) {}
|
||||
_yx(yx), _authorization(authorization) {}
|
||||
|
||||
const QString &url() const {return _url;}
|
||||
const Authorization &authorization() const {return _authorization;}
|
||||
const QString &layer() const {return _layer;}
|
||||
const QString &style() const {return _style;}
|
||||
const QString &format() const {return _format;}
|
||||
@ -34,6 +37,7 @@ public:
|
||||
QString _format;
|
||||
QString _crs;
|
||||
bool _yx;
|
||||
Authorization _authorization;
|
||||
};
|
||||
|
||||
|
||||
@ -41,7 +45,7 @@ public:
|
||||
|
||||
const Projection &projection() const {return _projection;}
|
||||
const RangeF &scaleDenominator() const {return _scaleDenominator;}
|
||||
const QRectF &boundingBox() const {return _boundingBox;}
|
||||
const RectC &boundingBox() const {return _boundingBox;}
|
||||
const QString &version() const {return _version;}
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
@ -54,7 +58,7 @@ private:
|
||||
struct CTX {
|
||||
const Setup &setup;
|
||||
RangeF scaleDenominator;
|
||||
QRectF boundingBox;
|
||||
RectC boundingBox;
|
||||
bool layer;
|
||||
bool style;
|
||||
bool format;
|
||||
@ -64,19 +68,22 @@ private:
|
||||
format(false), crs(false) {}
|
||||
};
|
||||
|
||||
RectC geographicBoundingBox(QXmlStreamReader &reader);
|
||||
QString style(QXmlStreamReader &reader);
|
||||
void getMap(QXmlStreamReader &reader, CTX &ctx);
|
||||
void request(QXmlStreamReader &reader, CTX &ctx);
|
||||
void layer(QXmlStreamReader &reader, CTX &ctx, const QList<QString> &pCRSs,
|
||||
const QList<QString> &pStyles);
|
||||
const QList<QString> &pStyles, RangeF &pScaleDenominator,
|
||||
RectC &pBoundingBox);
|
||||
void capability(QXmlStreamReader &reader, CTX &ctx);
|
||||
void capabilities(QXmlStreamReader &reader, CTX &ctx);
|
||||
bool parseCapabilities(const QString &path, const Setup &setup);
|
||||
bool getCapabilities(const QString &url, const QString &file);
|
||||
bool getCapabilities(const QString &url, const QString &file,
|
||||
const Authorization &authorization);
|
||||
|
||||
Projection _projection;
|
||||
RangeF _scaleDenominator;
|
||||
QRectF _boundingBox;
|
||||
RectC _boundingBox;
|
||||
QString _version;
|
||||
|
||||
bool _valid;
|
||||
|
@ -80,10 +80,10 @@ bool WMSMap::loadWMS()
|
||||
|
||||
_yx = (_setup.yx() && wms.version() >= "1.3.0") ? true : false;
|
||||
_projection = wms.projection();
|
||||
_boundingBox = _yx ? QRectF(QPointF(wms.boundingBox().bottom(),
|
||||
wms.boundingBox().right()), QPointF(wms.boundingBox().top(),
|
||||
wms.boundingBox().left())) : wms.boundingBox();
|
||||
_tileLoader = TileLoader(tileUrl(wms.version()), tilesDir());
|
||||
_boundingBox = QRectF(_projection.ll2xy(wms.boundingBox().topLeft()),
|
||||
_projection.ll2xy(wms.boundingBox().bottomRight()));
|
||||
_tileLoader = TileLoader(tileUrl(wms.version()), tilesDir(),
|
||||
_setup.authorization());
|
||||
|
||||
computeZooms(wms.scaleDenominator());
|
||||
updateTransform();
|
||||
|
@ -282,7 +282,8 @@ bool WMTS::parseCapabilities(const QString &path, const Setup &setup)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WMTS::getCapabilities(const QString &url, const QString &file)
|
||||
bool WMTS::getCapabilities(const QString &url, const QString &file,
|
||||
const Authorization &authorization)
|
||||
{
|
||||
QList<Download> dl;
|
||||
|
||||
@ -290,7 +291,7 @@ bool WMTS::getCapabilities(const QString &url, const QString &file)
|
||||
|
||||
QEventLoop wait;
|
||||
QObject::connect(_downloader, SIGNAL(finished()), &wait, SLOT(quit()));
|
||||
if (_downloader->get(dl))
|
||||
if (_downloader->get(dl, authorization))
|
||||
wait.exec();
|
||||
|
||||
if (QFileInfo(file).exists())
|
||||
@ -308,7 +309,7 @@ WMTS::WMTS(const QString &file, const WMTS::Setup &setup) : _valid(false)
|
||||
.arg(setup.url());
|
||||
|
||||
if (!QFileInfo(file).exists())
|
||||
if (!getCapabilities(capaUrl, file))
|
||||
if (!getCapabilities(capaUrl, file, setup.authorization()))
|
||||
return;
|
||||
if (!parseCapabilities(file, setup))
|
||||
return;
|
||||
|
@ -8,8 +8,8 @@
|
||||
#include <QHash>
|
||||
#include "common/rectc.h"
|
||||
#include "projection.h"
|
||||
#include "downloader.h"
|
||||
|
||||
class Downloader;
|
||||
class QXmlStreamReader;
|
||||
|
||||
class WMTS
|
||||
@ -20,11 +20,14 @@ public:
|
||||
public:
|
||||
Setup(const QString &url, const QString &layer, const QString &set,
|
||||
const QString &style, const QString &format, bool rest, bool yx,
|
||||
const QList<QPair<QString, QString> > &dimensions) :
|
||||
const QList<QPair<QString, QString> > &dimensions,
|
||||
const Authorization &authorization = Authorization()) :
|
||||
_url(url), _layer(layer), _set(set), _style(style), _format(format),
|
||||
_rest(rest), _yx(yx), _dimensions(dimensions) {}
|
||||
_rest(rest), _yx(yx), _dimensions(dimensions),
|
||||
_authorization(authorization) {}
|
||||
|
||||
const QString &url() const {return _url;}
|
||||
const Authorization &authorization() const {return _authorization;}
|
||||
const QString &layer() const {return _layer;}
|
||||
const QString &set() const {return _set;}
|
||||
const QString &style() const {return _style;}
|
||||
@ -43,6 +46,7 @@ public:
|
||||
bool _rest;
|
||||
bool _yx;
|
||||
QList<QPair<QString, QString> > _dimensions;
|
||||
Authorization _authorization;
|
||||
};
|
||||
|
||||
class Zoom
|
||||
@ -136,7 +140,8 @@ private:
|
||||
void contents(QXmlStreamReader &reader, CTX &ctx);
|
||||
void capabilities(QXmlStreamReader &reader, CTX &ctx);
|
||||
bool parseCapabilities(const QString &path, const Setup &setup);
|
||||
bool getCapabilities(const QString &url, const QString &file);
|
||||
bool getCapabilities(const QString &url, const QString &file,
|
||||
const Authorization &authorization);
|
||||
|
||||
QSet<TileMatrix> _matrixes;
|
||||
QSet<MatrixLimits> _limits;
|
||||
|
@ -23,7 +23,8 @@ bool WMTSMap::loadWMTS()
|
||||
_bounds = wmts.bounds();
|
||||
_zooms = wmts.zooms();
|
||||
_projection = wmts.projection();
|
||||
_tileLoader = TileLoader(wmts.tileUrl(), tilesDir());
|
||||
_tileLoader = TileLoader(wmts.tileUrl(), tilesDir(),
|
||||
_setup.authorization());
|
||||
|
||||
updateTransform();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user