From 986450eb20b2c617e7be772a766f2b4c69bbb640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 3 Oct 2021 21:17:49 +0200 Subject: [PATCH] Update QtWebApp to 1.8.3 nullptr redefinition for old __cplusplus versions has been removed, the rest is vanilla --- third_party/QtWebApp/CHANGELOG.txt | 21 +++++++++++++ third_party/QtWebApp/README.txt | 15 ++++------ .../httpserver/httpconnectionhandler.cpp | 12 ++++---- .../httpserver/httpconnectionhandler.h | 2 +- .../httpserver/httpconnectionhandlerpool.cpp | 7 +++-- .../QtWebApp/httpserver/httpcookie.cpp | 24 ++++++++++++++- third_party/QtWebApp/httpserver/httpcookie.h | 21 +++++++++---- .../QtWebApp/httpserver/httpglobal.cpp | 2 +- third_party/QtWebApp/httpserver/httpglobal.h | 1 - .../QtWebApp/httpserver/httplistener.cpp | 2 +- .../QtWebApp/httpserver/httprequest.cpp | 3 +- third_party/QtWebApp/httpserver/httpsession.h | 3 +- .../QtWebApp/httpserver/httpsessionstore.cpp | 10 +++++-- .../QtWebApp/httpserver/httpsessionstore.h | 8 +++++ .../httpserver/staticfilecontroller.cpp | 3 +- .../QtWebApp/templateengine/template.h | 1 - .../QtWebApp/templateengine/templatecache.cpp | 3 +- .../templateengine/templateengine.pri | 4 +++ .../templateengine/templateloader.cpp | 30 +++++++++++++++---- .../QtWebApp/templateengine/templateloader.h | 2 +- 20 files changed, 131 insertions(+), 43 deletions(-) diff --git a/third_party/QtWebApp/CHANGELOG.txt b/third_party/QtWebApp/CHANGELOG.txt index e24ec4af..19183495 100644 --- a/third_party/QtWebApp/CHANGELOG.txt +++ b/third_party/QtWebApp/CHANGELOG.txt @@ -1,6 +1,27 @@ Dont forget to update the release number also in QtWebApp.pro and httpserver/httpglobal.cpp. +1.8.3 +21.03.2021 +The minLevel for logging can now be configured as string: +DEBUG/ALL=0, INFO=4, WARNING=1, ERROR/CRITICAL=2, FATAL=3 +Info messages are now positioned between DEBUG and WARNING. +I also added an example for HTTP Basic authorization. + +1.8.2 +08.03.2021 +Fix threadId not printed in log file. + +1.8.1 +07.02.2021 +Add Cookie attribute "SameSite". +SessionStore does now emit a signal when a session expires. + +1.8.0 +06.02.2021 +Fix compatibility issues to Qt 4.7 and 6.0. +Removed qtservice, use the Non-Sucking Service Manager (https://nssm.cc/) instead. + 1.7.11 28.12.2019 Fix Http Headers are not properly received if the two characters of diff --git a/third_party/QtWebApp/README.txt b/third_party/QtWebApp/README.txt index 50c73a34..e9b2f575 100644 --- a/third_party/QtWebApp/README.txt +++ b/third_party/QtWebApp/README.txt @@ -1,25 +1,22 @@ QtWebAppLib is a library to develop server-side web applications in C++. -It requires the Qt SDK version 4.7.0 or newer. +Works with Qt SDK version 4.7 until at least 6.0 License: LGPL v3. -Project homepage: http://stefanfrings.de/qtwebapp/index.html +Project homepage: http://stefanfrings.de/qtwebapp/index-en.html Tutorial: http://stefanfrings.de/qtwebapp/tutorial/index.html API doc: http://stefanfrings.de/qtwebapp/api/index.html -There are three demo applications that demonstrate how to use the library. +In Qt 6.0 or newer, you must install the optional "core5compat" component. +This package contains the QTextCodec class which is needed to decode template files. +It supports a lot more encodings, for example ISO-8859-15 with the EUR symbol. Demo1 shows how to use the library by including the source code into your -project. This does not depend on the shared library. +project, the preferred method. Demo2 shows how to link against the shared library. Build the project QtWebApp to generate the shared library. -Demo3 shows how to use the qtservice component to start the application -as a Windows Service or Unix daemon. Start it with option -h to get help. - -I recommend to include the library by source as shown in Demo1 and 3. - Stefan Frings http://stefanfrings.de diff --git a/third_party/QtWebApp/httpserver/httpconnectionhandler.cpp b/third_party/QtWebApp/httpserver/httpconnectionhandler.cpp index f5fb8327..849425d3 100644 --- a/third_party/QtWebApp/httpserver/httpconnectionhandler.cpp +++ b/third_party/QtWebApp/httpserver/httpconnectionhandler.cpp @@ -28,16 +28,16 @@ HttpConnectionHandler::HttpConnectionHandler(const QSettings *settings, HttpRequ readTimer.setSingleShot(true); // Create TCP or SSL socket - createSocket(); + createSocket(); socket->moveToThread(thread); // Connect signals - connect(socket, &QIODevice::readyRead, this, &HttpConnectionHandler::read); - connect(socket, &QAbstractSocket::disconnected, this, &HttpConnectionHandler::disconnected); - connect(&readTimer, &QTimer::timeout, this, &HttpConnectionHandler::readTimeout); - connect(thread, &QThread::finished, this, &HttpConnectionHandler::thread_done); + connect(socket, SIGNAL(readyRead()), SLOT(read())); + connect(socket, SIGNAL(disconnected()), SLOT(disconnected())); + connect(&readTimer, SIGNAL(timeout()), SLOT(readTimeout())); + connect(thread, SIGNAL(finished()), this, SLOT(thread_done())); - qDebug("HttpConnectionHandler (%p): constructed", static_cast(this)); + qDebug("HttpConnectionHandler (%p): constructed", static_cast(this)); } diff --git a/third_party/QtWebApp/httpserver/httpconnectionhandler.h b/third_party/QtWebApp/httpserver/httpconnectionhandler.h index bf9bffac..fc03cc1d 100644 --- a/third_party/QtWebApp/httpserver/httpconnectionhandler.h +++ b/third_party/QtWebApp/httpserver/httpconnectionhandler.h @@ -20,7 +20,7 @@ namespace stefanfrings { /** Alias type definition, for compatibility to different Qt versions */ -#if QT_VERSION >= 0x050000 +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) typedef qintptr tSocketDescriptor; #else typedef int tSocketDescriptor; diff --git a/third_party/QtWebApp/httpserver/httpconnectionhandlerpool.cpp b/third_party/QtWebApp/httpserver/httpconnectionhandlerpool.cpp index f22eb087..56a15ec9 100644 --- a/third_party/QtWebApp/httpserver/httpconnectionhandlerpool.cpp +++ b/third_party/QtWebApp/httpserver/httpconnectionhandlerpool.cpp @@ -18,7 +18,7 @@ HttpConnectionHandlerPool::HttpConnectionHandlerPool(const QSettings *settings, this->sslConfiguration=NULL; loadSslConfig(); cleanupTimer.start(settings->value("cleanupInterval",1000).toInt()); - connect(&cleanupTimer, &QTimer::timeout, this, &HttpConnectionHandlerPool::cleanup); + connect(&cleanupTimer, SIGNAL(timeout()), SLOT(cleanup())); } @@ -77,7 +77,8 @@ void HttpConnectionHandlerPool::cleanup() { delete handler; pool.removeOne(handler); - qDebug("HttpConnectionHandlerPool: Removed connection handler (%p), pool size is now %i",handler,pool.size()); + long int poolSize=(long int)pool.size(); + qDebug("HttpConnectionHandlerPool: Removed connection handler (%p), pool size is now %li",handler,poolSize); break; // remove only one handler in each interval } } @@ -140,7 +141,7 @@ void HttpConnectionHandlerPool::loadSslConfig() sslConfiguration->setLocalCertificate(certificate); sslConfiguration->setPrivateKey(sslKey); sslConfiguration->setPeerVerifyMode(QSslSocket::VerifyNone); - sslConfiguration->setProtocol(QSsl::TlsV1SslV3); + sslConfiguration->setProtocol(QSsl::AnyProtocol); qDebug("HttpConnectionHandlerPool: SSL settings loaded"); #endif diff --git a/third_party/QtWebApp/httpserver/httpcookie.cpp b/third_party/QtWebApp/httpserver/httpcookie.cpp index f09a2c37..d85232e8 100644 --- a/third_party/QtWebApp/httpserver/httpcookie.cpp +++ b/third_party/QtWebApp/httpserver/httpcookie.cpp @@ -14,7 +14,9 @@ HttpCookie::HttpCookie() secure=false; } -HttpCookie::HttpCookie(const QByteArray name, const QByteArray value, const int maxAge, const QByteArray path, const QByteArray comment, const QByteArray domain, const bool secure, const bool httpOnly) +HttpCookie::HttpCookie(const QByteArray name, const QByteArray value, const int maxAge, const QByteArray path, + const QByteArray comment, const QByteArray domain, const bool secure, const bool httpOnly, + const QByteArray sameSite) { this->name=name; this->value=value; @@ -24,6 +26,7 @@ HttpCookie::HttpCookie(const QByteArray name, const QByteArray value, const int this->domain=domain; this->secure=secure; this->httpOnly=httpOnly; + this->sameSite=sameSite; this->version=1; } @@ -32,6 +35,7 @@ HttpCookie::HttpCookie(const QByteArray source) version=1; maxAge=0; secure=false; + httpOnly=false; QList list=splitCSV(source); foreach(QByteArray part, list) { @@ -76,6 +80,10 @@ HttpCookie::HttpCookie(const QByteArray source) { httpOnly=true; } + else if (name=="SameSite") + { + sameSite=value; + } else if (name=="Version") { version=value.toInt(); @@ -125,6 +133,10 @@ QByteArray HttpCookie::toByteArray() const if (httpOnly) { buffer.append("; HttpOnly"); } + if (!sameSite.isEmpty()) { + buffer.append("; SameSite="); + buffer.append(sameSite); + } buffer.append("; Version="); buffer.append(QByteArray::number(version)); return buffer; @@ -170,6 +182,11 @@ void HttpCookie::setHttpOnly(const bool httpOnly) this->httpOnly=httpOnly; } +void HttpCookie::setSameSite(const QByteArray sameSite) +{ + this->sameSite=sameSite; +} + QByteArray HttpCookie::getName() const { return name; @@ -210,6 +227,11 @@ bool HttpCookie::getHttpOnly() const return httpOnly; } +QByteArray HttpCookie::getSameSite() const +{ + return sameSite; +} + int HttpCookie::getVersion() const { return version; diff --git a/third_party/QtWebApp/httpserver/httpcookie.h b/third_party/QtWebApp/httpserver/httpcookie.h index f649f15f..f46cebd3 100644 --- a/third_party/QtWebApp/httpserver/httpcookie.h +++ b/third_party/QtWebApp/httpserver/httpcookie.h @@ -13,9 +13,8 @@ namespace stefanfrings { /** - HTTP cookie as defined in RFC 2109. This class can also parse - RFC 2965 cookies, but skips fields that are not defined in RFC - 2109. + HTTP cookie as defined in RFC 2109. + Supports some additional attributes of RFC6265bis. */ class DECLSPEC HttpCookie @@ -35,11 +34,13 @@ public: @param domain Optional domain for that the cookie will be sent. Defaults to the current domain @param secure If true, the cookie will be sent by the browser to the server only on secure connections @param httpOnly If true, the browser does not allow client-side scripts to access the cookie + @param sameSite Declare if the cookie can only be read by the same site, which is a stronger + restriction than the domain. Allowed values: "Lax" and "Strict". */ HttpCookie(const QByteArray name, const QByteArray value, const int maxAge, const QByteArray path="/", const QByteArray comment=QByteArray(), const QByteArray domain=QByteArray(), const bool secure=false, - const bool httpOnly=false); + const bool httpOnly=false, const QByteArray sameSite=QByteArray()); /** Create a cookie from a string. @@ -77,9 +78,15 @@ public: /** Set secure mode, so that the cookie will be sent by the browser to the server only on secure connections */ void setSecure(const bool secure); - /** Set HTTP-only mode, so that he browser does not allow client-side scripts to access the cookie */ + /** Set HTTP-only mode, so that the browser does not allow client-side scripts to access the cookie */ void setHttpOnly(const bool httpOnly); + /** + * Set same-site mode, so that the browser does not allow other web sites to access the cookie. + * Allowed values: "Lax" and "Strict". + */ + void setSameSite(const QByteArray sameSite); + /** Get the name of this cookie */ QByteArray getName() const; @@ -104,6 +111,9 @@ public: /** Get the HTTP-only flag of this cookie */ bool getHttpOnly() const; + /** Get the same-site flag of this cookie */ + QByteArray getSameSite() const; + /** Returns always 1 */ int getVersion() const; @@ -117,6 +127,7 @@ private: QByteArray path; bool secure; bool httpOnly; + QByteArray sameSite; int version; }; diff --git a/third_party/QtWebApp/httpserver/httpglobal.cpp b/third_party/QtWebApp/httpserver/httpglobal.cpp index d938a95c..a5b72a6a 100644 --- a/third_party/QtWebApp/httpserver/httpglobal.cpp +++ b/third_party/QtWebApp/httpserver/httpglobal.cpp @@ -2,6 +2,6 @@ const char* getQtWebAppLibVersion() { - return "1.7.11"; + return "1.8.3"; } diff --git a/third_party/QtWebApp/httpserver/httpglobal.h b/third_party/QtWebApp/httpserver/httpglobal.h index e7e856a9..4f499871 100644 --- a/third_party/QtWebApp/httpserver/httpglobal.h +++ b/third_party/QtWebApp/httpserver/httpglobal.h @@ -23,6 +23,5 @@ /** Get the library version number */ DECLSPEC const char* getQtWebAppLibVersion(); - #endif // HTTPGLOBAL_H diff --git a/third_party/QtWebApp/httpserver/httplistener.cpp b/third_party/QtWebApp/httpserver/httplistener.cpp index 768ab842..74871584 100644 --- a/third_party/QtWebApp/httpserver/httplistener.cpp +++ b/third_party/QtWebApp/httpserver/httplistener.cpp @@ -83,7 +83,7 @@ void HttpListener::incomingConnection(tSocketDescriptor socketDescriptor) { qDebug("HttpListener: Too many incoming connections"); QTcpSocket* socket=new QTcpSocket(this); socket->setSocketDescriptor(socketDescriptor); - connect(socket, &QAbstractSocket::disconnected, socket, &QObject::deleteLater); + connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater())); socket->write("HTTP/1.1 503 too many connections\r\nConnection: close\r\n\r\nToo many connections\r\n"); socket->disconnectFromHost(); } diff --git a/third_party/QtWebApp/httpserver/httprequest.cpp b/third_party/QtWebApp/httpserver/httprequest.cpp index 75642b90..c9294b7a 100644 --- a/third_party/QtWebApp/httpserver/httprequest.cpp +++ b/third_party/QtWebApp/httpserver/httprequest.cpp @@ -482,7 +482,8 @@ void HttpRequest::parseMultiPartFile() parameters.insert(fieldName,fileName); qDebug("HttpRequest: set parameter %s=%s",fieldName.data(),fileName.data()); uploadedFiles.insert(fieldName,uploadedFile); - qDebug("HttpRequest: uploaded file size is %lli",uploadedFile->size()); + long int fileSize=(long int) uploadedFile->size(); + qDebug("HttpRequest: uploaded file size is %li",fileSize); } else { diff --git a/third_party/QtWebApp/httpserver/httpsession.h b/third_party/QtWebApp/httpserver/httpsession.h index 35ed1f26..e9d40b04 100644 --- a/third_party/QtWebApp/httpserver/httpsession.h +++ b/third_party/QtWebApp/httpserver/httpsession.h @@ -43,7 +43,6 @@ public: */ HttpSession& operator= (const HttpSession& other); - /** Destructor. Detaches from the shared data. */ @@ -54,7 +53,7 @@ public: /** Null sessions cannot store data. All calls to set() and remove() - do not have any effect.This method is thread safe. + do not have any effect. This method is thread safe. */ bool isNull() const; diff --git a/third_party/QtWebApp/httpserver/httpsessionstore.cpp b/third_party/QtWebApp/httpserver/httpsessionstore.cpp index 3939aca4..123dea8a 100644 --- a/third_party/QtWebApp/httpserver/httpsessionstore.cpp +++ b/third_party/QtWebApp/httpserver/httpsessionstore.cpp @@ -13,7 +13,7 @@ HttpSessionStore::HttpSessionStore(const QSettings *settings, QObject* parent) :QObject(parent) { this->settings=settings; - connect(&cleanupTimer,&QTimer::timeout,this,&HttpSessionStore::sessionTimerEvent); + connect(&cleanupTimer,SIGNAL(timeout()),this,SLOT(sessionTimerEvent())); cleanupTimer.start(60000); cookieName=settings->value("cookieName","sessionid").toByteArray(); expirationTime=settings->value("expirationTime",3600000).toInt(); @@ -64,7 +64,8 @@ HttpSession HttpSessionStore::getSession(HttpRequest& request, HttpResponse& res QByteArray cookiePath=settings->value("cookiePath").toByteArray(); QByteArray cookieComment=settings->value("cookieComment").toByteArray(); QByteArray cookieDomain=settings->value("cookieDomain").toByteArray(); - response.setCookie(HttpCookie(cookieName,session.getId(),expirationTime/1000,cookiePath,cookieComment,cookieDomain)); + response.setCookie(HttpCookie(cookieName,session.getId(),expirationTime/1000, + cookiePath,cookieComment,cookieDomain,false,false,"Lax")); session.setLastAccess(); return session; } @@ -79,7 +80,8 @@ HttpSession HttpSessionStore::getSession(HttpRequest& request, HttpResponse& res HttpSession session(true); qDebug("HttpSessionStore: create new session with ID %s",session.getId().data()); sessions.insert(session.getId(),session); - response.setCookie(HttpCookie(cookieName,session.getId(),expirationTime/1000,cookiePath,cookieComment,cookieDomain)); + response.setCookie(HttpCookie(cookieName,session.getId(),expirationTime/1000, + cookiePath,cookieComment,cookieDomain,false,false,"Lax")); mutex.unlock(); return session; } @@ -111,6 +113,7 @@ void HttpSessionStore::sessionTimerEvent() if (now-lastAccess>expirationTime) { qDebug("HttpSessionStore: session %s expired",session.getId().data()); + emit sessionDeleted(session.getId()); sessions.erase(prev); } } @@ -122,6 +125,7 @@ void HttpSessionStore::sessionTimerEvent() void HttpSessionStore::removeSession(HttpSession session) { mutex.lock(); + emit sessionDeleted(session.getId()); sessions.remove(session.getId()); mutex.unlock(); } diff --git a/third_party/QtWebApp/httpserver/httpsessionstore.h b/third_party/QtWebApp/httpserver/httpsessionstore.h index de86ecd2..65fa2c92 100644 --- a/third_party/QtWebApp/httpserver/httpsessionstore.h +++ b/third_party/QtWebApp/httpserver/httpsessionstore.h @@ -112,6 +112,14 @@ private slots: /** Called every minute to cleanup expired sessions. */ void sessionTimerEvent(); + +signals: + + /** + Emitted when the session is deleted. + @param sessionId The ID number of the session. + */ + void sessionDeleted(const QByteArray& sessionId); }; } // end of namespace diff --git a/third_party/QtWebApp/httpserver/staticfilecontroller.cpp b/third_party/QtWebApp/httpserver/staticfilecontroller.cpp index 9510aec9..bafe4509 100644 --- a/third_party/QtWebApp/httpserver/staticfilecontroller.cpp +++ b/third_party/QtWebApp/httpserver/staticfilecontroller.cpp @@ -33,7 +33,8 @@ StaticFileController::StaticFileController(const QSettings *settings, QObject* p maxCachedFileSize=settings->value("maxCachedFileSize","65536").toInt(); cache.setMaxCost(settings->value("cacheSize","1000000").toInt()); cacheTimeout=settings->value("cacheTime","60000").toInt(); - qDebug("StaticFileController: cache timeout=%i, size=%i",cacheTimeout,cache.maxCost()); + long int cacheMaxCost=(long int)cache.maxCost(); + qDebug("StaticFileController: cache timeout=%i, size=%li",cacheTimeout,cacheMaxCost); } diff --git a/third_party/QtWebApp/templateengine/template.h b/third_party/QtWebApp/templateengine/template.h index 01716c53..d476fb3c 100644 --- a/third_party/QtWebApp/templateengine/template.h +++ b/third_party/QtWebApp/templateengine/template.h @@ -7,7 +7,6 @@ #define TEMPLATE_H #include -#include #include #include #include diff --git a/third_party/QtWebApp/templateengine/templatecache.cpp b/third_party/QtWebApp/templateengine/templatecache.cpp index e0f22bf5..60135f67 100644 --- a/third_party/QtWebApp/templateengine/templatecache.cpp +++ b/third_party/QtWebApp/templateengine/templatecache.cpp @@ -10,7 +10,8 @@ TemplateCache::TemplateCache(const QSettings* settings, QObject* parent) { cache.setMaxCost(settings->value("cacheSize","1000000").toInt()); cacheTimeout=settings->value("cacheTime","60000").toInt(); - qDebug("TemplateCache: timeout=%i, size=%i",cacheTimeout,cache.maxCost()); + long int cacheMaxCost=(long int)cache.maxCost(); + qDebug("TemplateCache: timeout=%i, size=%li",cacheTimeout,cacheMaxCost); } QString TemplateCache::tryFile(const QString localizedName) diff --git a/third_party/QtWebApp/templateengine/templateengine.pri b/third_party/QtWebApp/templateengine/templateengine.pri index 722c17fc..faca956a 100644 --- a/third_party/QtWebApp/templateengine/templateengine.pri +++ b/third_party/QtWebApp/templateengine/templateengine.pri @@ -1,6 +1,10 @@ INCLUDEPATH += $$PWD DEPENDPATH += $$PWD +greaterThan(QT_VERSION,6) { + QT += core5compat +} + HEADERS += $$PWD/templateglobal.h HEADERS += $$PWD/template.h HEADERS += $$PWD/templateloader.h diff --git a/third_party/QtWebApp/templateengine/templateloader.cpp b/third_party/QtWebApp/templateengine/templateloader.cpp index 2379755c..0db3115b 100644 --- a/third_party/QtWebApp/templateengine/templateloader.cpp +++ b/third_party/QtWebApp/templateengine/templateloader.cpp @@ -9,6 +9,12 @@ #include #include #include +#include +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + #include +#else + #include +#endif using namespace stefanfrings; @@ -35,8 +41,8 @@ TemplateLoader::TemplateLoader(const QSettings *settings, QObject *parent) else { textCodec=QTextCodec::codecForName(encoding.toLocal8Bit()); - } - qDebug("TemplateLoader: path=%s, codec=%s",qPrintable(templatePath),textCodec->name().data()); + } + qDebug("TemplateLoader: path=%s, codec=%s",qPrintable(templatePath),qPrintable(encoding)); } TemplateLoader::~TemplateLoader() @@ -67,13 +73,23 @@ QString TemplateLoader::tryFile(QString localizedName) Template TemplateLoader::getTemplate(QString templateName, QString locales) { QSet tried; // used to suppress duplicate attempts - QStringList locs=locales.split(',',QString::SkipEmptyParts); + + #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + QStringList locs=locales.split(',',Qt::SkipEmptyParts); + #else + QStringList locs=locales.split(',',QString::SkipEmptyParts); + #endif // Search for exact match foreach (QString loc,locs) { - loc.replace(QRegExp(";.*"),""); + #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + loc.replace(QRegularExpression(";.*"),""); + #else + loc.replace(QRegExp(";.*"),""); + #endif loc.replace('-','_'); + QString localizedName=templateName+"-"+loc.trimmed(); if (!tried.contains(localizedName)) { @@ -88,7 +104,11 @@ Template TemplateLoader::getTemplate(QString templateName, QString locales) // Search for correct language but any country foreach (QString loc,locs) { - loc.replace(QRegExp("[;_-].*"),""); + #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + loc.replace(QRegularExpression("[;_-].*"),""); + #else + loc.replace(QRegExp("[;_-].*"),""); + #endif QString localizedName=templateName+"-"+loc.trimmed(); if (!tried.contains(localizedName)) { diff --git a/third_party/QtWebApp/templateengine/templateloader.h b/third_party/QtWebApp/templateengine/templateloader.h index dd41fa53..faf24977 100644 --- a/third_party/QtWebApp/templateengine/templateloader.h +++ b/third_party/QtWebApp/templateengine/templateloader.h @@ -8,8 +8,8 @@ #include #include -#include #include +#include #include "templateglobal.h" #include "template.h"